sleyzerzon / soar

Automatically exported from code.google.com/p/soar
1 stars 0 forks source link

epmem episodes can contain disconnected structures #155

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
This was discussed over email; discussion copied below in chronological order. 
Nate created an example that can reproduce the problem (attached).

-------------------------

Hi guys,

I'm using epmem on a project, and I noticed that when I epmem --print episodes, 
they contain a lot of stuff that isn't actually connected to the episode. 
Here's a made up example (unfortunately, I can't share the real example):

(<id0> ^foo bar) # this is the top state and is part of the episode
(<id1> ^disconnected true) # this is just floating out there, not connected to 
the episode

It actually seems that after the system has been running for a while, these 
disconnected bits account for the majority of the episode size. Is this 
expected? Is there anything I can do about it? Does it affect performance 
(e.g., do these disconnected bits get reconstructed)?

Note that I'm using exclusions in an attempt to lower reconstruction costs, in 
case that matters.

Thanks!
Bob 

-------------------------

Hi Bob,

Disconnected subgraphs are definitely not expected behavior and, while
they should not lead to *incorrect* reconstructions, they will likely
lead to performance issues, depending on relative frequency (adding to
the number of intervals will slow down searches of the interval tree;
also, reconstruction is linear in the number of found intervals/WMEs,
even if they aren't put into working memory).

Not knowing anything about your situation, I am strongly suspicious
that this is interaction between exclusions (admittedly a hack) and
the change-based storage that Justin and I wrote (i.e. storage doesn't
perform a breadth-first scan of working memory from top state, but
instead lets the rete tell it about WME additions/removals and mirrors
them to epmem; it's much better for agents with big working memories).
I seem to recall that this type of situation can occur if substructure
is "moved" between excluded and not excluded portions of working
memory, which ends up fooling the change-based storage, something like
(excuse the notation)...

T1: add (S1 ^excluded E1) (E1 ^foo F1) (F1 ^bar baz)
T2: add (S1 ^scary F1)

I feel like we dealt with this exact situation, wherein an edge case
might not have (F1 ^bar baz) encoded in epmem because it is not a new
WME at the time that it is "connected" to a part of working memory not
under exclusion. However, there is likely an analogous bug that could
lead to disconnected subgraphs (something like... add substructure to
some identifier on state, then use a shared identifier to connect it
to an excluded region, and snip its old connection to state - thus
epmem will know it's still in working memory, but not know how). This
seems very likely, because (a) I'm not sure how we would detect such a
situation and (b) what is the correct storage policy for epmem if we
could detect it (e.g. pretend that it was removed from state and add
it again if it was reconnected in the future?).

Nate

-------------------------

Hi Nate,

I think you've hit the nail on the head. We have objects in working memory that 
have multiple paths leading to them. At least one of these paths is excluded. I 
believe the sequence is:

1. Add object to input-link
2. Add pointer to object in main working memory using path that is not excluded
3. Add pointer to object in main working memory using path that is excluded 
(likely finding the object via non-excluded path, not by looking directly on 
input-link)
4. Remove object from input-link and non-excluded path in main working memory, 
but keep it in excluded path in main working memory.

So the only additional twist here is that the objects are composed (mostly) of 
input wmes (some non-input wmes may also be added by the agent). After a while, 
these disconnected objects account for >90% of the episode wmes.

We intend to clean up the objects from the excluded path as well, so perhaps 
this problem will go away for us when we do that. It would be nice if this 
problem didn't exist at all, but as you point out, it's not clear what the 
intended behavior is. I think treating objects that re-enter a non-excluded 
part of working memory should be a new interval, as if they were just added to 
working memory, because, from the perspective of the episodes, they did just 
enter working memory.

Thanks!
Bob

-------------------------

Attached is a simple test case (woohoo I can still write soar code!)
that produces this bug/behavior (on Soar v9.3.2). Run and then print
out the episodes via "epmem -p" and you'll see that in episode 4 there
is (<id7> ^bar baz) that is not connected to state.

I agree - this should be reported as a bug (Bob, would you do the
honors?). With some thought, perhaps there's a way to detect the
situation efficiently and deal with the situation sanely. If that
works, the built in storage-compression routines would hopefully not
create too many added intervals/ids.

Nate

-------------------------

I am mildly surprised that this bug (still?) exists, since I feel like Nate and 
I have had discussions about this exact issue. I'll take a look at the test 
case and see if I can come to with a solution.

Justin (sent from my phone; excuse the typos)

Original issue reported on code.google.com by marin...@gmail.com on 12 Mar 2014 at 3:27

Attachments: