Commit e896f500 authored by Eric Tobias's avatar Eric Tobias

Changed CPS to no longer use Octave by default

parent 64f96cf6
......@@ -40,5 +40,10 @@
<artifactId>javaoctave</artifactId>
<version>0.6.5-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</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
* 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 lu.list.itis.dkd.cps.variable.Variable;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import com.google.common.base.Preconditions;
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;
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;
}
/**
* 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;
}
/**
* 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.
*/
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, "Exception while executing script!", e); //$NON-NLS-1$
}
}
/**
* 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);
/**
* 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());
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;
}
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 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 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();
}
/**
* 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
/**
* 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
* 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;
import com.google.common.base.Preconditions;
import java.util.concurrent.ConcurrentHashMap;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
/**
* 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
* 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 1.0
* @version 1.2.0
*/
@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();
// }
@NonNullByDefault
public class LinearEquationSystem extends System {
private ConcurrentHashMap<Mapping, Equation> equations;
private ScriptEngine scriptEngine;
/**
* 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.
*/
public LinearEquationSystem(boolean lockToNesting) {
super();
equations = new ConcurrentHashMap<>();
scriptEngine = new ScriptEngineManager().getEngineByName("js"); //$NON-NLS-1$
this.lockSystemForNesting = lockToNesting;
assert scriptEngine != null : "Script engine cannot be null;"; //$NON-NLS-1$
}
/**
* 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) {
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();
}
}
/**
* 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 inputChanged(InputEvent input) {
Preconditions.checkArgument(input != null && input.getSource() != null,
"Neither the input nor the input source may be null."); //$NON-NLS-1$
/** {@inheritDoc} */
@Override
public synchronized void clockTicked(long tick)
{
super.clockTicked(tick);
for(Equation equation : equations.values())
{
equation.evaluate();
}
}
/** Invoke super method dealing with nested systems. */
super.inputChanged(input);
/** {@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();
}
}
}
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();
}
}
/** {@inheritDoc} */
@Override
public void saveState() {
for (Equation equation : equations.values()) {
equation.saveState();
}
}
}
\ 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
* 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.LinkedHashSet;
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;
import com.google.common.base.Preconditions;
import java.util.LinkedHashSet;
/**
* Class describing the mapping between a set of input
* variables and an output variable. The order of input
* variables is preserved and essential when defining the
* equation.
* @author Eric TOBIAS [eric.tobias@tudor.lu]
* @since 24 Feb 2014
* @version 1
* Class describing the mapping between a set of input variables and an output variable. The order
* of input variables is preserved and essential when defining the equation.
*
* @author Eric Tobias [eric.tobias@tudor.lu]
* @since 1.0
* @version 1.2.0
*/
@NonNullByDefault
public class Mapping
{
private LinkedHashSet<Variable> independentVariables;
private Variable dependentVariable;
/**
* Constructor initialising the mapping.
* @param independentVariables
* The independent variables of the mapping.
* @param dependentVariable
* The dependent variable of the mapping.
*/
public Mapping(LinkedHashSet<Variable> independentVariables, Variable dependentVariable)
{
Preconditions.checkArgument(! independentVariables.isEmpty(), "The set of input variables cannot be empty.");
this.independentVariables = independentVariables;
this.dependentVariable = dependentVariable;
}
/**
* Simple getter method for independentVariables.
* @return The value of independentVariables.
*/
public LinkedHashSet<Variable> getIndependentVariables()
{
return independentVariables;
}
/**
* Simple getter method for dependentVariable.
* @return The value of dependentVariable.
*/
public Variable getDependentVariable()
{
return dependentVariable;
}
/** {@inheritDoc} */
@SuppressWarnings("null")
@Override
public String toString()
{
String separator = "";
StringBuilder renderer = new StringBuilder ();
for(Variable variable : independentVariables)
{
renderer.append(separator).append(variable.getName());
separator = ", ";
}
renderer.append(" => ").append(dependentVariable.getName());
return renderer.toString();
// String result = "";
// for(Variable variable : independentVariables)
// {
// result = result.concat(variable.getName() + ", ");
// }
//
// return result.trim().substring(0, result.length() - 2).concat(" => " + dependentVariable.getName());
}
/**
* {@inheritDoc}<br><br>
*
* The method invocation will compute the hash code based
* on the {@link #toString()} output.
*/
@Override
public int hashCode()
{
return toString().hashCode();
}
/** {@inheritDoc} */
@Override
public boolean equals(@Nullable Object object)
{
if(object == null) return false;
if(object == this) return true;
if(object instanceof Mapping)
{
Mapping mapping = (Mapping) object;
if(mapping.toString().equals(toString()))
{
return true;
}
}
return false;
}
/**
* Method querying whether the {@link Mapping} instance holds
* the {@link Variable} instance given as a parameter as an
* independent {@link Variable} instance.
* @param variable
* The variable to look up.
* @return
* <code>True</code> if the {@link Variable} instance is
* an independent variable managed by this {@link Mapping}
* instance.
*/
public boolean catersTo(Variable variable)
{
for(Variable _variable : independentVariables)
{
if(_variable.equals(variable))
{
return true;
}
}
//return (independentVariables.contains(variable));
return false;
}
/**
* Method for locking the mapping; cloning all variables such
* that they may not be influenced by the evaluation of the
* equation.
* @return
* A deep copy of the {@link Mapping}.
*/
public Mapping lock()
{
LinkedHashSet<Variable> clones = new LinkedHashSet<>();
for(Variable variable : independentVariables)
{
clones.add(variable.clone());
}
return new Mapping(clones, dependentVariable.clone());
}
public class Mapping {
private LinkedHashSet<Variable> independentVariables;
private Variable dependentVariable;
/**
* Constructor initialising the mapping.
*
* @param independentVariables
* The independent variables of the mapping.
* @param dependentVariable
* The dependent variable of the mapping.
*/
public Mapping(LinkedHashSet<Variable> independentVariables, Variable dependentVariable) {
Preconditions.checkArgument(!independentVariables.isEmpty(), "The set of input variables cannot be empty."); //$NON-NLS-1$
this.independentVariables = independentVariables;
this.dependentVariable = dependentVariable;
}
/**
* Simple getter method for independentVariables.
*
* @return The value of independentVariables.
*/
public LinkedHashSet<Variable> getIndependentVariables() {
return independentVariables;
}
/**
* Simple getter method for dependentVariable.
*
* @return The value of dependentVariable.
*/
public Variable getDependentVariable() {
return dependentVariable;
}
/** {@inheritDoc} */
@Override
public String toString() {
String separator = ""; //$NON-NLS-1$
StringBuilder renderer = new StringBuilder();
for (Variable variable : independentVariables) {
renderer.append(separator).append(variable.getName());
separator = ", "; //$NON-NLS-1$
}
renderer.append(" => ").append(dependentVariable.getName()); //$NON-NLS-1$
return renderer.toString();
}
/**
* {@inheritDoc}<br>
* <br>
*
* The method invocation will compute the hash code based on the {@link #toString()} output.
*/
@Override
public int hashCode() {
return toString().hashCode();
}
/** {@inheritDoc} */
@Override
public boolean equals(@Nullable Object object) {
if (object == null)
return false;
if (object == this)
return true;
if (object instanceof Mapping) {
Mapping mapping = (Mapping) object;
if (mapping.toString().equals(toString())) {
return true;
}
}
return false;
}
/**
* Method querying whether the {@link Mapping} instance holds the {@link Variable} instance
* given as a parameter as an independent {@link Variable} instance.
*
* @param variable
* The variable to look up.
* @return <code>True</code> if the {@link Variable} instance is an independent variable managed
* by this {@link Mapping} instance.
*/
public boolean catersTo(Variable variable) {
for (Variable _variable : independentVariables) {
if (_variable.equals(variable)) {
return true;
}
}
return (independentVariables.contains(variable));
}
/**
* Method for locking the mapping; cloning all variables such that they may not be influenced by
* the evaluation of the equation.
*
* @return A deep copy of the {@link Mapping}.
*/
public Mapping lock() {
LinkedHashSet<Variable> clones = new LinkedHashSet<>();
for (Variable variable : independentVariables) {
clones.add(variable.clone());
}