|
Post by etienneb on Mar 13, 2017 2:49:57 GMT -8
Hi all, As part of my bachelor thesis I am trying to represent propositional logic and first order logic as a game using GDL. Unfortunately, I was not able to find much resources to get started learning GDL and I am struggling to advance. For now, I am trying to implement the rules of logic in GDL and I am focusing on very simple games. For example my game AndIntro starts with A and with B, has one move available: (<= (legal solver (conjunction ?x ?y)) (true ?x) (true ?y)) and the goal is to get (conjunction A B). In this case it might just be that the players I use to try it are dumb because the player only tries (conjunction (control solver) (control solver)). You can find the code here: vps1.piater.name/commie/#LdGefuH2I've also tried And elimination: vps1.piater.name/commie/#L3mMJSF7Implication elimination: vps1.piater.name/commie/#2l6gvNJhOr introduction: vps1.piater.name/commie/#0b5asX6iI imagine I made beginners mistakes that are quite simple to solve but if someone is able to help me with this, I would appreciate detailed explanation as I have little experience with GDL. Thank you in advance!
|
|
|
Post by alandau on Mar 13, 2017 23:43:17 GMT -8
First recommendation: You are currently getting your logic of interest intermixed with the logic of the game itself. I'd recommend separating it out, with an approach like this:
(init (known A)) (init (known B))
(<= (legal solver (conjunction ?x ?y)) (true (known ?x)) (true (known ?y)))
; Turn what the player does into more known facts (<= (next (known (conjunction ?x ?y))) (does solver (conjunction ?x ?y)))
; You'll need this if you want the things you know in one turn to stay known the next turn: (<= (next (known ?fact)) (true (known ?fact)))
|
|
|
Post by etienneb on Mar 14, 2017 2:10:36 GMT -8
I see! Thank you very much, that sounds like great advice! I will try to implement that as soon as I can
|
|
|
Post by etienneb on Mar 29, 2017 5:05:18 GMT -8
Thanks to your help I was able to progress quite a bit! Here is my game for AND introduction for example: vps1.piater.name/commie/#cj1QdUqJI have done a bunch more as well now but cannot find a way to implement boxes (like for -> introduction). The characteristics of a bow that I noticed are: 1. can be opened 2. can be closed 3. can open within another but cannot overlap 4. can access bigger/higher boxes' statements 5. first and last statements are used in the resolution So the idea I'm working on goes like this: We introduce 'assumption' for example: knonwn assumption A and we somehow prepend or append them to each other when opening a box within a box. For example: _________ | x | ... | _______ | | y | | formula then formula would be written something like: known assumption y assumption x formula Does this make sense? Is this a sensible way to go at this problem? And if yes, how would you implement it? Is there a way to prepend? Thank you in advance!
|
|
|
Post by alandau on Apr 2, 2017 23:41:25 GMT -8
Managing assumptions/boxes can get a little tricky; the tree structure goes beyond the types of geometric relationships found in most board games. It's probably going to involve recursion in some sense.
One restriction is that a given sentence name (or function name) is supposed to have a consistent number of arguments. (This is inconsistently enforced, but breaking it would make it difficult to write rules involving it anyway.) Technically, I think you could get around this with a "linked list" approach like (known (assumptions foo (assumptions bar (assumptions baz null))) formula), but this is unwieldy and would break a lot of players.
So it's probably better to break the information about assumptions out into multiple sentence types (like having multiple tables in a database). It would help to have some kind of "key" to "join" these sentences together on, to continue the database analogy. It might work if the key referred to the formula, but it would probably be easier to have it refer to the box (or set of assumptions).
So then you'd have something like (true (known box4 p)) along with (true (assumption box4 q)), (true (known box4 q)), and (true (boxIsInside box4 box2)). Say you also have (true (boxIsInside box2 box1)) and box1 is the starting point. (The proof isn't over until you've achieved (true (known box1 whateverYouWantToProve)).)
I assume the progress of the game from step-to-step is going down the list of statements in the proof, so we also have a box we're currently in, (true (currentBox box4)); and that would also handle the problem of how to exclude statements from box2 that occur after box4 is closed.
So then the statements we can access are those whose boxes we are in, which we can find with the help of recursion: (<= (accessible ?statement) (accessibleBox ?box) (true (known ?box ?statement))) (<= (accessibleBox ?box) (true (currentBox ?box))) (<= (accessibleBox ?outerBox) (true (boxIsInside ?innerBox ?outerBox)) (accessibleBox ?innerBox))
Meanwhile, opening and closing boxes would be moves and would need transitions that managed the state of e.g. currentBox and boxIsInside. (Note that you can only give the player a finite number of possible assumptions to make when opening a box...)
|
|
|
Post by etienneb on Apr 3, 2017 0:36:30 GMT -8
So I think I've found a satisfying solution to this problem. One quick question though. I have 2 things I initialise, known formulas (for example known A) and unknown ones but needed to solve the problem (for example formula B). Is there a way to tell the game controller or player that any known thing is also a formula?
Would (<= (formula ?x) (true (known ?x))) work if it is somewhere in the rules? Also how can I add that ?x should not be 'bottom'?
|
|
|
Post by etienneb on Apr 3, 2017 0:43:48 GMT -8
I actually had this window open for just over an hour and I didn't see your reply. The solution I'm going for at the moment has an 'assume A' to open a box and 'assumption A X' for what happens in the box. That leads, assuming it works as intended, to something like 'assumption (((A) B) C) X' down the line. That would be more like the list approach you say is unstable right?
|
|
|
Post by alandau on Apr 3, 2017 20:02:26 GMT -8
To answer your quick question:
The rule you stated would work fine. To exclude the case where ?x is "bottom", you use the "distinct" keyword:
(<= (formula ?x) (true (known ?x)) (distinct ?x bottom))
I'm not quite sure about the list approach you're mentioning. I'd probably have to see more of the rules involved.
|
|
|
Post by etienneb on Apr 4, 2017 4:20:21 GMT -8
Yes, sorry it's not very clear. Here is an example for -> intro, I haven't tested it yet but it's representative of the idea I'm going for atm. vps1.piater.name/commie/#kvTJybkbIt seems very similar to your idea of linked list unfortunately :/
|
|
|
Post by alandau on Apr 4, 2017 20:43:08 GMT -8
Right. The GGP-Base ProverStateMachine should be able to process it correctly, but faster methods of interpreting (such as propnets) will fail, so most highly competitive players won't be able to handle the game description. Whether that's a problem or not depends on your research goals.
|
|
|
Post by etienneb on Apr 9, 2017 23:36:36 GMT -8
I see. Testing the game with the best players is a side goal so I might have to rewrite this. Thanks.
|
|
|
Post by etienneb on Apr 10, 2017 8:21:08 GMT -8
Follow up to my previous quick question. I'm using this: (<= (formula ?f) (or (true (known ?f)) (true (assumption ?a ?f))) (distinct ?f bottom) ) in order to make anything a formula but it doesn't seem to work. I made a game starting with (known (conjunction A A)) and the rules for opening boxes as well as Conjunction elimination. The goal was to find (known (implies A A)) but the player played only the conjunction elimination. Opening a box is done from a formula: (<= (legal solver (assume ?x null)) (true (formula ?x)) ) (<= (legal solver (assume (negated ?x) null)) (true (formula ?x)) ) and when I added the line (init (formula A)) the player was then able to solve it. What do you think is wrong with my way of making formulas automatically? This is a link to the whole game: vps1.piater.name/commie/#bZ66GvzkAlso is there a way to prevent player from playing the same move again and again? I tried (<= (legal solver (known ?x)) (true (known (conjunction ?x ?y))) (not (known ?x))) to indicate that this move is redundant if ?x is already known but it didn't work. Thanks for your help.
|
|
|
Post by alandau on Apr 11, 2017 19:32:45 GMT -8
I notice that in those rules, you are using both (true (formula _)) and (formula _) as sentence types. These do not mean the same thing, and should not be included in the same game, to avoid confusion. There are really two types of sentences; "true" was perhaps a poor choice of keyword, as it means something closer to "state". Sentences with the names "true", "init", and "next" deal with the state of the game, while sentences lacking that are part of the game logic within a given turn.
If you want something that expresses all the types of formulas that could exist, you normally want this to be a bit of logic that is separate from the game state. (That is, use "(formula _)" and not "(true (formula _))".) For example, tic-tac-toe uses an (index _) sentence to indicate 1, 2, and 3 as the possible x- or y-coordinates. Chess similarly has (rank _) and (file _) sentences for this. It would probably be helpful to have (proposition p), (proposition q), etc. as a starting point, listing the individual claims that might be assumed to be true or false.
For the rule at the end, (not (known ?x)) should be (not (true (known ?x))).
(Extra note: You don't need to include "control" state if it remains the same every turn. It has no meaning beyond how it is used elsewhere in a game description.)
|
|
|
Post by etienneb on Apr 13, 2017 0:44:11 GMT -8
I think I get it. This is what I did: I can got rid of (init (formula A)) as well as (<= (next (formula ?formula)) (true (formula ?formula)) )
because it is out of the game state. While the moves involving formula become
(<= (legal solver (assume ?x null)) (formula ?x) )
But
(<= (formula ?f) (or (true (known ?f)) (true (assumption ?a ?f))) (distinct ?f bottom) ) doesn't change. That worked really well! I also got rid of
(<= (next (control solver)) (true (control solver)) )
without any issues. Thanks!
In the discussion we had earlier about boxes, can you please explain to me why propnets would not be able to interpret the list solution? I will start to implement your version of boxes now that the list version seems to work fine.
|
|
|
Post by etienneb on Apr 17, 2017 1:52:55 GMT -8
So I've been trying to implement the idea of recursive boxes and I ran into some issues. The main one is to do with the naming of the boxes: box1, box2 and so on. Is there a way to do that automatically? as in: (<= (legal solver (assumption "boxName" ?a)) (formula ?a) (true (currentBox ?box)) ) how could I declare "boxName" to be the next after box3 for example? Also in the rule: (<= (accessibleBox ?outerBox) (true (boxIsInside ?innerBox ?outerBox)) (accessibleBox ?innerBox) ) the gdl syntax parser for eclipse says that the last line violates the recursion restriction. I have tried to make a few rules for this way of making boxes and can see it here: vps1.piater.name/commie/#nJDFyzo0Thank you in advance!
|
|