garfieldnate / pysoarlib

This is a python library module with code to help make working with Soar SML in python easier.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PySoarLib

Aaron Mininger

2018

This is a python library module with code to help make working with Soar SML in python just a little bit easier.

Methods do have docstrings, to read help information open a python shell and type

import pysoarlib
help(pysoarlib)
help(pysoarlib.SoarClient)

SoarClient

Defines a class used for creating a soar agent, sending commands, running it, etc. There are a number of settings that you can use to configure the client (see following subsection) and can specify either by including them in the config file or by giving as keyword arguments in the constructor.

SoarClient(config_filename=None, print_handler=None, **kwargs)
Will create the soar kernel and agent, as well as source the agent files. print_handler specifies how output is handled (defaults to python print) and config_filename names a file with client settings in it

add_connector(AgentConnector, name:str)
Adds the given connector and will invoke callbacks on it (such as on_input_phase)

get_connector(name:str)
Returns a connector of the given name, or None

has_connector(name:str) -> Boolean
Returns true if the given connector exists

add_print_event_handler(handler)
Will call the given handler during each soar print event (handler should be a method taking 1 string)

connect()
Will register callbacks (call before running)

disconnect()
Will deregister callbacks

start()
Will cause the agent to start running in new thread (non-blocking)

stop()
Will stop the agent

execute_command(cmd:str, print_res:bool=False)
Sends the given command to the agent and returns the result as a string. If print_res=True it also prints the output using print_handler

restart()
Completely destroys the agent and creates + sources a new one

kill()
Will stop the agent and destroy the agent/kernel

Config Settings (kwargs or config file)

These can be passed as keyword arguments to the SoarClient constructor, or you can create a config file that contains these settings.

Argument Type Default Description
agent_name str soaragent The soar agent's name
agent_source filename The root soar file to source the agent productions
smem_source filename The root soar file that sources smem add commands
source_output enum str summary How much detail to print when sourcing files: none, summary, or full
watch_level int 1 Sets the soar watch/trace level, how much to print each DC (0=none)
spawn_debugger bool false If true, spawns the soar java debugger
start_running bool false If true, will automatically start running the agent
write_to_stdout bool false If true, will print all soar output to the print_handler
print_handler method print A method taking 1 string arg, handles agent output
enable_log bool false If true, writes all soar/agent output to a file
log_filename filename agent-log.txt The name of the log file to create
time settings
use_time_connector bool false If true, creates a TimeConnector to put time info on the input-link
clock_include_ms bool true Will include milliseconds for elapsed and clock times
sim_clock bool false If false, the clock shows real time. If true, it advances a fixed amount each DC
clock_step_ms int 50 The number of milliseconds the simulated clock advances each decision cycle

Instead of passing as arguments, you can include them in a file specified by config_filename Each line in the file should be 'setting = value'

Example File:

agent_name = Rosie    
agent_source = agent.soar    
spawn_debugger = false    

AgentConnector

Defines an abstract base class for creating classes that connect to Soar's input/output links

AgentConnector(client:SoarClient)

add_output_command(command_name:str)
Will register a handler that listens to output link commands with the given name

add_print_event_handler(handler:func)
Will register a print event handler (function taking 1 string argument) that will be called whenever a soar print event occurs.

on_init_soar()
Event Handler called when init-soar happens (need to release SML working memory objects)

on_input_phase(input_link:Identifier)
Event Handler called every input phase

on_output_event(command_name, root_id)
Event Handler called when a new output link command is created (<output-link> ^command_name <root_id>)

IdentifierExtensions

These add a few helper methods to the sml.Identifier class: (Do not need to import directly, come with any import from module)

Identifier.GetChildString(attribute:str)
Given an attribute, will look for a child WME of the form (<id> ^attribute <value>) and return the value as a string

Identifier.GetChildInt(attribute:str)
Given an attribute, will look for a child IntegerWME of the form (<id> ^attribute <value>) and return the value as an integer

Identifier.GetChildFloat(attribute:str)
Given an attribute, will look for a child FloatWME of the form (<id> ^attribute <value>) and return the value as an float

Identifier.GetChildId(attribute:str)
Given an attribute, will look for a child WME of the form (<id> ^attribute <child_id>) and return an Identifier with child_id as the root

Identifier.GetAllChildIds(attribute:str=None)
Given an attribute, returns a list of Identifiers from all child WME's matching (<id> ^attribute <child_id>) If no attribute is specified, all child Identifiers are returned

