using System;
namespace Legalsoft.Truffer
{
public class Frprmn : Dlinemethod
{
private int iter { get; set; }
private double fret { get; set; }
private double ftol { get; set; }
public Frprmn(RealValueFunWithDiff funcd, double ftoll = 3.0e-8) : base(funcd)
{
this.ftol = ftoll;
}
public double[] minimize(double[] pp)
{
const int ITMAX = 200;
const double EPS = 1.0e-18;
const double GTOL = 1.0e-8;
int n = pp.Length;
//p = pp;
p = Globals.CopyFrom(pp);
double[] g = new double[n];
double[] h = new double[n];
//xi.resize(n);
xi = new double[n];
double fp = func.funk(p);
func.df(p, xi);
for (int j = 0; j < n; j++)
{
g[j] = -xi[j];
xi[j] = h[j] = g[j];
}
for (int its = 0; its < ITMAX; its++)
{
iter = its;
fret = linmin();
if (2.0 * Math.Abs(fret - fp) <= ftol * (Math.Abs(fret) + Math.Abs(fp) + EPS))
{
return p;
}
fp = fret;
func.df(p, xi);
double test = 0.0;
double den = Math.Max(Math.Abs(fp), 1.0);
for (int j = 0; j < n; j++)
{
double temp = Math.Abs(xi[j]) * Math.Max(Math.Abs(p[j]), 1.0) / den;
if (temp > test)
{
test = temp;
}
}
if (test < GTOL)
{
return p;
}
double dgg = 0.0;
double gg = 0.0;
for (int j = 0; j < n; j++)
{
gg += g[j] * g[j];
// dgg += xi[j]*xi[j];
dgg += (xi[j] + g[j]) * xi[j];
}
//if (gg == 0.0)
if (Math.Abs(gg) <= float.Epsilon)
{
return p;
}
double gam = dgg / gg;
for (int j = 0; j < n; j++)
{
g[j] = -xi[j];
xi[j] = h[j] = g[j] + gam * h[j];
}
}
throw new Exception("Too many iterations in frprmn");
}
}
}