Hello everyone and thanks for your time, unfortunately i almost out of time due to graduation deadlines...
As Nil reminds me, atomspace is used as immutable data storage. I always knew this but I realized late what it means on a practical level... I tried to use it dynamically, adding and removing atoms during the reasoning. I think this is the biggest mistake that didn't allow me to get to a solution with backwards chaining. Responding to Nil's proposals: 1. I think temporal reasoning is the most correct way .. and it would come close to the ROCCA model (the one you presented in a meeting some time ago), if I'm not mistaken. 2. I tried some solutions describing each state explicitly but (now I don't remember well) the problem was the lack of generality of the rules (probably my lack of knowledge didn't allow me to generalize them properly) ... As I write this, new solutions are coming to my mind and I would really like to have the time to try them all. Anyway, I don't know why, I never considered inferring action rather than cubes... although, it's logically obvious! In conclusion, a few days ago I talked to Adrian Borucki (I hope I'm not wrong) and I tried a step-by-step approach... so, I run one rule at a time and the effects are applied in the atomspace. Ok.. it works, of course. I wrote breadth-first tree expansion algorithm, which starts from the initial arrangement and tries all available actions, for each result it creates a new node of the tree (and apply the effect of that action in its atomspace) and repeats until reaching the goal. I don't think it's the correct way to use the atomspace but with the rules I had written, my previous knowledge and lack of time, I couldn't do better. Unfortunately, I rely on the university's private Ros codes for the first part of the project, which I cannot disclose. Within the next 2 weeks (or a little more) I should be able to replace them with a fake code and therefore makes everything open source For now I think to keep this way... but after graduation, maybe I will implement one of the correct approaches! It has become a personal challenge! Thanks again for your availability! Michele Il giorno giovedì 26 agosto 2021 alle 18:40:37 UTC+2 linas ha scritto: > I've been travelling, and will try to read and write a response "real soon > now" (next few days). > > --linas > > On Sat, Aug 14, 2021 at 9:36 AM Michele Thiella <[email protected]> > wrote: > >> Hello everyone, >> I will try to explain in a simple way: >> >> 1) my problem and my goal >> 2) the possible solutions >> 3) errors/shortcomings found and extra questions encountered along the way >> >> >> *1) The Problem:* >> >> Let's start from scratch. My problem is based on the classic problem >> called "blocksworld problem". That is: >> >> - there is a robot manipulator that has 4 actions available: >> pickup, putdown, stack, unstack. >> >> - there are blocks on a table >> >> - there is a goal to be achieved >> >> *The Goal: * >> I am trying to solve any possible arrangement of the blocks. So my work >> aims to take as input a final arrangement of the blocks and >> through backward inference, obtain the derivation tree to reach that >> arrangement, through the 4 actions mentioned above. >> (I'll explain better later) >> >> >> *The construction of the problem:* >> >> - each block can be "clear", ie. the robot can take it >> (it is not clear to me if the vice versa "not-clear" is also necessary) >> >> - the robot hand may be "busy": so it is holding a block. Or "free": it >> has nothing in its hand >> >> - the 4 actions: >> >> 1) pickup: >> - preconditions: "clear" block, "on-table" block and "free" (robot) >> hand >> - effects: "not-clear" block, "in-hand" block and "busy" hand >> >> 2) putdown: >> - preconditions: "not-clear" block, "in-hand" block and "busy" hand >> - effects: "clear" block, "on-table" block and "free" hand >> >> 3) stack: >> - preconditions: block1 "in-hand", block2 "clear" and "busy" hand >> - effects: block2 "not-clear", block1 "on" block2, block1 "clear" >> and hand "free" >> >> 4) unstack: >> - preconditions: block2 "not-clear", block1 "on" block2, block1 >> "clear" and hand "free" >> - effects: block1 "in-hand", block2 "clear" and "busy" hand >> >> Basically the 4 actions mirror physics. >> Eg. If I want to take a block from the table, the block must be free >> ("clear") and my hand must be free. >> If block A is "on" block B then I can "unstack" block A and then make >> block B "clear" and having block A in hand. >> >> Obviously the pickup action is the opposite of putdown and are used to >> take/place a block from/on the table. >> The stack action is the opposite of unstack and are used to put/take a >> block on/from another block. >> >> I hope the introduction to the problem is complete enough. >> >> *2) Implementation:* (note that I'm looking for an Atomese-pure >> implementation) >> >> - Initial Set in the atomspace: >> An external algorithm detects all the blocks present on the table >> (for now the initial arrangement of the blocks does not have any blocks >> on top of another, as the detection of the blocks is done through Apriltag >> and therefore I would not be able to find the blocks placed under others. >> If I have time I will solve this problem using PointCloud. >> This is to say that my initial block arrangement can be any. >> Eg. 4 blocks: >> - A on B on C, D on table >> - A on D, B on C >> - A, B, C, D on table >> - and so on ... >> ) >> >> So my atomspace will be about: >> >> (SetLink >> ; block1 >> (InheritanceLink (stv 1 1) >> (ConceptNode "block1") >> (ConceptNode "object")) >> >> (EvaluationLink (stv 1 1) >> (PredicateNode "clear") >> (ConceptNode "block1")) >> >> ; block2 >> ; .... >> >> ; differentiate the various blocks >> (NotLink (EqualLink (ConceptNode "block1") (ConceptNode "block2"))) >> ) >> >> - Goal Implementation: >> it completely depends on how the model is formulated. >> If you look for a state resolution (finite state machine type) the goal >> will be formulated as one of them. >> Alternative: in the end, each block will always be on top of something >> (table or other block) so a possible goal formulation would be like: >> >> (define (compute) >> (define goal-state >> (AndLink >> (ListLink >> (VariableNode "$ A") >> (VariableNode "$ B") >> ) >> (ListLink >> (VariableNode "$ B") >> (VariableNode "$ C") >> ) >> (NotLink (EqualLink (VariableNode "$ A") (VariableNode "$ B"))) >> (NotLink (EqualLink (VariableNode "$ A") (VariableNode "$ C"))) >> (NotLink (EqualLink (VariableNode "$ B") (VariableNode "$ C"))) >> ) >> ) >> (define vardecl >> (VariableList >> (TypedVariableLink >> (VariableNode "$ A") >> (TypeNode "ConceptNode")) >> (TypedVariableLink >> (VariableNode "$ B") >> (TypeNode "ConceptNode")) >> (TypedVariableLink >> (VariableNode "$ C") >> (TypeNode "ConceptNode")) >> (TypedVariableLink >> (VariableNode "$ D") >> (TypeNode "ConceptNode")) >> ) >> ) >> (cog-bc rbs goal-state #: vardecl vardecl) >> ) >> >> - Rules for inference: >> Same considerations made for the formulation of the goal. >> Let's start with the rules corresponding to the 4 robot actions and leave >> out extra rules. >> If we rely on the definition above, then for example the stack rule would >> be something like: >> >> (define stack >> (BindLink >> (VariableList >> (TypedVariableLink (VariableNode "?ob") (TypeNode "ConceptNode")) >> (TypedVariableLink (VariableNode "?underob") (TypeNode >> "ConceptNode")) >> ) ; parameters >> (PresentLink >> (NotLink >> (EqualLink (VariableNode "?ob") (VariableNode "?underob"))) >> (InheritanceLink >> (VariableNode "?ob") >> (ConceptNode "object")) >> (InheritanceLink >> (VariableNode "?underob") >> (ConceptNode "object")) >> (AndLink >> (EvaluationLink >> (PredicateNode "in-hand") >> (VariableNode "?ob")) >> (EvaluationLink >> (PredicateNode "clear") >> (VariableNode "?underob")) >> ) >> ) >> (ExecutionOutputLink >> (GroundedSchemaNode "scm: stack-action") >> (ListLink >> ; effect: this represent ?ob "on" ?underob >> (ListLink >> (VariableNode "?ob") >> (VariableNode "?underob") >> ) >> ; precondition >> (AndLink >> (EvaluationLink >> (PredicateNode "in-hand") >> (VariableNode "?ob")) >> (EvaluationLink >> (PredicateNode "clear") >> (VariableNode "?underob")) >> ) >> ) >> ) >> ) >> ) >> >> >> *3)* Before talking about the problems that this writing (and the >> state-based alternative) has, I would like to talk about backward inference. >> >> Probably the implementation and functioning of URE is my biggest >> shortcoming >> and also the reason why I don't find the right way to formulate and solve >> this problem. Some questions: >> >> 3.1) I've always seen backward inference work via BindLink and >> VariableNode. I have no idea if there is an alternative/better way to do it. >> >> 3.2) As Linas mentioned, BindLink requires PresentLink and this is one of >> the biggest problems. >> By backward inference the rules are called and combine into a large >> BindLink and the same is true for the PresentLink. >> In the end, you get a large PresentLink made up of all the PresentLinks >> of the called rules. >> This means that for example I cannot use atoms like >> >> ; atom [0] >> (EvaluationLink >> (PredicateNode "clear") >> (VariableNode "? Ob")) >> ; atom [1] >> (EvaluationLink >> (PredicateNode "not-clear") >> (VariableNode "? Ob")) >> >> because it doesn't make sense that the same block is both "clear" and >> "not-clear". >> >> ---------------------- >> PS. this leads to another question: is what I am saying correct? I'll >> explain: >> Suppose I have 2 rules. One has the atom [0] in the PresentLink and the >> other has the atom [1]. >> Suppose the rules are called in succession from backward inference. >> When is PresentLink evaluated? From what I've seen: >> >> 1) the two rules compose the new BindLink, containing the PresentLink of >> both (which I think is the "Expanded forward chainer strategy") >> 2) The BindLink is evaluated and then the solutions are found or not >> (which I think is the "Selected and-BIT for fulfillment") >> >> Then, only at the end, the PresentLink is evaluated, this implies that >> both atoms [0] and [1] must be present together in the atomspace. >> >> This is incorrect: "The PresentLink of each rule is evaluated when that >> rule is called." Right? >> ---------------------- >> >> That said, it wouldn't seem like a problem. Instead it is, >> because it means that once the rule writes a new atom into the atomspace >> then that atom will always be present and therefore the rule that uses >> that atom as a precondition can be called whenever it wants. >> Consequently , in example: >> >> - blocks A, B, C >> - initial arrangement: A "on" B, C on the table >> - goal: Variable ?ob "on" Variable ?underob >> >> Consequently, for example, the use of certain atoms is no longer good for >> trying to follow the physics of actions >> (eg hand- "busy" and hand- "free": I can only take an object if my hand >> is free). >> The two atoms will always appear in the PresentLink and therefore, after >> doing a "pickup" and a "putdown", >> I can do two "pickups" in a row without worrying about having to put the >> object down first. >> So, you don't understand anything. >> But essentially the presence of certain atoms to limit the solutions to >> only physically correct sequences of actions does not work (or at least I >> have not been able to find a logic that fits). >> >> >> 3.3) Mirror problem with unstack rule: >> >> First let's take a step back: >> >> - blocks A, B, C >> - initial arrangement: A, B, C on the table >> - goal: >> (AndLink >> (ListLink >> (VariableNode "?ob") >> (VariableNode "?underob") >> ) >> (NotLink (EqualLink (VariableNode "?ob") (VariableNode >> "?underob"))) >> ) >> >> >> Backward inference could call the following rules in order: (conjunction >> joins two Links in a AndLink) >> >> (goal) <- conjunction <- stack <- conjunction <- pickup <- (init-set) >> >> >> >> (EvaluationLink (PredicateNode "clear")(VariableNode "?ob")) >> >> ----------------------------------------pickup-action---------------------------------------- >> (EvaluationLink (PredicateNode "in-hand") (VariableNode "?ob")) >> (EvaluationLink (PredicateNode >> "clear")(VariableNode "?underob")) >> >> ==========================================================conjunction============================================================ >> >> (AndLink >> >> (EvaluationLink >> >> (PredicateNode "in-hand") >> >> (VariableNode "?ob")) >> >> (EvaluationLink >> >> (PredicateNode "clear") >> >> (VariableNode "?underob")) >> >> ) >> ------------------------------------------------------------------------------------------------------- >> >> stack-action ---------------------------------- >> >> (ListLink >> >> (VariableNode "?ob") >> >> >> (VariableNode "?underob") >> (NotLink (EqualLink (VariableNode >> "?ob") (VariableNode "?underob"))) >> >> ==========================================================conjunction========================================================================================= >> >> (AndLink >> >> (ListLink >> >> (VariableNode "?ob") >> >> (VariableNode "?underob") >> >> ) >> >> (NotLink (EqualLink (VariableNode >> "?ob") (VariableNode "?underob"))) >> >> ) >> >> >> and returns as a solution all the combinations of the 3 blocks one above >> the other two by two. >> This is great, but analyzing the rules, then "unstack" would be of the >> form: >> >> >> >> (ListLink >> >> (VariableNode "?ob") >> >> (VariableNode "?underob") >> ----------------------------------------------------------------------------------------------------------------- >> >> unstack-action >> ----------------------------------------------------------------------------------------------------------------- >> >> (AndLink >> >> (EvaluationLink >> >> (PredicateNode "in-hand") >> >> (VariableNode "?ob")) >> >> (EvaluationLink >> >> (PredicateNode "clear") >> >> (VariableNode "?underob")) >> >> ) >> >> >> and now the trouble begins, because, as for the conjunction rule used for >> stack, then I need a disjunction for unstack rule, >> >> >> (AndLink >> >> (EvaluationLink >> >> (PredicateNode "in-hand") >> >> (VariableNode "?ob")) >> >> (EvaluationLink >> >> (PredicateNode "clear") >> >> (VariableNode "?underob")) >> >> ) >> >> ==========================================================disjunction============================================================ >> (EvaluationLink (PredicateNode "in-hand") (VariableNode "?ob")) >> (EvaluationLink (PredicateNode >> "clear")(VariableNode "?underob")) >> >> >> Which from what I know is not possible to have because there is always a >> single atom as an effect and a single atom as a precondition. >> But there should be something like the composition rule: >> >> Γ′⊢ψ Γ, ψ, Γ ”⊢ ∇ >> -------------------------------------------------- >> Γ, Γ ′, Γ′′⊢ ∇ >> >> >> >> >> 3.4) Finally, the last and I think the most important question: let's try >> to work by states. >> Well, I have tried many ways and I have not succeeded in any. >> Basically I found some shortcomings rather than logical errors. >> >> As has been said, the number of states for this problem is large to have >> them all in the atomspace (especially if we use a lot of blocks) and a >> waste because, based on the goal, 3/4 of the states would be useless. >> >> So there are 2 ideas (always in Atomese-pure): >> >> 1) Find a rule that takes in (precondition) a state and an action and >> returns (effect) a new state. >> >> 2) Find 4 rules (one for each action) that take in (precondition) a state >> and return (effect) a new one. >> >> So, first of all: >> >> - I could not give as a precondition: the last state created. >> The preconditions and effects of the rules are non-generic atoms. The >> only possibility I had thought was to have the input state as VariableNode, >> so that with fulfillment it would try all the atoms that represented my >> states. >> But this is not good because maybe after n actions, instead of taking the >> n-th state and creating the n + 1-th state, it could take the i-th state >> and create the n + 1-th state. And of course it is wrong because the i-th >> state is old and the layout of the blocks has certainly changed. (I hope >> it's clear enough) >> >> This led me to think that StateLink was a good atom for this purpose. >> - StateLink is unique, so it's fine as a precondition of my rule because >> it will definitely always represent the current situation of my blocks. >> Yet when I get a sequence of states as a solution to my inference, then >> in the PresentLink of my final BindLink all these states are required to be >> present in the atomspace. And this does not work (always confirming my >> initial assumption that the presence in the atomspace of the atoms >> contained in the PresentLink is verified at the time of fulfillment and not >> at the call of each rule), because all the StateLinks prior to the last one >> no longer exist, for StateLink definition. >> >> - I tried associating a Floats Value to the StateLink to represent the >> state of each block, so for example for each block one bit for "clear" / >> "not-clear", one bit for "in-hand" / "not-in -hand ", etc ... >> The idea was to change the status bits of an object as a rule was called >> on that object. >> I guess that's not good because: >> - either the bits of the Value are the precondition and the effect of >> the rule, or the inference does not perceive their change during the calls >> of the various rules (if for example the flips of the bits occur in the >> GroundedSchemaNode) >> - even if the bits of the Value were the precondition and the effect >> of the rule, there would still be the PresentLink problem. So once I have >> created the "can-pickup" state of block A, it will always be usable because >> it is inserted in the atomspace, even when A is no longer "pickable". >> >> >> >> >> >> *4) Conclusions:* >> I think something is missing from the current system to solve this >> problem (or I need some advice because I can't do it in any way) >> >> - The idea is a StateLink which however does not delete its old state but >> which keeps it in the atomspace. But somehow it can be called generically >> as a precondition of the rules, and this generic call always refers to the >> last StateLink created. (I saw that there was an obsolete atom: LatestLink, >> which maybe took over part of this operation) >> >> So the operation would be (call this new atom LatestStateLink): >> >> (define choose-action >> (BindLink >> (VariableList >> (TypedVariableLink (VariableNode "?ob") (TypeNode "ConceptNode")) >> ) >> (PresentLink >> (InheritanceLink >> (VariableNode "?ob") >> (ConceptNode "object")) >> >> (LatestStateLink "actual_state" >> (ListLink (ConceptNode "?ob") (PredicateNode "state")) >> (FloatValue 0 1 0 .....) >> ) >> >> ) >> (ExecutionOutputLink >> (GroundedSchemaNode "scm: action") >> (ListLink >> ; effect: >> (LatestStateLink "actual_state" >> (ListLink (ConceptNode "?ob") (PredicateNode "state")) >> (FloatValue 1 1 1 .....) >> ) >> ; precondition >> (LatestStateLink "actual_state" >> (ListLink (ConceptNode "?ob") (PredicateNode "state")) >> (FloatValue 0 1 0 .....) >> ) >> ) >> ) >> ) >> ) >> >> This is very similar to StateLink except for the name given to >> LatestStateLink. The idea is that the precondition for this rule is to >> check only the last state relative to the ?ob block and not the previous >> ones as well. If the last state, which I named "actual_state", has the >> FloatValue corresponding to the required ones then the rule can be >> called, otherwise not. >> >> When the rule is called the effect is written on the atomspace and then a >> new LatestStateLink "actual_state" is added and the previous >> LatestStateLink is left in the atomspace losing the name (so that you have >> one and only one "actual_state"). >> >> By doing this, it is possible to write rules in a generic way that >> respect the physics of actions and function in states. >> it's just a draft it will probably have other errors but it was one of >> the ideas that came to me. >> >> Unfortunately I haven't even looked at the C ++ implementation part of >> the Atom and their types. So for "code additions" of this type I think I >> don't have the time to get by, understand how the C ++ part works and write >> the code correctly and completely. >> >> >> This is all I have managed to write. I'm sorry it's so long and I >> apologize for the many unclear parts and logical and grammatical errors. >> For those who like it, happy reading! >> >> Michele >> >> -- >> > You received this message because you are subscribed to the Google Groups >> "opencog" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected]. >> > To view this discussion on the web visit >> https://groups.google.com/d/msgid/opencog/c9d4af3c-3117-4ea0-8cd2-bb885f108e1cn%40googlegroups.com >> >> <https://groups.google.com/d/msgid/opencog/c9d4af3c-3117-4ea0-8cd2-bb885f108e1cn%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > > > -- > Patrick: Are they laughing at us? > Sponge Bob: No, Patrick, they are laughing next to us. > > > -- You received this message because you are subscribed to the Google Groups "opencog" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/opencog/01eedcde-0a95-4e4e-b0ad-65ffe98dca45n%40googlegroups.com.
