Memória semântica é um mecanismo que permite o armazenamento e recuperação de objetos persistentes, os chamandos, Lont-term Identifiers (LTI).
Utilizando-se o comando "smem --add" é possível criar objetos na memória semântica:
smem --add {
(<a> ^name alice ^friend <b>)
(<b> ^name bob ^friend <a>)
(<c> ^name charley)
}
Os LTIs são representados com o prefixo "@", o que pode ser verificado com o comando "smem --print":
(@A1 ^friend @B1 ^name alice [+1.000])
(@B1 ^friend @A1 ^name bob [+2.000])
(@C3 ^name charley [+3.000])
Esse conteúdo é armazenado numa região da memória completamente independente da memória de trabalho. Para apagá-lo é preciso utilizar o comando "smem --init"; esse comando apaga não somente a memória semântica, mas também toda a memória de trabalho: Isso é necessário porque referências LTI podem estar espalhadas por ela.
É possível salvar o conteúdo da memória semântica num arquivo para ser visualizado graficamente; utilizando o comando:
command-to-file <filename> smem --viz
É criado um arquivo com informação que permite ser visualizada graficamente com o programa "Graphviz Renderer", através do comando:
dot -Tpng <input-filename> -o <output-filename>.png
Representação gráfica dos elementos da memória semântica, fornecida pelo Graphviz
INTERAÇÃO COM A MEMÓRIA SEMÂNTICA
A memória semântica funciona como um componente externo ao agente, sendo acessado por comandos criados na extensão "^smem" - automaticamente criada em todos os estados - de maneira similar ao que ocorre com a extensão "^io":
- a extensão "^smem.command" é utilizada para o agente iniciar instruções
- a extensão "^smem.result" é utilizada para o agente receber feedback da memória semântica
A dinâmica de interção é a seguinte: o agente envia instruções à memória semântica, criando extensões dentro de "^smem.command" e recebendo respostas em "^smem.result"; o próprio Soar se encarrega de manter (popular e limpar) a extensão "^smem.result".
Para que essa dinâmica ocorra, entretanto, é preciso habilitá-la através do comando:
smem --set learning on
A seguir serão estudados os diversos comandos que podem ser enviados para a memória semântica a partir do estudo do exemplo "smem-tutorial.soar", distribuído juntamente com o SOAR.
O comando STORE
O comando STORE pode ser utilizado tanto para criar quanto para modificar um objeto dentro da memória semântica.
Para criar objetos:
sp {apply*init
(state <s> ^operator.name init
^smem.command <cmd>)
-->
(<s> ^name friends)
(<cmd> ^store <a> <b> <c>)
(<a> ^name alice ^friend <b>)
(<b> ^name bob ^friend <a>)
(<c> ^name charley)
}
Uma observação importante é que as referências na WM tornam-se LTI assim que os objetos referenciados são armazenados na memória semântica. Assim, dentro da extensão "^smem.command" tem-se o seguinte:
p s2 -d 2
(S2 ^command C2 ^result R3)
(C2 ^store @A1 ^store @B1 ^store @C3)
(R3 ^success @A1 ^success @B1 ^success @C3)
As referências inicialmente utilizadas para criar os elementos na memória semântica tornam-se LTIs depois do comando ser executado.
Múltiplos comandos STORE podem ser enviados de uma única vez e são executados ao final da fase corrente de execução do SOAR.
Para modificar objetos
Para se modificar objetos na memória semântica através do comando STORE é necessário que se tenha uma referência LTI; no exemplo, a própria extensão do comando original de criação é utilizada para obtenção da LTI:
sp {apply*mod
(state <s> ^operator.name mod
^smem.command <cmd>)
(<cmd> ^store <a> <b> <c>)
(<a> ^name alice)
(<b> ^name bob)
(<c> ^name charley)
-->
(<a> ^name alice -)
(<a> ^name anna
^friend <c>)
(<cmd> ^store <b> -)
(<cmd> ^store <c> -)
}
Uma observação importante é que o comando STORE não é recursivo: apenas as extensões diretas do LTI referenciado pelo comando são armazenadas.
COMANDO RETRIEVE COM REFERÊNCIA LTI
Através do comando retrieve é possível ao agente requisitar todas as extensões de um elemento da memória semântica para o qual o agente tem uma referência LTI; no exemplo é novamente utilizada a extensão do comando "^store" - já executado anteriormente - para obter o referência LTI de um das extensões "^friend" de "^name anna":
sp {propose*ncb-retrieval
(state <s> ^name friends
^smem.command <cmd>)
(<cmd> ^store <a>)
(<a> ^name anna
^friend <f>)
-->
(<s> ^operator <op> + =)
(<op> ^name ncb-retrieval
^friend <f>)
}
sp {apply*ncb-retrieval*retrieve
(state <s> ^operator <op>
^smem.command <cmd>)
(<op> ^name ncb-retrieval
^friend <f>)
(<cmd> ^store <a>)
-->
(<cmd> ^store <a> -
^retrieve <f>)
}
Diferentemente do comando STORE, o comando RETRIEVE só é executado na fase de OUTPUT do SOAR; assim, logo após ser aplicado apenas a extensão "^smem.command.retrieve" é criada, mas ainda sem resultado:
p s2 -d 2
(S2 ^command C2 ^result R3)
(C2 ^retrieve @B1)
Somente depois da etapa de OUTPUT é que as extensões requisitadas são criadas, abaixo da extensão da requisição "^smem.command.retrieve":
run 1 --phase
--- output phase ---
=>WM: (47: R3 ^retrieved @B1)
=>WM: (46: R3 ^success @B1)
=>WM: (45: @B1 ^friend @A1)
=>WM: (44: @B1 ^name bob)
p s2 -d 2
(S2 ^command C2 ^result R3)
(C2 ^retrieve @B1)
(R3 ^retrieved @B1 ^success @B1)
p s2 -d 3
(S2 ^command C2 ^result R3)
(C2 ^retrieve @B1)
(@B1 ^friend @A1 ^name bob)
(R3 ^retrieved @B1 ^success @B1)
No exemplo como o elemento de "^name anna" tinha duas extensões "^friend", SOAR retorna aleatóriamente uma delas; caso a referência especificada no comando "^retrieve" não seja para um LFI, o resultado terá a indicação de "^failure".
Tal como o comando STORE, o comando RETRIEVE não é recursivo: apenas as extensões diretas do LTI refereciado são retornadas.
COMANDO RETRIEVE COM CONSULTA
Uma outra forma de utilizar o comando RETRIEVE, sem precisar fornecer a referência LTI que se quer obter, é fornecer parâmetros de CONSULTA que serão utilizados para fazer a seleção de quais LTI serão retornados.
Caso seja encontrado um LFI que satisfaça a busca ele será retornado quando o comando for executado ao final da etapa de OUTPUT:
run 1 --phase
--- output phase ---
=>WM: (56: R3 ^success C4)
=>WM: (55: R3 ^retrieved @A1)
=>WM: (54: @A1 ^friend @B1)
=>WM: (53: @A1 ^friend @C3)
=>WM: (52: @A1 ^name anna)
<=WM: (46: R3 ^success @B1)
<=WM: (47: R3 ^retrieved @B1)
p s2 -d 3
(S2 ^command C2 ^result R3)
(C2 ^query C4)
(C4 ^friend @B1 ^name A2)
(R3 ^retrieved @A1 ^success C4)
(@A1 ^friend @B1 ^friend @C3 ^name anna)
Neste caso, o elemento encontrado é retornado como extensão de "^smem.result.retrieved".
Caso não seja encontrado nenhum elemento que corresponda à consulta, será retornado "^failure"; caso existam múltiplos elementos, será retornado o elemento mais recente - ou seja, o que foi criado na memória semântica por último - uma vez que o parâmetro BIAS é utilizado para desempate:
smem --print
(@A1 ^friend @B1 @C3 ^name anna [+6.000])
(@B1 ^friend @A1 ^name bob [+5.000])
(@C3 ^name charley [+3.000])