All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.meliorbis.numerics.fixedpoint.IterativeFixedPointFinder Maven / Gradle / Ivy

Go to download

A library for working with large multi-dimensional arrays and the functions they represent

There is a newer version: 1.2
Show newest version
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_;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy