Commit 0393e0df authored by Eric Tobias's avatar Eric Tobias

Initial forke of CPS

parents
*.metadata
*.classpath
CPS/target
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>cps</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
This diff is collapsed.
This diff is collapsed.
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>lu.list.itis.dkd.tui</groupId>
<artifactId>cps</artifactId>
<version>1.0.0</version>
<name>Complex Problem Solving library</name>
<build>
<sourceDirectory>src</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>lu.list.itis.dkd</groupId>
<artifactId>dbc-annotation</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>19.0</version>
</dependency>
<dependency>
<groupId>dk.ange</groupId>
<artifactId>javaoctave</artifactId>
<version>0.6.4</version>
</dependency>
<dependency>
<groupId>lu.list.itis.dkd.tui</groupId>
<artifactId>tulip</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
/**
* Copyright CRP Henri Tudor, 2014.
* All rights reserved. If you wish to use this code for any purpose,
* please contact CRP Henri Tudor's Technology Transfer Office : tto@tudor.lu
*/
package lu.list.itis.dkd.cps;
import java.util.Vector;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
/**
* Class implementing a clock holding a value representing
* an abstract turn.
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 21 Feb 2014
* @version 1
*/
@NonNullByDefault
public class Clock
{
/** Field holding the current turn value. */
private long tick = 0;
/** Field holding a {@link Vector} of listeners to turn churns. */
private Vector<InputDriver> tickListeners = new Vector<>();
/**
* Getter method returning the current turn count.
* @return
* The current turn value.
* @invariant tick >= 0
*/
public long getTick()
{
return tick;
}
/**
* Method resetting the turn value.
* @post tick = 0
*/
public void reset()
{
tick = 0;
}
/**
* Advances the turn count by one. Should the count be the
* maximum value of the counter it will wrap to 0. The
* method also notifies all listeners of the change.
* @return
* The value of the new turn count.
* @post tick = old(tick) + 1 || tick = Long.MAX_VALUE => tick = 0
*/
public long tick()
{
if(tick == Long.MAX_VALUE)
{
reset();
} else {
tick++;
}
for(InputDriver listener : tickListeners)
{
listener.clockTicked(tick);
}
return tick;
}
/**
* Method invoked to add a {@link InputDriver} to the {@link Vector} of
* listeners to notify on tick.
* @param listener
* The {@link InputDriver} to add.
*/
public void addListener(InputDriver listener)
{
tickListeners.add(listener);
}
}
\ No newline at end of file
/**
* Copyright CRP Henri Tudor, 2014.
* All rights reserved. If you wish to use this code for any purpose,
* please contact CRP Henri Tudor's Technology Transfer Office : tto@tudor.lu
*/
package lu.list.itis.dkd.cps;
import java.util.EventListener;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
/**
* Interface defining method for listeners to input change.
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 21 Feb 2014
* @version 1
*/
@NonNullByDefault
public interface InputChangeListener extends EventListener
{
/**
* Method invoked by any observed instances when an input has changed.
* @param input
* The {@link InputEvent} holding the source as well as turn
* count, variable name, and value of the input.
*/
public void inputChanged(InputEvent input);
}
\ No newline at end of file
/**
* Copyright CRP Henri Tudor, 2014.
* All rights reserved. If you wish to use this code for any purpose,
* please contact CRP Henri Tudor's Technology Transfer Office : tto@tudor.lu
*/
package lu.list.itis.dkd.cps;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
/**
* Interface specifying the methods for driving the collection or
* forwarding of input values.
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 21 Feb 2014
* @version 1
*/
@NonNullByDefault
public interface InputDriver
{
/**
* Method invoked when the clock advanced a turn.
* @param tick
* The turn count the clock advanced to.
*/
public void clockTicked(long tick);
}
\ No newline at end of file
/**
* Copyright CRP Henri Tudor, 2014.
* All rights reserved. If you wish to use this code for any purpose,
* please contact CRP Henri Tudor's Technology Transfer Office : tto@tudor.lu
*/
package lu.list.itis.dkd.cps;
import java.util.EventObject;
import lu.list.itis.dkd.cps.variable.Variable;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
/**
* Class implementing an event holding all necessary information
* to change {@link Variable} instances synchronously with the change
* of an external input.
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 21 Feb 2014
* @version 1
*/
@NonNullByDefault
public class InputEvent extends EventObject
{
private static final long serialVersionUID = 2884355501325896122L;
/** The turn index the event was triggered at. */
private long tick;
/**
* Constructor initialising the source and all other fields.
* @param source
* The source of the event.
* @param tick
* The turn index the event was triggered at.
*/
public InputEvent(Variable source, long tick)
{
super(source);
this.tick = tick;
}
/**
* Constructor initialising the source field and
* setting the tick field to -1.
* @param source
* The source of the event.
*/
public InputEvent(Variable source)
{
super(source);
this.tick = -1;
}
/**
* Simple getter method for tick.
* @return The value of tick.
*/
public long getTick()
{
return tick;
}
}
\ No newline at end of file
/**
* Copyright CRP Henri Tudor, 2014.
* All rights reserved. If you wish to use this code for any purpose,
* please contact CRP Henri Tudor's Technology Transfer Office : tto@tudor.lu
*/
package lu.list.itis.dkd.cps;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import lu.list.itis.dkd.cps.variable.Variable;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
/**
*
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 21 Feb 2014
* @version 1
*/
@NonNullByDefault
public class Phenomenon
{
/** The clock which may dictate the sampling rate and advancement of the phenomenon. */
private Clock clock;
/** The independent variables characterising the system. */
private ConcurrentHashMap<String, Variable> independentVariables;
/** The variables depending on the system and its inputs. */
private ConcurrentHashMap<String, Variable> dependentVariables;
/** The system computing dependent variables from input independent variables. */
private lu.list.itis.dkd.cps.system.System system;
/** Field indicating whether the observation is to be driven by a clock. */
private boolean clockDriven;
/**
* Constructor initialising all fields.
* @param independentVariables
* The independent variables characterising the system.
* @param dependentVariables
* The variables depending on the system and its inputs.
* @param system
* The system computing dependent variables from input independent variables.
* @param clockDriven
* Indication whether the observation of the phenomenon is to be driven
* by the ticking of a clock or is synchronous.
*/
public Phenomenon(ConcurrentHashMap<String, Variable> independentVariables,
ConcurrentHashMap<String, Variable> dependentVariables,
lu.list.itis.dkd.cps.system.System system, boolean clockDriven)
{
clock = new Clock();
this.independentVariables = independentVariables;
this.dependentVariables = dependentVariables;
this.system = system;
this.clockDriven = clockDriven;
if(clockDriven)
{
clock.addListener(system);
} else {
for(Variable variable : independentVariables.values())
{
variable.addListener(system);
}
for(Variable variable : dependentVariables.values())
{
variable.addListener(system);
}
}
}
/**
* Method used to advance the observation by one turn or period.
* @return
* The turn of the observation or <code>-1</code> if the phenomenon
* is observed synchronously with the modification of the input
* parameters.
* @invariant result >= -1
*/
public long churn()
{
if(clockDriven)
{
return clock.tick();
}
return -1;
}
/**
* Method for retrieving the output.
* @return
* The {@link Collection} of dependent variables.
*/
@SuppressWarnings("null")
public Collection<Variable> getOutputs()
{
return dependentVariables.values();
}
/**
* Method used to retrieve the output with the given name.
* @param variableName
* The name of the {@link Variable} to retrieve.
* @return
* The instance of the {@link Variable} or <code>null</code>
* if no such {@link Variable} was defined.
*/
public @Nullable Variable getOutput(String variableName)
{
return dependentVariables.get(variableName);
}
/**
* Simple getter method for independentVariables.
* @return The value of independentVariables.
*/
@SuppressWarnings("null")
public Collection<Variable> getInputs()
{
return independentVariables.values();
}
/**
* Simple getter method for system.
* @return The value of system.
*/
public lu.list.itis.dkd.cps.system.System getSystem()
{
return system;
}
}
\ No newline at end of file
/**
* Copyright CRP Henri Tudor, 2014.
* All rights reserved. If you wish to use this code for any purpose,
* please contact CRP Henri Tudor's Technology Transfer Office : tto@tudor.lu
*/
package lu.list.itis.dkd.cps.system;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import com.google.common.base.Preconditions;
import lu.list.itis.dkd.cps.variable.Variable;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
/**
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 24 Feb 2014
* @version 1
*/
@NonNullByDefault
public class Equation
{
private Mapping mapping, lockedMapping;
@Nullable
private ScriptEngine scriptEngine;
private String script;
/**
* Constructor
* @param mapping
* The mapping of variables to take into account for the equation.
* @param script
* The mathematical representation of the equation in string form.
* Note that the names of the variables in the script must coincide with
* the names of the variables in the mapping.
*/
public Equation(Mapping mapping, String script)
{
this.mapping = mapping;
this.lockedMapping = mapping;
this.script = script;
}
/**
* Simple getter method for mapping.
* @return The value of mapping.
*/
public Mapping getMapping()
{
return mapping;
}
/**
* Method called to evaluate the script of the equation with
* the variables provided by the mapping.
*/
@SuppressWarnings("null")
public void evaluate()
{
Preconditions.checkState(scriptEngine != null);
try{
mapping.getDependentVariable().setValue(scriptEngine.eval(replaceVariables()));
} catch (ScriptException e) {
Logger.getLogger(Equation.class.getSimpleName()).log(Level.SEVERE, "", e);
}
}
/**
* Method used to replace variables with their actual values in the formula.
* @return
* The formula with variables replaced by their values, ready for evaluation.
*/
private String replaceVariables()
{
String result = new String(script);
for(Variable variable : lockedMapping.getIndependentVariables())
{
result = result.replaceAll(variable.getName(), variable.getValue().toString());
}
result = result.replaceAll(lockedMapping.getDependentVariable().getName(), lockedMapping.getDependentVariable().getValue().toString());
assert result != null;
return result;
}
/**
* Method for setting the script engine to use.
* @param engine
* The {@link ScriptEngine} instance to use for
* evaluating the scripted formulas.
*/
public void setScriptEngine(ScriptEngine engine)
{
scriptEngine = engine;
}
/**
* Method querying whether the {@link Equation} instance is
* affected by a change of the {@link Variable} instance and
* would need to recompute.
* @param variable
* The variable to look up.
* @return
* <code>True</code> if the {@link Variable} instance is
* an independent variable that is part of this
* {@link Equation} isntance's computation.
*/
public boolean catersTo(Variable variable)
{
return mapping.catersTo(variable);
}
/**
* Method used to make a local copy of all variables to lock
* down the state for asynchronous, clock-driven computation.
*/
public void saveState()
{
lockedMapping = mapping.lock();
}
}
\ No newline at end of file
This diff is collapsed.
package lu.list.itis.dkd.cps.system;
/**
* @author nmack
* @date 07 Apr 2015
*
* <br>$Log: EquationSystemException.java,v $
*/
//***************************************************************************
//* Class Definition and Members *
//***************************************************************************
public class EquationSystemException extends Exception
{
/**
*
*/
private static final long serialVersionUID = 7422560120940501724L;
//***************************************************************************
//* Constants *
//***************************************************************************
//---------------------------------------------------------------------------
//***************************************************************************
//* Constructor(s) *
//***************************************************************************
//---------------------------------------------------------------------------
public EquationSystemException (String reason)
{
super(reason);
}
//---------------------------------------------------------------------------
//***************************************************************************
//* Primitives *
//***************************************************************************
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//***************************************************************************
//* Class Body *
//***************************************************************************
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//***************************************************************************
//* End of Class *
//***************************************************************************
//---------------------------------------------------------------------------
}
\ No newline at end of file
/**
* Copyright CRP Henri Tudor, 2014.
* All rights reserved. If you wish to use this code for any purpose,
* please contact CRP Henri Tudor's Technology Transfer Office : tto@tudor.lu
*/
package lu.list.itis.dkd.cps.system;
import java.util.concurrent.ConcurrentHashMap;
import com.google.common.base.Preconditions;
import lu.list.itis.dkd.cps.InputEvent;
import lu.list.itis.dkd.cps.variable.Variable;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
/**
* Class implementing a system of linear equations. The class
* holds a number of equations and defines the engine that
* evaluates the equations. The class may be driven by a clock
* react to input changes synchronously.
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 21 Feb 2014
* @version 1
*/
@NonNullByDefault
public class LinearEquationSystem extends System
{
private ConcurrentHashMap<Mapping, Equation> equations;
// private ScriptEngine scriptEngine;
// private static OctaveEngine scriptEngine;
// static {
// OctaveEngineFactory l_Factory = new OctaveEngineFactory();
// l_Factory.setOctaveProgram(new File ("/opt/local/bin/octave"));
// l_Factory.setWorkingDir(new File("./octave"));
// scriptEngine = l_Factory.getScriptEngine();
// }
/**
* Constructor issuing a super call and initialising the map of
* equations.
* @param lockToNesting
* Boolean indicating whether nested systems will have their
* inputs locked during computation. Doing so will result
* in a synchronous behaviour of the system while choosing
* <code>false</code> will have the nested systems evaluate
* their equations first, possibly propagating results to
* systems higher up in the nesting tree.
*/
@SuppressWarnings("null")
public LinearEquationSystem(boolean lockToNesting)
{
super();
equations = new ConcurrentHashMap<>();
// scriptEngine = new ScriptEngineManager().getEngineByName("js");
this.lockSystemForNesting = lockToNesting;
// assert scriptEngine != null : "Script engine cannot be null;";
}
/**
* Method used for adding an {@link Equation} instance to the system.
* @param equation
* The {@link Equation} instance to add.
* @return
* An instance of the equation map for chain-calling.
*/
public ConcurrentHashMap<Mapping, Equation> addEquation(Equation equation)
{
// ((OctaveEquation)equation).setScriptEngine(scriptEngine);
// equation.setScriptEngine(scriptEngine);
equations.put(equation.getMapping(), equation);
return equations;
}
/** {@inheritDoc} */
@Override
public synchronized void clockTicked(long tick)
{
super.clockTicked(tick);
for(Equation equation : equations.values())
{
equation.evaluate();
}
}
/** {@inheritDoc} */
@SuppressWarnings("null")
@Override
public synchronized void inputChanged(InputEvent input)
{
Preconditions.checkArgument(input != null && input.getSource() != null,
"Neither the input nor the input source may be null.");
/** Invoke super method dealing with nested systems. */
super.inputChanged(input);
for(Equation equation : equations.values())
{
if(equation.catersTo((Variable) input.getSource()))
{
equation.evaluate();
}
}
}
/** {@inheritDoc} */
@Override
public void saveState()
{
for(Equation equation : equations.values())
{
equation.saveState();
}
}
}
\ No newline at end of file