gov.sandia.cognition.math.signals.LinearDynamicalSystem Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cognitive-foundry Show documentation
Show all versions of cognitive-foundry Show documentation
A single jar with all the Cognitive Foundry components.
/*
* File: LinearDynamicalSystem.java
* Authors: Kevin R. Dixon
* Company: Sandia National Laboratories
* Project: Cognitive Foundry
*
* Copyright June 1, 2007, Sandia Corporation. Under the terms of Contract
* DE-AC04-94AL85000, there is a non-exclusive license for use of this work by
* or on behalf of the U.S. Government. Export of this program may require a
* license from the United States Government. See CopyrightHistory.txt for
* complete details.
*
*/
package gov.sandia.cognition.math.signals;
import gov.sandia.cognition.annotation.PublicationReference;
import gov.sandia.cognition.annotation.PublicationReferences;
import gov.sandia.cognition.annotation.PublicationType;
import gov.sandia.cognition.evaluator.AbstractStatefulEvaluator;
import gov.sandia.cognition.math.matrix.Matrix;
import gov.sandia.cognition.math.matrix.MatrixFactory;
import gov.sandia.cognition.math.matrix.Vector;
import gov.sandia.cognition.math.matrix.VectorFactory;
import gov.sandia.cognition.math.matrix.VectorInputEvaluator;
import gov.sandia.cognition.math.matrix.VectorOutputEvaluator;
import gov.sandia.cognition.math.matrix.VectorizableVectorFunction;
import gov.sandia.cognition.util.ObjectUtil;
/**
* A generic Linear Dynamical System of the form
*
x_n = A*x_(n-1) + B*u_n
*
y_n = C*x_n,
*
* where x_(n-1) is the previous state, x_n is the current state, u_n is the
* current input, y_n is the current output, A is the system matrix, B is the
* input-gain matrix, and C is the output-selector matrix
*
* @author Kevin R. Dixon
* @since 1.0
*
*/
@PublicationReferences(
references={
@PublicationReference(
author="Norman S. Nise",
title="Control Systems Engineering, Second Edition",
type=PublicationType.Book,
year=1995,
pages={648,702},
notes="Chapter 12"
)
,
@PublicationReference(
author="Wikipedia",
title="Linear dynamical system",
type=PublicationType.WebPage,
year=2008,
url="http://en.wikipedia.org/wiki/Linear_dynamical_system",
notes="This Wikipedia page is simply horrible..."
)
}
)
public class LinearDynamicalSystem
extends AbstractStatefulEvaluator
implements VectorizableVectorFunction,
VectorInputEvaluator,
VectorOutputEvaluator
{
/**
* System (Jacobian) matrix. Must be square.
*/
private Matrix A;
/**
* Input-gain matrix. Columns must equal A's rows.
*/
private Matrix B;
/**
* Output-selector matrix. Columns must equal A's rows.
*/
private Matrix C;
/**
* Default constructor.
*/
public LinearDynamicalSystem()
{
this( 1, 1 );
}
/**
* Creates a new instance of LinearDynamicalSystem.
* @param inputDimensionality
* Dimensionality of the input Vectors.
* @param stateDimensionality
* Dimensionality of the state Vectors.
*/
public LinearDynamicalSystem(
int inputDimensionality,
int stateDimensionality )
{
this( inputDimensionality, stateDimensionality, stateDimensionality );
}
/**
* Creates a new instance of LinearDynamicalSystem.
* @param inputDimensionality
* Dimensionality of the input Vectors.
* @param stateDimensionality
* Dimensionality of the state Vectors.
* @param outputDimensionality
* Dimensionality of the output Vectors.
*/
public LinearDynamicalSystem(
int inputDimensionality,
int stateDimensionality,
int outputDimensionality )
{
this( MatrixFactory.getDefault().createIdentity(stateDimensionality,stateDimensionality),
MatrixFactory.getDefault().createMatrix(stateDimensionality,inputDimensionality),
MatrixFactory.getDefault().createIdentity(outputDimensionality,stateDimensionality) );
}
/**
* Creates a new instance of LinearDynamicalSystem
* @param A
* System (Jacobian) matrix. Must be square.
* @param B
* Input-gain matrix. Columns must equal A's rows.
*/
public LinearDynamicalSystem(
Matrix A,
Matrix B )
{
this( A, B, MatrixFactory.getDefault().createIdentity(A.getNumRows(), A.getNumRows()) );
}
/**
* Creates a new instance of LinearDynamicalSystem
* @param A
* System (Jacobian) matrix. Must be square.
* @param B
* Input-gain matrix. Columns must equal A's rows.
* @param C
* Output-selector matrix. Columns must equal A's rows.
*/
public LinearDynamicalSystem(
Matrix A,
Matrix B,
Matrix C )
{
if( !A.isSquare() )
{
throw new IllegalArgumentException( "A must be square!" );
}
if( A.getNumRows() != B.getNumRows() )
{
throw new IllegalArgumentException(
"A and B must have same number of rows!" );
}
if( A.getNumRows() != C.getNumColumns() )
{
throw new IllegalArgumentException(
"Number of A rows must equal number of C columns!" );
}
this.setA(A);
this.setB(B);
this.setC(C);
}
@Override
public LinearDynamicalSystem clone()
{
LinearDynamicalSystem clone = (LinearDynamicalSystem) super.clone();
clone.setA( ObjectUtil.cloneSafe( this.getA() ) );
clone.setB( ObjectUtil.cloneSafe( this.getB() ) );
clone.setC( ObjectUtil.cloneSafe( this.getC() ) );
return clone;
}
public Vector createDefaultState()
{
return VectorFactory.getDefault().createVector(
this.getStateDimensionality());
}
public Vector evaluate(
Vector input)
{
Vector xnm1 = this.getState();
Vector xn = A.times(xnm1);
xn.plusEquals( B.times(input) );
this.setState(xn);
return C.times(xn);
}
public Vector convertToVector()
{
return this.A.convertToVector().stack( this.B.convertToVector() );
}
public void convertFromVector(
Vector parameters)
{
int Adim = this.A.getNumRows() * this.A.getNumColumns();
int Bdim = this.B.getNumRows() * this.B.getNumColumns();
if( Adim+Bdim != parameters.getDimensionality() )
{
throw new IllegalArgumentException(
"Number of parameters doesn't equal A and B elements!" );
}
Vector av = parameters.subVector(0, Adim-1);
Vector bv = parameters.subVector(Adim,parameters.getDimensionality()-1);
this.A.convertFromVector(av);
this.B.convertFromVector(bv);
}
public int getInputDimensionality()
{
return this.B.getNumColumns();
}
public int getOutputDimensionality()
{
return this.C.getNumRows();
}
/**
* Gets the dimensionality of the state.
* @return
* Dimensionality of the state.
*/
public int getStateDimensionality()
{
return this.A.getNumRows();
}
@Override
public String toString()
{
StringBuffer retval = new StringBuffer( 1000 );
retval.append( "x = " + this.getState() + "\n" );
retval.append( "A =\n" + this.getA() + "\n" );
retval.append( "B = \n" + this.getB() + "\n" );
retval.append( "C = \n" + this.getC() + "\n" );
return retval.toString();
}
/**
* Getter for A.
* @return
* System (Jacobian) matrix. Must be square.
*/
public Matrix getA()
{
return this.A;
}
/**
* Setter for A.
* @param A
* System (Jacobian) matrix. Must be square.
*/
public void setA(
Matrix A)
{
this.A = A;
}
/**
* Getter for B.
* @return
* Input-gain matrix. Columns must equal A's rows.
*/
public Matrix getB()
{
return this.B;
}
/**
* Setter for B.
* @param B
* Input-gain matrix. Columns must equal A's rows.
*/
public void setB(
Matrix B)
{
this.B = B;
}
/**
* Getter for C.
* @return
* Output-selector matrix. Columns must equal A's rows.
*/
public Matrix getC()
{
return this.C;
}
/**
* Setter for C.
* @param C
* Output-selector matrix. Columns must equal A's rows.
*/
public void setC(
Matrix C)
{
this.C = C;
}
}