jadex.rules.rulesystem.rete.nodes.SplitNode Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-rules Show documentation
Show all versions of jadex-rules Show documentation
Jadex Rules is a small lightweight rule engine, which currently
employs the well-known Rete algorithm for highly efficient rule
matching. Jadex rules is therefore similar to other rule engines
like JESS and Drools. Despite the similarities there are also
important differences between these systems:
* Jadex Rules is very small and
intended to be used as component
of other software. Even though rules can be specified in a Java
dialect as well as (a small variation of) the CLIPS language
its primary usage is on the API level. Jadex Rules is currently
the core component of the Jadex BDI reasoning engine.
* Jadex Rules cleanly separates between state and rule representation.
This allows the state implementation as well as the matcher to be
flexibly exchanged. Some experiments have e.g. been conducted with
a Jena representation. Regarding the matcher, it is planned to
support also the Treat algorithm, which has a lower memory footprint
than Rete.
* Jadex Rules pays close attention to rule debugging. The state as
well as the rete engine can be observed at runtime. The rule debugger
provides functionalities to execute a rule program stepwise and also
use rule breakpoints to stop the execution at those points.
package jadex.rules.rulesystem.rete.nodes;
import jadex.commons.SReflect;
import jadex.rules.rulesystem.AbstractAgenda;
import jadex.rules.rulesystem.rete.extractors.AttributeSet;
import jadex.rules.rulesystem.rete.extractors.IValueExtractor;
import jadex.rules.state.IOAVState;
import jadex.rules.state.IProfiler;
import jadex.rules.state.OAVAttributeType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* A split node has the purpose of generating virtual facts
* for multislot bindings that use a non-multi variable or
* variable patterns.
*/
public class SplitNode extends AbstractNode implements IObjectConsumerNode, IObjectSourceNode
{
//-------- attributes --------
/** The constant for a multi variable. */
public static String MULTI = "multi";
/** The constant for a single variable. */
public static String SINGLE = "single";
/** The constant for a dummy multi variable. */
public static String MULTI_DUMMY = "multi_dummy";
//-------- attributes --------
/** The object source. */
protected IObjectSourceNode osource;
/** The object consumers. */
protected IObjectConsumerNode[] oconsumers;
/** The set of relevant attributes. */
protected AttributeSet relevants;
/** The set of indirect attributes. */
protected AttributeSet indirects;
/** The values extractor. */
// Needed as long as multifield extractor is based on attribute
protected OAVAttributeType attr;
/** The values extractor. */
protected IValueExtractor extractor;
/** The splitpattern (multi, single or multi dummy). */
protected String[] splitpattern;
/** The minimum number of required values. */
protected int min_values;
//-------- constructors --------
/**
* Create a new node.
* @param state The state.
*/
public SplitNode(int nodeid, IValueExtractor extractor, OAVAttributeType attr, String[] splitpattern)
{
super(nodeid);
assert extractor!=null;
assert attr!=null;
assert !OAVAttributeType.NONE.equals(attr.getMultiplicity());
assert splitpattern.length>0;
this.extractor = extractor;
this.attr = attr;
this.min_values = 0;
for(int i=0; i0)
System.arraycopy(oconsumers, 0, tmp, 0, i);
if(i flattened multi-collection
ret = new ArrayList();
for(Iterator it=((Map)mem.getNodeMemory(this)).values().iterator(); it.hasNext(); )
ret.addAll((Collection)it.next());
}
return ret;
}
/**
* Get all object consumer nodes.
* @return All object consumer nodes.
*/
public IObjectConsumerNode[] getObjectConsumers()
{
return oconsumers;
}
//-------- methods --------
/**
* Create the node memory.
* @param state The state.
* @return The node memory.
*/
public Object createNodeMemory(IOAVState state)
{
return new LinkedHashMap();
}
//-------- helper methods --------
/**
* Propagate a new object to all object consumers.
* @param object The new object.
*/
protected void propagateAdditionToObjectConsumers(Object object, IOAVState state, ReteMemory mem, AbstractAgenda agenda)
{
IObjectConsumerNode[] ocon = oconsumers;
for(int i=0; ocon!=null && i=min_values)
generateBindings(values.length, 0, new int[splitpattern.length], object, values, ret);
return ret;
}
/**
* Generate all possible bindings for a list of values.
* @param weight The number of values to distribute on variables.
* @param cur The current variable number.
* @param binding Results are stored in this binding array (contains
* for each variable how many values it should store).
* @param values The values to distribute.
* @param ret The result list containing all found bindings (in form of virtual facts).
*/
protected void generateBindings(int weight, int cur, int[] binding, Object object,
Object[] values, List ret)
{
if(cur==binding.length-1)
{
binding[cur] = weight;
//System.out.println("Found binding: "+Srules.arrayToString(binding));
ret.add(generateVirtualFact(object, binding, values));
}
else
{
if(splitpattern[cur]!=SINGLE)
{
for(int i=0; i<=weight-min_values; i++)
{
binding[cur] = i;
generateBindings(weight-i, cur+1, binding, object, values, ret);
}
}
else
{
binding[cur] = 1;
generateBindings(weight-1, cur+1, binding, object, values, ret);
}
}
}
/**
* Generate a virtual fact for a found binding.
* @param binding The number of values for each variable.
* @param values The multislot values.
* @return A virtual fact with one binding.
*/
protected VirtualFact generateVirtualFact(Object object, int[] binding, Object[] values)
{
int off = 0;
int bcnt = 0;
List splitvals = new ArrayList();
for(int i=0; i1)
{
List vals = new ArrayList();
for(int j=off; j