Predicate Subgraph Nodes

Working Memory Variable Node

class pysigma.graphical.predicate_nodes.WMVN(name, ks, rel_var_list, param_var=None, index_var_list=None, ran_var_list=None, **kwargs)[source]

Working Memory Variable Node.

Gate node connecting predicate structure to conditionals.

WMVN will attempt to combine incoming messages, regardless of whether they come from alpha terminals in Conditional subgraphs, or from other nodes in the Predicate subgraph. The combined message generally yields the semantics of marginal belief coming from a certain part of the graphical model, and is sent to downstream nodes for further processing.

A KnowledgeServer instance associated with the belonging Predicate is required because occasionally log prob of particles needs to be queried.

WMVN quiescence state:

A WMVN reaches quiescence state if and only if all incoming linkdata do not contain new message.

It is defined as such so that, although inefficiency may be induced due to WMVN having to fire multiple times while sending partially complete messages, it is guaranteed that no new arriving message would be blocked herein simply because other messages were blocked elsewhere and did not arrive at this node, consequently blocking all downstream processing.

Parameters
  • name (str) – Name of this variable node.

  • ks (KnowledgeServer) – The KnowledgeServer instance associated with the belonging Predicate.

  • rel_var_list (iterable of Variable) – Iterable of relational variables. Corresponds to the batch dimensions. Used to check b_shape attribute of incoming messages.

  • param_var (Variable, optional) – The parameter variable. Corresponds to the parameter dimension. Used to check p_shape attribute of incoming messages.

  • index_var_list (iterable of Variable, optional) – Iterable of indexing variables. Corresponds to the sample dimensions. Used to check s_shape attribute of incoming messages. Must specify if ran_var_list is specified.

  • ran_var_list (iterable of Variable, optional) – Iterable of random variables. Corresponds to the event dimensions. Used to check e_shape attribute of incoming messages. Must specify if index_var_list is specified.

ks

The KnowledgeServer instance associated with the belonging Predicate.

Type

KnowledgeServer

compute()[source]

Combine incoming message to this Predicate subgraph.

Will attempt to combine incoming messages if there are multiple incoming links, subsuming the functionality of FAN node in Lisp Sigma. Combination can be carried out if messages are all Parameter type, or if there exist Particles type messages but all of them are homogeneous (sharing the same particle values as well as sampling log densities).

Raises
  • AssertionError – If found that not all incoming messages contain either parameter or particles, or both.

  • AssertionError – If the MessageType.Particles type messages in the incoming links do not share the same particles (including particle value tensors and/or particle log sampling density tensors)

Warns

UserWarning – If there is only one incoming link, but this link is connected to a factor node that is also connected from this WMVN via an outgoing link. This means, per Sum-Product exclusion principle, that this outgoing link will also be neglected during compute() and no new message will ever be propagated via this link.

Notes

Following combination procedure is carried out to conform to the standard of all inference methods

  1. If incoming messages all contains parameter, then these parameters will be combined. The outgoing message will contain the combined parameter. Otherwise if any incoming message does not contain parameter, this procedure will not be performed and the outgoing message will not contain parameter, but rather a combined particle list will be computed. See the followings.

    For the parameter message combination procedure and accompanying assumptions, see Message class notes on arithmetic structures for more details.

  2. If any incoming message also contains particles, then it is imperative that all such messages contain the same particle values as well as particle log sampling densities. The particle weights will be gathered from these messages and combined. For all other parameter messages that only contain parameters, the particles from these particles messages will be used as the surrogate particles to generate a particle message as approximation, which will take part in the particles combination procedure.

In short, here is a summary listing the correspondence between incoming message types and outgoing message types:

Incoming Message Types

Outgoing Message Type

Parameter

Parameter

Particles

Particles

Both

Both

Parameter + Particles

Particles

Parameter + Both

Both

Particles + Both

Particles

Parameter + Particles + Both

Particles

Or, logically speaking, the outgoing message will contain particles if any incoming message also contains particles, but it will contain parameter only if all incoming messages contain parameters.

Note that in any case, incoming message can not be MessageType.Undefined type, in which case an exception will be raised.