Identifier.GetAllChildValues(attribute:str=None)
Given an attribute, returns a list of strings from all child WME's matching (<id> ^attribute <value>) If no attribute is specified, all child WME values (non-identifiers) are returned

Identifier.GetAllChildWmes()
Returns a list of (attr, val) tuples representing all wmes rooted at this identifier. val will either be an Identifier or a string, depending on its type """

WMInterface:

An interface class which defines a standard way of adding/removing structures from working memory:

is_added()
Returns True if the structure is currently added to working memory

add_to_wm(parent_id)
Adds the structure to working memory under the given identifier

update_wm(parent_id=None)
Applies any changes to working memory
Note, if a parent_id is given and the item is not yet added to wm, it will add it

remove_from_wm()
Removes the structure from working memory

SoarWME:

A class which can represent a WMElement with an (<id> ^att value) but takes care of actually interfacing with working memory

You can update its value whenever you want, it will not affect working memory. To change working memory, call add_to_wm, update_wm, and remove_from_wm during an event callback (like BEFORE_INPUT_PHASE)

SVSCommands:

A collection of helper functions to create string commands that can be send to SVS Here pos, rot, and scl are lists of 3 numbers (like [1, 2.5, 3.1])

  • add_box(obj_id, pos=None, rot=None, scl=None)
  • change_pos(obj_id, pos)
  • change_rot(obj_id, rot)
  • change_scl(obj_id, scl)
  • delete(obj_id)
  • add_tag(obj_id, tag_name, tag_value)
  • change_tag(obj_id, tag_name, tag_value)
  • delete_tag(obj_id, tag_name)

TimeConnector

An AgentConnector that will create time info on the input-link. Includes elapsed time since the agent started, and can have a real-time or simulated wall clock. It is enabled through the client setting use-time-connector=True There are several settings that control its behavior as described in Config Settings.

# Will add and update the following on the input-link:
([il] ^time [t])
([t] ^seconds [secs] # real-time seconds elapsed since start of agent
     ^milliseconds [ms] # real-time milliseconds elapsed since start
     ^steps [steps] # number of decision cycles since start of agent
     ^clock [clock])
([clock] ^hour [hr] # 0-23
         ^minute [min] # 0-59
         ^second [sec] # 0-59
         ^millisecond [ms] # 0-999
         ^epoch [sec] # Unix epoch time in seconds)

Also, if using a simulated clock, the agent can change the time itself using an output command:

([out] ^set-time [cmd])
([cmd] ^hour 9
       ^minute 15
       ^second 30) # optional 

pysoarlib.util

Package containing several utility functions for reading/writing working memory through sml structures.

parse_wm_printout(text:str)

Given a printout of soar's working memory (p S1 -d 4), parses it into a dictionary of wmes, where the keys are identifiers, and the values are lists of wme triples rooted at that id.

You can wrap the result with a PrintoutIdentifier(wmes, root_id) which will provide an Identifier-like iterface for crawling over the graph structure. It provides all the methods in the IdentifierExtensions interface.

extract_wm_graph(root_id, max_depth)

Recursively explores all working memory reachable from the given root_id (up to max_depth), builds up a graph structure representing all that information.

Note: max_depth is optional (defaults to no depth limit), and the function is smart about handling cycles (will not recurse forever)

# Returns a WMNode object wrapping the root_id and containing links to children
node.id = root_id (Identifier)
node.symbol = string (The root_id symbol e.g. O34)
node.attributes() - returns a list of child attribute strings
node['attr'] = WMNode   # for child identifiers
node['attr'] = constant # for string, double, or int value
node['attr'] = [ val1, val2, ... ] # for multi-valued attributes 
               (values can be constants or WMNodes)
str(node) - will pretty-print the node and all children recursively

update_wm_from_tree(root_id, root_name, input_dict, wme_table)

Will update working memory using the given input_dict as the provided structure rooted at root_id. Created wme's are stored in the given wme_table, which should be a dictionary that is kept across multiple calls to this function. root_name specifies a prefix for each wme name in the wme_table.

# input_dict should have the following structure:
{
  'attr1': getter() <- The value will be the result of calling the given getter function
  'attr2': dict   <- The value will be a child identifier with its own recursive substructure
}

remove_tree_from_wm(wme_table)

Given a wme_table filled by SoarUtils.update_wm_from_tree, removes all wmes from working memory

About

This is a python library module with code to help make working with Soar SML in python easier.

License:MIT License


Languages

Language:Python 100.0%