JSoarEpisodicMemory - soartech/jsoar GitHub Wiki
JSoar's implementation of episodic memory has several features/foibles not present in CSoar.
Analogous to the epmem exclusion list, the inclusion list is a set of attributes which must be on a value's path (from the top-state) in order to be included in an episode. By default, the inclusion list is empty, implying that all attributes are whitelisted. Note that a WME with an attribute not in the inclusion list may still be included in the episode if that WME's value is an identifier which, somewhere in the subgraph rooted at that identifier, there is an attribute in the inclusion list. For example, if the inclusion list contains only the attribute "keep" and WM looks like this:
(<s> ^test <test>
^stuff <stuff>)
(<test> ^test 4)
(<stuff> ^keep <this>
^do-not-keep <that>)
then episodic memory will only record this path: (<s> ^stuff.keep <this>)
.
If both the inclusion and exclusion lists are empty, everything on the top state (except the standard items, such as epmem
and smem
) get recorded by episodic memory. If only exclusion list is empty, then only paths with an attribute in the inclusion list get recorded. If only the inclusion list is empty, then all paths which do not have an attribute in the exclusion list get recorded. If both lists are non-empty, then a path will only be recorded if:
- The path contains an attribute on the inclusion list.
- The path does not contain an attribute on the exclusion list.
For example, consider these lists:
epmem --set exclusions foo
epmem --set inclusions bar
And suppose that working memory looks like this:
^base
^bar
^chef
^x 3
^y 4
^foo 0
^foo
^x 5
^y 6
^jaz
^x 1
^y 2
Then the episode which gets recorded will be:
^base
^bar
^chef
^x 3
^y 4
Epmem can be forced to create a new memory when it otherwise wouldn't. To do this, put a ^store WME on the ^epmem.command structure, like this:
sp {test*example
(state <s> ^epmem.command <cmd>)
...
-->
(cmd ^store <dummy>) # <dummy> can be any value/identifier
}
At the next epmem storage phase (either output
or selection
, as set by the epmem --set phase
command), epmem will create a memory. Note that if this overlaps with other triggers (such as dc
or output
, as set by the epmem --set trigger
command), only one memory will get created.
Thus, to have entirely manual control over the epmem storage cycle, use epmem --set trigger none
, and then use the ^store WME to trigger episode creation.
Once the deliberate storage command has been processed and the new memory created, epmem will put a ^success WME on the ^epmem.result structure: <s> ^epmem.result.success <dummy>
, where <dummy>
is the same value/identifier which was put on the ^epmem.command.store WME.
Like with other epmem commands, the ^store WME must be removed and re-added in order to trigger another deliberate storage.
Custom memories can be inserted into epmem using the epmem --add
command. To add a single episode to epmem, use a syntax like:
epmem --add { (state <s> ^my.test.memory <mem> ^multi-valued 1 2 3 ^test true ^just-an-id <id>) (<mem> ^count 5) }
The epmem --add
command will use the variable preceded by "state" to represent the top state. If you don't use "state", then it will treat the first variable in the first clause as the top state.
To add multiple memories in one command, just enclose each memory in its own set of braces:
epmem --add { { (state <s> ^memory 1) } { (state <s> ^memory <mem>) (<mem> ^count 2) } }
If you need to call the epmem --add
command from the RHS, you will need to replace the outermost braces with pipes:
sp {test
(state ...)
-->
(...)
(cmd epmem --add | { (state <s> ^memory 1) } { (state <s> ^memory <mem>) (<mem> ^count 2) } |)
}
For convenience, the epmem --add
command can also read from a file: epmem --add file-name.epmem
. The file is expected to contain exactly the same format as the parameters handed to the epmem --add
command.
Note that if you use Tcl, replace the outermost braces with double-quotes to enable Tcl variable substitution:
epmem --add "(state <s> ^a.single.memory <mem>)"
epmem --add "{(state <s> ^first.memory <mem>)} {(state <s> ^of <of>) (<of> ^two memories)}"