When combining messages, will exclude message from the link to which the combined message is to send to (if such a bidirected link exists). This implements the Sum-Product algorithm’s variable node semantics, if this WMVN is served as both WMVN_IN and WMVN_OUT, i.e., if the predicate is of memory-less vector type.

Optimization is implemented by caching the combination result for each outgoing link. If two outgoing links share the same set of incoming links that provide the messages, previously computed result will be reused

Long-Term Memory Factor Node

class pysigma.graphical.predicate_nodes.LTMFN(name, ks, rel_var_list, param_var, index_var_list, ran_var_list, to_draw=True, **kwargs)[source]

Long-Term Memory Factor Node.

Memorizes and updates the predicate’s knowledge across decision cycles. Hosts and maintains the associated KnowledgeServer instance to provide service to downstream nodes.

Admits one incoming link from WMVN_IN that contains combined action message toward this predicate by the end of the decision cycle, as well as arbitrary number of incoming links from parameter feeds and/or WMFN that contains parameter messages. Special attribute therefore needs to be declared in the linkdata’s attribute dictionary to distinguish which one sends “event” message from WMVN_IN and which ones send “param” messages from parameter feeds.

If there are multiple incoming “param” labeled links, then combination will be carried out by taking summation over the parameters. See Message class notes on arithmetic structures for more details.

init_msg() should be called during modification phase of a cognitive cycle so that the message to be sent to downstream nodes during the next cognitive cycle is prepared herein. This includes gathering new parameters that are ready to be read from the incoming param linkdata at the end of the previous decision phase, as well as optionally drawing importance weighted particles w.r.t. the batched distributions that are instantiated from the newly gathered parameters. The latter behavior can be set by calling toggle_draw() method. In general, it is expected to include as much information as possible in the outgoing message, and so drawing mode should be turned on, but there are also circumstances in which this behavior should be avoided, for instance when the Predicate is perceiving observations / evidence from PBFN, where the particle values should be determined by the observation feed rather than be drawn here at the LTMFN.

Particles can optionally be drawn during modification phase of each cognitive cycle by calling init_msg() method, which internally calls the corresponding method of the KnowledgeServer instance to perform the Gibbs sampling procedure.

Todo

Define LTMFN’s quiescence behavior.

Parameters
  • name (str) – Name of this node.

  • ks (KnowledgeServer) – The KnowledgeServer instance associated with the predicate.

  • rel_var_list (iterable of Variable) – Iterable of relational variables, corresponding to the predicate’s relational arguments.

  • param_var (Variable) – The parameter variable.

  • index_var_list (iterable of Variable) – Iterable of indexing variables.

  • ran_var_list (iterable of Variable) – Iterable of random variables, corresponding to the predicate’s random arguments.

  • to_draw (bool, optional) – Initialize whether this LTMFN should be drawing particles in init_msg(). Defaults to True.

ks
rel_var_list
param_var
index_var_list
ran_var_list
to_draw
b_shape

The batch shape.

Type

torch.Size

p_shape

The parameter shape (size).

Type

torch.Size

s_shape

The sample shape.

Type

torch.Size

e_shape

The event shape.

Type

torch.Size

msg_cache

The message cache. Set during modification phase, and sent during decision phase of the next cognitive cycle.

Type

Message

Only admits one incoming and one outgoing event message link, the former should be connected from WMVN_IN and the later from WMVN_OUT (can be the same WMVN instance). However can admit multiple incoming parameter message link.

Parameters

linkdata (LinkData) – The linkdata to be registered. The 'type' key-ed attribute must present in the linkdata’s attribute dict.

Raises
  • AssertionError – If the new linkdata does not have identical batch shape and param shape.

  • AssertionError – If attempting to register more than one outgoing link.

  • AssertionError – If 'type' key does not exist in the linkdata’s attribute dict, or if the associated value is neither 'event' nor 'param'.

  • AssertionError – If attempting to register more than one event incoming link.

toggle_draw(to_draw)[source]

Sets whether this LTMFN should draw particles in init_msg() and send MessageType.Both type message, or not draw particles and send MessageType.Parameter message

Parameters

to_draw (bool) – Whether to draw particles or not.

init_msg()[source]

Draws particles and instantiate new message for next cognitive cycle.

