protected override bool Optimize()
{
Evaluations = 0;
Iterations = 0;
int length = MaxIterations;
double[] X = base.Solution;
double M = 0.0;
int iteration = 0;
int Linessearch_isfailed = 0;
// get first function eval
double f1 = Function(X);
// get first grad eval
df1 = Gradient(X);
Evaluations++;
if (length < 0)
iteration++;
// this is the steepest search directions
for (int i = 0; i < df1.Length; i++)
s[i] = -df1[i];
// this is the slope of the line in negative direction
double d1 = 0.0;
for (int j = 0; j < s.Length; j++)
d1 += -s[j] * s[j];
// initial step is red(red/|s|+1)
double z1 = Red / (1 - d1);
double[] X0 = new double[X.Length];
double[] DF0 = new double[X.Length];
while (iteration < Math.Abs(length))
{
if (Token.IsCancellationRequested)
break;
if (length > 0)
iteration++; // count epoch(iter)
Iterations = iteration;
// make copy of current values
for (int j = 0; j < X0.Length; j++)
X0[j] = X[j];
for (int j = 0; j < DF0.Length; j++)
DF0[j] = df1[j];
double F0 = f1;
// begin line search
for (int j = 0; j < X.Length; j++)
X[j] += s[j] * z1;
// evaluate cost - and gradient function with new params
double f2 = Function(X);
double[] df2 = Gradient(X);
Evaluations++;
if (length < 0)
iteration++;
double d2 = 0;
for (int i = 0; i < df2.Length; i++)
d2 += df2[i] * s[i];
// initialize point 3 equal to point 1
double f3 = f1, d3 = d1, z3 = -z1;
if (length > 0)
{
M = MAX;
}
else
{
M = Math.Min(MAX, -length - iteration);
}
// initialize quantities
double succes = 0.0;
double limit = -1.0;
while (true)
{
//f2 = 0.70;
while (((f2 > f1 + z1 * RHO * d1) || (d2 > -SIG * d1)) && (M > 0))
{
limit = z1; // tighten bracket
// values for cubic or quadratic fit
double A = 0.0d;
double B = 0.0d;
double z2 = 0.0d;
if (f2 > f1)
{
// quadratic fit
z2 = z3 - ((0.5 * d3 * z3 * z3) / (d3 * z3 + f2 - f3));
}
else
{
// cubic fit
A = (6 * (f2 - f3)) / (z3 + (3 * (d2 + d3)));
B = (3 * (f3 - f2) - (z3 * ((d3 + 2) * d2)));
// numerical error possible - ok!
z2 = Math.Sqrt(((B * B) - (A * d2 * z3)) - B) / A;
}
if (Double.IsNaN(z2) || Double.IsInfinity(z2) || Double.IsNegativeInfinity(z2))
{
z2 = z3 / 2.0;
}
// don't accept too close to limit
z2 = Math.Max(Math.Min(z2, INT * z3), (1 - INT) * z3);
z1 = z1 + z2; // update this step
for (int j = 0; j < X.Length; j++)
X[j] += s[j] * z2;
f2 = Function(X);
df2 = Gradient(X);
Evaluations++;
M = M - 1;
// count epochs
if (length < 0)
iteration++;
// new slope
d2 = 0.0;
for (int i = 0; i < df2.Length; i++)
d2 += df2[i] * s[i];
// z3 is now relative to the location of z2
z3 = z3 - z2;
}
if (f2 > (f1 + z1 * RHO * d1) || d2 > (-SIG * d1))
{
// this is a failure
break;
}
else if (d2 > (SIG * d1))
{
succes = 1.0;
break; // success
}
else if (M == 0)
{
break; // failure
}
// Make cubic extrapolation
var A1 = 6 * (f2 - f3) / z3 + 3 * (d2 + d3);
var B1 = 3 * (f3 - f2) - z3 * (d3 + 2 * d2);
var z21 = -d2 * z3 * z3 / (B1 + Math.Sqrt(B1 * B1 - A1 * d2 * z3 * z3));
if (z21 < 0)
{
z21 = z21 * -1;
}
// num prop or wrong sign ?
if (double.IsNaN(z21) || double.IsInfinity(z21) || z21 < 0)
{
if (limit < -0.5) // no upper limit
{
z21 = z1 * (EXT - 1);
}
else
{
z21 = (limit - z1) / 2;
}
}
else if (limit > -0.5 && (z21 + z1 > limit))
{
z21 = (limit - z1) / 2;
}
else if (limit < -0.5 && (z21 + z1 > z1 * EXT))
{
z21 = z1 * (EXT - 1.0);
}
else if (z21 < -z3 * INT)
{
z21 = -z3 * INT;
}
else if ((limit > -0.5) && (z21 < (limit - z1) * (1.0 - INT)))
{
z21 = (limit - z1) * (1.0 - INT);
}
// set point 3 equal to point 2
f3 = f2;
d3 = d2;
z3 = -z21;
z1 = z1 + z21;
// update current estimate
for (int j = 0; j < X.Length; j++)
X[j] += s[j] * z21;
// evaluate functions
df2 = Gradient(X);
f2 = Function(X);
M = M - 1;
iteration = iteration + (length < 0 ? 1 : 0); // count epochs
d2 = 0;
for (int i = 0; i < df2.Length; i++)
d2 += df2[i] * s[i];
}// end of line search
if (succes == 1.0) // if line searched succeded
{
f1 = f2;
// Polack- Ribiere direction
var ptemp1 = df2.Dot(df2) - df1.Dot(df2);
var ptemp2 = df1.Dot(df1);
var ptemp3 = ptemp1 / ptemp2;
for (int j = 0; j < s.Length; j++)
s[j] = s[j] * ptemp3 - df2[j];
// swap derivatives
var tmp = df1;
df1 = df2;
df2 = tmp;
// get slope
d2 = 0;
for (int i = 0; i < df1.Length; i++)
d2 += df1[i] * s[i];
// new slope must be negative
if (d2 > 0)
{
// use steepest direction
for (int i = 0; i < s.Length; i++)
s[i] = -df1[i];
d2 = 0;
for (int i = 0; i < df1.Length; i++)
d2 -= s[i] * s[i];
}
// slope ration but max ratio
z1 = z1 * Math.Min(RATIO, (d1 / (d2 - 2.2251e-308)));
d1 = d2;
Linessearch_isfailed = 0; // this linesearch did not fail
}
else
{
// restore point from before failed line search
f1 = F0;
for (int j = 0; j < X.Length; j++)
X[j] = X0[j];
for (int j = 0; j < df1.Length; j++)
df1[j] = DF0[j];
// line search twice in a row
if (Linessearch_isfailed == 1 || iteration > Math.Abs(length))
{
break; // or we ran out of time , so we give up
}
var tmp = df1;
df1 = df2;
df2 = tmp; // swap derivatives
for (int i = 0; i < df1.Length; i++)
s[i] = -df1[i];
d1 = 0;
for (int i = 0; i < s.Length; i++)
d1 -= s[i] * s[i];
z1 = 1d / (1d - d1);
Linessearch_isfailed = 1; // this line search failed
}
}
Value = f1;
return true;
}
}