jgraley / inferno-cpp2v

2 stars 0 forks source link

Fix cache to cache by child X and not link #194

Closed jgraley closed 3 years ago

jgraley commented 3 years ago

Output from sctest13 (XLINK_BY_ARROWHEAD and CHECK_LINKS_COMPARISON defined):

003)}>CR ----ASSERTION FAILED: (XLink)alink == (XLink)rlink
003)}>CR ----src/sr/agents/agent.cpp:157 in ResumeNormalLinkedQuery()
003)}>CR Found conflicting X links for &Agent<Integral>#P-94-0
003)}>CR Actual   0x2e4fa68->Agent<Integral>#P-94-0@5BF776:=0x3313fb0~>Signed#2-274-2983@5BEFDC
003)}>CR Required 0x2e4fa68->Agent<Integral>#P-94-0@5BFB49:=0x331fbe0~>Signed#2-274-2983@5BEFDC
003)}>CR TransformOfAgent's cache {0x330a8d0~>SpecificInstanceIdentifier('i')#I-216-20@86EC11: 0x3313fb0~>Signed#2-274-2983@5BEFDC, 0x330ba60~>SpecificInstanceIdentifier('i')#I-216-20@86EC11: 0x331fbe0~>Signed#2-274-2983@5BEFDC}

sctests 11, 12 and pointeris all passed, so this looks quite "niche". I think it would be wise to look into why the incoming links differ before concluding that the cache is broken.

jgraley commented 3 years ago
003)}>CR ----ASSERTION FAILED: (XLink)alink == (XLink)rlink
003)}>CR ----src/sr/agents/agent.cpp:157 in ResumeNormalLinkedQuery()
003)}>CR Found conflicting X links for &Agent<Integral>#P-94-0
003)}>CR Actual   0x2d419f8->Agent<Integral>#P-94-0@5BF776:=0x31c1580~>Signed#2-268-2983@5BEFDC
003)}>CR Required 0x2d419f8->Agent<Integral>#P-94-0@5BFB49:=0x32065f0~>Signed#2-268-2983@5BEFDC
003)}>CR TransformOfAgent's cache 
{
    0x31fbd70~>SpecificInstanceIdentifier('i')#I-216-20@86EC11: 0x31c1580~>Signed#2-268-2983@5BEFDC, 
    0x31fcf00~>SpecificInstanceIdentifier('i')#I-216-20@86EC11: 0x32065f0~>Signed#2-268-2983@5BEFDC
}
Aborted (core dumped)
jgraley@ike:~/inferno-cpp2v$ addr2line
5BEFDC
/home/jgraley/inferno-cpp2v/src/sr/agents/transform_of_agent.cpp:29
            return XLink::CreateDistinct(xt);  // Cache will un-distinct
5BF776
/home/jgraley/inferno-cpp2v/src/sr/agents/transform_of_agent.cpp:38 (discriminator 5)
    query.RegisterNormalLink( PatternLink(this, &pattern), cache( x, op ) );    
5BFB49
/home/jgraley/inferno-cpp2v/src/sr/agents/transform_of_agent.cpp:10
    pq->RegisterNormalLink( PatternLink(this, &pattern) );
86EC11
/home/jgraley/inferno-cpp2v/src/sr/agents/standard_agent.cpp:208 (discriminator 4)
            query.RegisterNormalLink( PatternLink(this, &*pit), XLink(base_x.GetChildX(), &*xit) ); // Link into X
jgraley commented 3 years ago

StandardAgent::NLQ() saw:

In the TransformOfAgent cache:

jgraley commented 3 years ago

This TransformOf is probably really a TypeOf: Signed is probably the type of the SpecificInstanceIdentifier('i'). The cache, because it is caching by X link thinks that two of the different links into the Identifier should have two different links into the Signed node as well.

jgraley commented 3 years ago

Went wrong in step 3: DetectCombableFor

See how the TypeOf on the right is pre-restricted as an Identifier and has a truly massive number of incoming pattern links (so it is also a coupling).

And since it is a type-of, it has a link to a type node, Integral, which the Signed will be matched against.

jgraley commented 3 years ago

Full arrow head model is based on the invariant that X links are unique in any kind of tree walk, so that orderings over domain are well-defined.

The TypeOf type Signed appears to be a child of the Identifier. Why? because

         TypeOfAgent                   ->                Agent<Integral>
             ..                                               ..
             ||                                               ||
SpecificInstanceIdentifier('i')                             Signed

but Signed is no child of SpecificInstanceIdentifier(). In particular, a Stuff node somewhere above may find the SpecificInstanceIdentifier('i') but will not find any Signed under it or indeed anything at all.

jgraley commented 3 years ago

The current general plan is that nodes like Signed in the above, which have been called "local" or "Y" nodes are added to the domain as new root nodes (TypeOf is cabable of returning a subtree for the type, which would remain intact).

From the POV of couplings to the type pattern (the Integral agent in this case), this matters not a jot, and if the Y subtree was actually found in the original X tree, it can still be copied out into new domain values, because couplings operate by equivalance and disparate X links can still be found to be successfully coupled. So couplings are not a problem here.

Question remains, with couplings to the type pattern not being a problem, why if at all should it be necessary for these cache lines to coalesce (eg by caching against X node rather than X link)?

They reached NLQ() as required and actual, and NLQ() works by X link identity (this is important).

jgraley commented 3 years ago

It's something like this: you don't notice that the Identifier X node has many parents if you're not coupling it: each match will follow only one path into the Identifier and so the Identifier only ever has to be reached through one X link. This X link can proxy for the Identifier and the whole problem can by solved by-XLink.

When we do couple the Identifier, we'll reach the Identifier via multiple paths. But the coupling logic (by equivalence) takes care of the differing XLinks and still allows a match.

Identifiers do not have children. However, agents like TypeOf can be applied to it and will generate new nodes. But these will not be compared by equivalence, and so we need to coalesce them.

jgraley commented 3 years ago

I think the real answer is to ensure that we only ever progress past an agent's coupling compare into DQ(), NLQ() on keyers, not residuals.

Eliminating residuals from regeneration fixes this: the XLink in question is now only ever the keyer.

We will also need to remember to only use the keyer X link in the CSP also.

At root it's this: consider a coupled agent A with child agents. There will be many arrowheads coming in but only one going out. There are no variable for the agents themselves. So we need a correspondance between the many links coming into A and the one that comes out. This shall be: use the keyer.

After that, what we cache by won't really matter: incoming keying xLinks are 1:1 with the X nodes they point to.