com.meliorbis.numerics.fixedpoint.IterativeFixedPointFinder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Numerics Show documentation
Show all versions of Numerics Show documentation
A library for working with large multi-dimensional arrays and the functions they represent
package com.meliorbis.numerics.fixedpoint;
import org.apache.commons.lang.ArrayUtils;
import com.meliorbis.numerics.NumericsException;
import com.meliorbis.numerics.function.MultiVariateVectorFunction;
/**
* Created by toby on 28/01/2014.
*/
public class IterativeFixedPointFinder implements FixedPointFinder
{
private final Double _precision;
private Double _damping;
public IterativeFixedPointFinder(Double precision_, Double damping_)
{
_precision = precision_;
_damping = damping_;
}
@Override
public double[] findFixedPoint(MultiVariateVectorFunction function_, double[] initialVals_)
{
Double error;
Double[] currentInputs = ArrayUtils.toObject(initialVals_.clone());
// Makes it easier to switch to relatively sized adjustments
Double lastDelta[] = new Double[initialVals_.length];
int backTrack = 0;
Double lastError = Double.POSITIVE_INFINITY;
do
{
try
{
error =0d;
Double[] implied = function_.call(currentInputs);
// Compare each one to the assumed state and update the criterion to be the maximum relative difference
for(int varIndex = 0; varIndex < currentInputs.length; varIndex++)
{
if(Double.isNaN(implied[varIndex]))
{
throw new NumericsException("fn returned NaN");
}
Double currError = Math.abs(implied[varIndex] - currentInputs[varIndex]);
if(error < currError)
{
error = currError;
}
}
// Solution found!
if(error < _precision)
{
return ArrayUtils.toPrimitive(currentInputs);
}
System.out.println(String.format("Current distance: %s", error));
// Check that the error has not increased
if(error > lastError)
{
throw new RuntimeException(String.format("Error Increased from %s to %s",lastError, error));
}
// Remember the error for next time
lastError = error;
// Determine the jump by moving toward the implied in all dimensions
for(int i = 0; i < currentInputs.length; i++)
{
lastDelta[i] = (implied[i] - currentInputs[i])*_damping;
currentInputs[i] += lastDelta[i];
}
// Reset the backtrack
backTrack = 0;
} catch (Exception e)
{
System.out.println("Caught Exception: " + e.getMessage());
//e.printStackTrace();
System.out.println(String.format("Backtracking (%s times so far)",++backTrack));
if(backTrack > 10)
{
throw new RuntimeException("Found local maximum but not fixed point");
}
// Go half way back to last known good
for(int i = 0; i < currentInputs.length; i++)
{
lastDelta[i] /= 2;
currentInputs[i] -= lastDelta[i];
}
}
}
while(true);
}
@Override
public void setDamping(double damping_)
{
_damping = damping_;
}
}