This method should be called during the modification phase. Parameter will be gathered from incoming param linkdata, and in the case of multiple incoming param linkdata the parameter tensors gathered will be combined. A new list of particles will then be drawn in the cognitive format by querying the given KnowledgeServer.

Raises
  • AssertionError – If no param type incoming linkdata is found.

  • AssertionError – If messages read from incoming linkdata do not all contain parameters.

compute()[source]

Send message in self.msg_cache to the connected WMVN_OUT node.

Raises
  • AssertionError – If there are no connected outgoing linkdata.

  • AssertionError – If self.msg_cache is None. This means init_msg() were not called prior to the current decision phase which calls this method.

Parameter Store Factor Node

class pysigma.graphical.predicate_nodes.PSFN(name, batch_shape, param_shape, init_param=None, **kwargs)[source]

Parameter Store Factor Node

Stores the batched distribution parameters of the Predicate’s knowledge and feeds them to LTMFN via DVN. Admits no incoming links and only one outgoing link to a DVN.

This node is typically used in combination with a LTMFN, where a PSFN handles the actual storage and updates of the distribution parameter, and LTMFN uses this parameter to derive the event messages to be sent to WMVN gate node.

By default, the parameter tensor is stored using a torch.nn.Parameter wrapper, so that any downstream processing and derived tensors automatically turns on gradient tracing.

PSFN quiescence state:

A PSFN reaches quiescence state if and only if it has been visited.

The quiescence property is therefore overridden to conform to this definition.

Parameters
  • batch_shape (torch.Size) – The batch shape of the distribution parameter.

  • param_shape (torch.Size) – The parameter shape of the distribution parameter.

  • init_param (torch.Tensor or None) – The initialized parameter tensor. If not None, should be a tensor of shape (batch_shape + param_shape). Defaults to None.

b_shape
p_shape
param

The parameter buffer. Should be a tensor of shape (batch_shape + param_shape). Value defaults to a zero tensor, when init_param is None during initialization.

Type

torch.nn.Parameter

reset_param(param)[source]

Resets the parameter tensor.

Parameters

param (torch.Tensor) – The tensor to be set as the parameter value. Should have shape (self.b_shape + self.p_shape).

For PSFN, only one outgoing link is admitted.

compute()[source]

Instantiates and sends a Parameter message.

property quiescence

Overrides so that PSFN’s quiescence state is equivalent to its visited state

Perceptual Buffer Node

class pysigma.graphical.predicate_nodes.PBFN(name, batch_shape, event_shape, **kwargs)[source]

Perception Buffer Factor Node.

Receives perception / observation / evidence as particle list from perceive() and sends particles message to WMVN.

Does not admit any incoming link. Only admits one outgoing link connecting to a WMVN.

Perception is buffered, and will be latched to next cycle if no new observation is specified. To cancel out the previously buffered observation, a None observation needs to be perceived.

PBFN quiescence state:

A PBFN reaches quiescence state if and only if it has been visited.

The quiescence property is therefore overridden to conform to this definition.

Parameters
  • name (str) – Name of this node

  • batch_shape (torch.Size) – The batch shape of the Predicate’s knowledge. In a PBFN this is solely used to align the particle weight tensor in the outgoing message to the correct shape.

  • event_shape (torch.Size) – The event shape of any observation / evidence event particles, except for None observation. Its length should match the number of predicate random arguments. See more details in following perceive() method.

buffer

The perceptual buffer. It is a 2D tensor whose last dimension is the event dimension with size equal to self.e_shape.

Type

torch.Tensor

b_shape

Set by batch_shape.

Type

torch.Size

e_shape

Set by event_shape.

Type

torch.Size

perceive(obs=None, weight=None, mode='joint')[source]

Perceives a new piece of observation / evidence particle events, specified by obs, with optional weight specified by weight. instantiate the perception message to be sent by compute() and store it in the perceptual buffer.

If obs is None, a MessageType.Both type identity message will be instantiated. Otherwise, it is a MessageType.Particles message with particle values from obs, particles weight reflecting weight (uniform if weight is None), and uniform log sampling densities.

The particle weight tensor will be copied and expanded to include full batch dimension shape self.b_shape.

There are two perception mode: joint or marginal, specified by mode. This distinction makes a difference mostly for predicates with multiple random arguments:

  • When in joint mode, the observations should be list of joint particle events. Accordingly, obs must be a 2D tensor with the last dimension being the joint event dimension having a size equal to the sum of all random variables’ sizes (sum of self.e_shape), and the first dimension being the sample (indexing) dimension. ‘weight’ must a 1D tensor with its length equal to the size of obs ‘s first dimension.

    Internally, in order to conform to standard message format, this joint event tensor obs will be broken up into chunks along the event dimension according to the sizes of the random variables. Each chunk thus represents a list of marginal event values, corresponding to one of the random variables, on an axis of a high-dimensional event lattice in the joint event space. A weight tensor of the same dimensional shape will be created to annotate this event lattice, with entries equal to values found in weight for the slots that corresponds to those joint events in obs, and other entries set to NP_EPSILON (representing numerically stable 0 weight).

  • When in marginal mode, the observations are tuple of marginal events for each random variable, and the assumption is taken that these marginal events for each random variable are mutually independent. Accordingly, obs must be an ITERABLE of 2D tensors, with the last dimension size of each entry equal to the size of the corresponding random variable, in the order specified by self.e_shape. Similarly, weight must also be an ITERABLE with the same length as obs, containing 1D tensors.

The weights for duplicate events would be added together. However, this behavior should not be counted on and it is recommended to avoid duplicate entries in obs and instead use weight to signal the relative importance of each observation.

Note that it is not necessary that weight is normalized and sums to 1; they will be automatically normalized when the outgoing message is instantiated. However weight must contain only positive values.

This method should be called prior to the decision phase of a cognitive cycle for the perceived observation be sent to downstream nodes during the decision phase.

Parameters
  • obs (iterable of torch.Tensor, torch.Tensor, or None. optional) – If not None, must be a 2D tensor if mode is joint, or an iterable of 2D tensors if mode is marginal. Defaults to None.

  • weight (iterable of torch.Tensor, torch.Tensor, or None. optional) – If not None, must be a 1D tensor if mode is joint, or an iterable of 1D tensors if mode is marginal. If obs is None, this value will be ignored. Defaults to None.

  • mode ({"joint", "marginal"}) – The perception mode. Defaults to "joint".

For PBFN, only one linkdata can be admitted, and it should be an outgoing linkdata connecting a WMVN node.

compute()[source]

Sends the contents in perceptual buffer to the connected WMVN.

property quiescence

Overrides default behavior so now PBFN’s quiescence is determined by whether compute() has been called.

Working Memory Factor Node

class pysigma.graphical.predicate_nodes.WMFN(name, decay_rate=1, **kwargs)[source]

Working Memory Factor Node.

Effectively a buffer node that contains a memory buffer, WMFN mixes the incoming message with its stored memory by taking a weight sum during the modification phase, updates its memory with the result, and sends this updated memory during the decision phase at the next cognitive cycle. The first two steps are performed by update_memory(), whereas sending the message is, as always, performed by compute().

The weighted sum mixture behavior can be described as follows:

new_memory = new_msg + (1 - decay_rate) * old_memory

where decay_rate is a real number in range [0, 1]. The vector addition and scalar multiplication for messages of different types are mathematically defined by the Message class. See Message class notes on arithmetic structures for more details.

The incoming message will always be cloned before weighted sum update is performed. This is to prevent any components of the memory message from in-place change by some parts elsewhere in the graph.

Admits only one incoming and one outgoing links. Note that WMFN does not check the message shape of messages and memory contents. These should be guaranteed compatible by linkdata and neighboring nodes.

The check_quiesce() method is overridden so that PSFN’s quiescence state is determined by whether this node is visited during the decision phase, i.e., whether compute() is called.

Parameters
  • name (str) – The name of this node

  • decay_rate (float) – The decay rate of the memory contents.

decay_rate
memory

WMFN only admits one incoming link and one outgoing link.

update_memory()[source]

Updates the content in memory using message from incoming link.

This step should be called during the modification phase.

compute()[source]

Sends memory content toward outgoing link

check_quiesce()[source]

Overrides so that quiescence for WMFN is equivalent to visited