public OptimizationProgressEventArgs[] Actual(Specification problem) { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(problem.Variables) { Corrections = m, Epsilon = epsilon, Past = past, Delta = delta, MaxIterations = max_iterations, LineSearch = (LineSearch)linesearch, MaxLineSearch = max_linesearch, MinStep = min_step, MaxStep = max_step, ParameterTolerance = ftol, Wolfe = wolfe, GradientTolerance = gtol, FunctionTolerance = xtol, OrthantwiseC = orthantwise_c, OrthantwiseStart = orthantwise_start, OrthantwiseEnd = orthantwise_end }; target.Function = problem.Function; target.Gradient = problem.Gradient; actual.Clear(); target.Progress += new EventHandler <OptimizationProgressEventArgs>(target_Progress); target.Minimize((double[])problem.Start.Clone()); ActualMessage = target.Status.GetDescription(); return(actual.ToArray()); }
public void ConstructorTest2() { Func <double[], double> function = // min f(x) = 10 * (x+1)^2 + y^2 x => 10.0 * Math.Pow(x[0] + 1.0, 2.0) + Math.Pow(x[1], 2.0); Func <double[], double[]> gradient = x => new[] { 20 * (x[0] + 1), 2 * x[1] }; double[] start = new double[2]; BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2, function.Invoke, gradient.Invoke); Assert.IsTrue(target.Minimize()); double minimum = target.Value; double[] solution = target.Solution; Assert.AreEqual(0, minimum, 1e-10); Assert.AreEqual(-1, solution[0], 1e-5); Assert.AreEqual(0, solution[1], 1e-5); double expectedMinimum = function(target.Solution); Assert.AreEqual(expectedMinimum, minimum); }
/// <summary> /// Runs the learning algorithm with the specified input /// training observations and corresponding output labels. /// </summary> /// /// <param name="observations">The training observations.</param> /// <param name="labels">The observation's labels.</param> /// public double Run(T[][] observations, int[][] labels) { double f; double[] g; lbfgs.Function = parameters => { model.Function.Weights = parameters; f = -model.LogLikelihood(observations, labels); return(f); }; lbfgs.Gradient = parameters => { model.Function.Weights = parameters; g = gradient(observations, labels); return(g); }; try { double ll = lbfgs.Minimize(model.Function.Weights); } catch (LineSearchFailedException) { // TODO: Restructure L-BFGS to avoid exceptions. } model.Function.Weights = lbfgs.Solution; return(model.LogLikelihood(observations, labels)); }
public void lbfgsTest3() { Accord.Math.Tools.SetupGenerator(0); Func <double[], double> f; Func <double[], double[]> g; createExpDiff(out f, out g); int errors = 0; for (int i = 0; i < 10000; i++) { double[] start = Accord.Math.Matrix.Random(2, -1.0, 1.0); var lbfgs = new BroydenFletcherGoldfarbShanno(numberOfVariables: 2, function: f, gradient: g); lbfgs.Minimize(start); double minValue = lbfgs.Value; double[] solution = lbfgs.Solution; double expected = -2; if (Math.Abs(expected - minValue) > 1e-3) { errors++; } } Assert.IsTrue(errors < 800); }
public void lbfgsTest() { Func <double[], double> f = rosenbrockFunction; Func <double[], double[]> g = rosenbrockGradient; Assert.AreEqual(104, f(new[] { -1.0, 2.0 })); int n = 2; // number of variables double[] initial = { -1.2, 1 }; BroydenFletcherGoldfarbShanno lbfgs = new BroydenFletcherGoldfarbShanno(n, f, g); double actual = lbfgs.Minimize(initial); double expected = 0; Assert.AreEqual(expected, actual, 1e-10); double[] result = lbfgs.Solution; Assert.AreEqual(49, lbfgs.Evaluations); Assert.AreEqual(40, lbfgs.Iterations); Assert.AreEqual(0.99999999999963229, result[0]); Assert.AreEqual(0.99999999999924027, result[1]); double y = f(result); double[] d = g(result); Assert.AreEqual(1.9432410039142452E-25, y); Assert.AreEqual(0.0000000000089901419642010907, d[0]); Assert.AreEqual(-0.0000000000048627768478581856, d[1]); }
public void lbfgsTest2() { #region doc_minimize // Ensure that results are reproducible Accord.Math.Random.Generator.Seed = 0; // Suppose we would like to find the minimum of the function // // f(x,y) = -exp{-(x-1)²} - exp{-(y-2)²/2} // // First we need write down the function either as a named // method, an anonymous method or as a lambda function: Func <double[], double> f = (x) => - Math.Exp(-Math.Pow(x[0] - 1, 2)) - Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2)); // Now, we need to write its gradient, which is just the // vector of first partial derivatives del_f / del_x, as: // // g(x,y) = { del f / del x, del f / del y } // Func <double[], double[]> g = (x) => new double[] { // df/dx = {-2 e^(- (x-1)^2) (x-1)} 2 * Math.Exp(-Math.Pow(x[0] - 1, 2)) * (x[0] - 1), // df/dy = {- e^(-1/2 (y-2)^2) (y-2)} Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2)) * (x[1] - 2) }; // Finally, we create a L-BFGS solver for the two variable problem: var lbfgs = new BroydenFletcherGoldfarbShanno(numberOfVariables: 2) { Function = f, Gradient = g }; // And then minimize the function: bool success = lbfgs.Minimize(); // should be true double minValue = lbfgs.Value; // should be -2 double[] solution = lbfgs.Solution; // should be (1, 2) // The resultant minimum value should be -2, and the solution // vector should be { 1.0, 2.0 }. The answer can be checked on // Wolfram Alpha by clicking the following the link: // http://www.wolframalpha.com/input/?i=maximize+%28exp%28-%28x-1%29%C2%B2%29+%2B+exp%28-%28y-2%29%C2%B2%2F2%29%29 #endregion Assert.IsTrue(success); double expected = -2; Assert.AreEqual(expected, minValue, 1e-10); Assert.AreEqual(1, solution[0], 1e-3); Assert.AreEqual(2, solution[1], 1e-3); }
public void NoGradientTest() { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2) { Function = (x) => 0.0 }; target.Minimize(); }
public void WrongGradientSizeTest() { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2) { Function = (x) => 0.0, Gradient = (x) => new double[1] }; target.Minimize(); }
public void MutableGradientSizeTest() { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2) { Function = (x) => 0.0, Gradient = (x) => x }; target.Minimize(); }
public void MutableGradientSizeTest() { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2) { Function = (x) => 0.0, Gradient = (x) => x }; Assert.Throws <InvalidOperationException>(() => target.Minimize(), ""); }
public void NoGradientTest() { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2) { Function = (x) => 0.0 }; Assert.IsTrue(target.Minimize()); // The optimizer should use finite differences as the gradient }
public static double[] InverseKinematics(List <MDHParameters> dht, double[] target, ref bool success) { Func <double[], double> f = x => Distance(dht, target, x); var calculator = new FiniteDifferences(dht.Count, f); Func <double[], double[]> g = calculator.Gradient; var optimizer = new BroydenFletcherGoldfarbShanno(numberOfVariables: dht.Count, function: f, gradient: g); optimizer.Minimize(); success = !(optimizer.Value >= 0.01); return(optimizer.Solution); }
public void lbfgsTest2() { Accord.Math.Tools.SetupGenerator(0); // Suppose we would like to find the minimum of the function // // f(x,y) = -exp{-(x-1)²} - exp{-(y-2)²/2} // // First we need write down the function either as a named // method, an anonymous method or as a lambda function: Func <double[], double> f = (x) => - Math.Exp(-Math.Pow(x[0] - 1, 2)) - Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2)); // Now, we need to write its gradient, which is just the // vector of first partial derivatives del_f / del_x, as: // // g(x,y) = { del f / del x, del f / del y } // Func <double[], double[]> g = (x) => new double[] { // df/dx = {-2 e^(- (x-1)^2) (x-1)} 2 * Math.Exp(-Math.Pow(x[0] - 1, 2)) * (x[0] - 1), // df/dy = {- e^(-1/2 (y-2)^2) (y-2)} Math.Exp(-0.5 * Math.Pow(x[1] - 2, 2)) * (x[1] - 2) }; // Finally, we can create the L-BFGS solver, passing the functions as arguments var lbfgs = new BroydenFletcherGoldfarbShanno(numberOfVariables: 2, function: f, gradient: g); // And then minimize the function: double minValue = lbfgs.Minimize(); double[] solution = lbfgs.Solution; // The resultant minimum value should be -2, and the solution // vector should be { 1.0, 2.0 }. The answer can be checked on // Wolfram Alpha by clicking the following the link: // http://www.wolframalpha.com/input/?i=maximize+%28exp%28-%28x-1%29%C2%B2%29+%2B+exp%28-%28y-2%29%C2%B2%2F2%29%29 double expected = -2; Assert.AreEqual(expected, minValue, 1e-10); Assert.AreEqual(1, solution[0], 1e-6); Assert.AreEqual(2, solution[1], 1e-6); }
public void lbfgsTest() { Func <double[], double> f = rosenbrockFunction; Func <double[], double[]> g = rosenbrockGradient; Assert.AreEqual(104, f(new[] { -1.0, 2.0 })); int n = 2; // number of variables double[] initial = { -1.2, 1 }; var lbfgs = new BroydenFletcherGoldfarbShanno(n, f, g); double expected = 0; Assert.IsTrue(lbfgs.Minimize(initial)); bool success = lbfgs.Minimize(); double actual = lbfgs.Value; Assert.IsTrue(success); Assert.AreEqual(expected, actual, 1e-10); double[] result = lbfgs.Solution; Assert.AreEqual(1.0, result[0], 1e-5); Assert.AreEqual(1.0, result[1], 1e-5); double y = f(result); double[] d = g(result); Assert.AreEqual(0, y, 1e-10); Assert.AreEqual(0, d[0], 1e-6); Assert.AreEqual(0, d[1], 1e-6); }
public static double[] Learn(double[][] X, double[] Y, double[] weights, double lambda = 0) { var optimizationAlgorithm = new BroydenFletcherGoldfarbShanno(weights.Length); double m = Y.Length; optimizationAlgorithm.Function = (double[] t) => (1.0 / 2.0 * m) * (X.Dot(t).Subtract(Y).Pow(2).Sum()) + (lambda / 2.0 * m) * (t.Pow(2).Sum()); optimizationAlgorithm.Gradient = (double[] t) => X.TransposeAndDot(X.Dot(t).Subtract(Y)).Divide(m).Add(t.Multiply(lambda / m)); optimizationAlgorithm.Minimize(weights); return(optimizationAlgorithm.Solution .To <double[]>()); }
/// <summary> /// Runs the learning algorithm with the specified input /// training observations and corresponding output labels. /// </summary> /// /// <param name="observations">The training observations.</param> /// <param name="outputs">The observation's labels.</param> /// public double RunEpoch(T[][] observations, int[] outputs) { this.Inputs = observations; this.Outputs = outputs; try { lbfgs.Minimize(Model.Function.Weights); } catch (LineSearchFailedException) { // TODO: Restructure LBFGS to avoid exceptions. } Model.Function.Weights = lbfgs.Solution; return(Model.LogLikelihood(observations, outputs)); }
/// <summary> /// Runs the learning algorithm with the specified input /// training observations and corresponding output labels. /// </summary> /// /// <param name="observations">The training observations.</param> /// <param name="outputs">The observation's labels.</param> /// public double Run(T[][] observations, int[] outputs) { calculator.Inputs = observations; calculator.Outputs = outputs; try { lbfgs.Minimize(Model.Function.Weights); } catch (LineSearchFailedException) { // TODO: Restructure L-BFGS to avoid exceptions. } Model.Function.Weights = lbfgs.Solution; // Return negative log-likelihood as error function return(-Model.LogLikelihood(observations, outputs)); }
public void InvalidLineSearchTest2() { int n = 10; Func <double[], double> function = (parameters) => { return(-(n * Math.Log(0) - n * Math.Log(Math.PI))); }; Func <double[], double[]> gradient = (parameters) => { return(new[] { 2.0, Double.NegativeInfinity }); }; double[] start = { 0, 0 }; var lbfgs = new BroydenFletcherGoldfarbShanno(2, function, gradient); bool success = lbfgs.Minimize(start); Assert.IsFalse(success); }
public static void FitCTF(float2[] data, float[] simulation, float[] zeros, float[] peaks, out Cubic1D background, out Cubic1D scale) { if (zeros.Length < 2 || peaks.Length < 1) { background = new Cubic1D(new[] { new float2(0, 0), new float2(1, 0) }); scale = new Cubic1D(new[] { new float2(0, 1), new float2(1, 1) }); return; } float MinX = MathHelper.Min(data.Select(p => p.X)), MaxX = MathHelper.Max(data.Select(p => p.X)), ScaleX = 1f / (MaxX - MinX); peaks = peaks.Where(v => v >= MinX && v <= MaxX).Where((v, i) => i % 1 == 0).ToArray(); zeros = zeros.Where(v => v >= MinX && v <= MaxX).Where((v, i) => i % 1 == 0).ToArray(); List <float2> Peaks = new List <float2>(), Zeros = new List <float2>(); foreach (var zero in zeros) { int Pos = (int)((zero - MinX) * ScaleX * data.Length); int First = Math.Max(0, Pos - 1); int Last = Math.Min(data.Length - 1, Pos + 1); float MinVal = data[First].Y; for (int i = First; i < Last; i++) { MinVal = Math.Min(MinVal, data[i].Y); } Zeros.Add(new float2(zero, MinVal)); } float[] Background = (new Cubic1D(Zeros.ToArray())).Interp(data.Select(v => v.X).ToArray()); float2[] DataSubtracted = Helper.ArrayOfFunction(i => new float2(data[i].X, data[i].Y - Background[i]), Background.Length); for (int z = 0; z < Zeros.Count; z++) { float2 Zero = Zeros[z]; int Pos = (int)((Zero.X - MinX) * ScaleX * DataSubtracted.Length); int First = Math.Max(0, Pos - 1); int Last = Math.Min(DataSubtracted.Length, Pos + 1); float MinVal = DataSubtracted[First].Y; for (int i = First; i < Last; i++) { MinVal = Math.Min(MinVal, DataSubtracted[i].Y); } Zeros[z] = new float2(Zero.X, Zero.Y + MinVal); } Background = (new Cubic1D(Zeros.ToArray())).Interp(data.Select(v => v.X).ToArray()); DataSubtracted = Helper.ArrayOfFunction(i => new float2(data[i].X, data[i].Y - Background[i]), Background.Length); float GlobalMax = 0; foreach (var peak in peaks) { int Pos = (int)((peak - MinX) * ScaleX * DataSubtracted.Length); int First = Math.Max(0, Pos - 1); int Last = Math.Min(DataSubtracted.Length, Pos + 1); float MaxVal = GlobalMax * 0.05f;// DataSubtracted[First].Y; for (int i = First; i < Last; i++) { MaxVal = Math.Max(MaxVal, DataSubtracted[i].Y); } Peaks.Add(new float2(peak, MaxVal)); GlobalMax = Math.Max(MaxVal, GlobalMax); } background = Zeros.Count > 1 ? new Cubic1D(Zeros.ToArray()) : new Cubic1D(new[] { new float2(0, 0), new float2(1, 0) }); scale = Peaks.Count > 1 ? new Cubic1D(Peaks.ToArray()) : new Cubic1D(new[] { new float2(0, 1), new float2(1, 1) }); return; int EveryNth = 1; float[] ZerosX = new float[Zeros.Count / EveryNth]; for (int i = 0; i < ZerosX.Length; i++) { ZerosX[i] = Zeros[i * EveryNth].X; } float[] PeaksX = new float[Peaks.Count / EveryNth]; for (int i = 0; i < PeaksX.Length; i++) { PeaksX[i] = Peaks[i * EveryNth].X; } float[] DataX = data.Select(v => v.X).ToArray(); float[] DataY = data.Select(v => v.Y).ToArray(); Func <double[], double> Eval = (input) => { Cubic1D SplineBackground = new Cubic1D(Helper.ArrayOfFunction(i => new float2(ZerosX[i], (float)Math.Exp(input[i])), ZerosX.Length)); Cubic1D SplineScale = new Cubic1D(Helper.ArrayOfFunction(i => new float2(PeaksX[i], (float)Math.Exp(input[i + ZerosX.Length])), PeaksX.Length)); float[] ContinuumBackground = SplineBackground.Interp(DataX); float[] ContinuumScale = SplineScale.Interp(DataX); float[] Diff = Helper.ArrayOfFunction(i => ContinuumBackground[i] + ContinuumScale[i] * simulation[i] - DataY[i], ContinuumBackground.Length); float DiffSq = 0; for (int i = 0; i < Diff.Length; i++) { DiffSq += Diff[i] * Diff[i]; } return(DiffSq); }; Func <double[], double[]> Grad = (input) => { double CurrentValue = Eval(input); double[] Result = new double[input.Length]; Parallel.For(0, input.Length, i => { double Delta = 1e-5; double[] InputPlus = input.ToArray(); InputPlus[i] += Delta; Result[i] = (Eval(InputPlus) - CurrentValue) / Delta; }); return(Result); }; double[] ResampledBackground = background.Interp(ZerosX).Select(v => Math.Log(Math.Max(v, 1e-5))).ToArray(); double[] ResampledScale = scale.Interp(PeaksX).Select(v => Math.Log(Math.Max(v, 1e-5))).ToArray(); double[] StartParams = Helper.Combine(ResampledBackground, ResampledScale); BroydenFletcherGoldfarbShanno Optimizer = new BroydenFletcherGoldfarbShanno(StartParams.Length, Eval, Grad); Optimizer.MaxIterations = 10; Optimizer.Minimize(StartParams); background = new Cubic1D(Helper.ArrayOfFunction(i => new float2(ZerosX[i], (float)Math.Exp(StartParams[i])), ZerosX.Length)); scale = new Cubic1D(Helper.ArrayOfFunction(i => new float2(PeaksX[i], (float)Math.Exp(StartParams[i + ZerosX.Length])), PeaksX.Length)); }
/// <summary> /// Fits the underlying distribution to a given set of observations. /// </summary> /// /// <param name="observations">The array of observations to fit the model against. The array /// elements can be either of type double (for univariate data) or /// type double[] (for multivariate data).</param> /// <param name="weights">The weight vector containing the weight for each of the samples.</param> /// <param name="options">Optional arguments which may be used during fitting, such /// as regularization constants and additional parameters.</param> /// /// <remarks> /// Although both double[] and double[][] arrays are supported, /// providing a double[] for a multivariate distribution or a /// double[][] for a univariate distribution may have a negative /// impact in performance. /// </remarks> /// public void Fit(double[] observations, double[] weights, CauchyOptions options) { if (immutable) { throw new InvalidOperationException("This object can not be modified."); } if (weights != null) { throw new ArgumentException("This distribution does not support weighted samples."); } bool useMLE = true; bool estimateT = true; bool estimateS = true; if (options != null) { useMLE = options.MaximumLikelihood; estimateT = options.EstimateLocation; estimateS = options.EstimateScale; } double t = location; double s = scale; int n = observations.Length; DoubleRange range; double median = Accord.Statistics.Tools.Quartiles(observations, out range, alreadySorted: false); if (estimateT) { t = median; } if (estimateS) { s = range.Length; } if (useMLE) { // Minimize the log-likelihood through numerical optimization BroydenFletcherGoldfarbShanno lbfgs = new BroydenFletcherGoldfarbShanno(2); // Define the negative log-likelihood function, // which is the objective we want to minimize: lbfgs.Function = (parameters) => { // Assume location is the first // parameter, shape is the second if (estimateT) { t = parameters[0]; } if (estimateS) { s = parameters[1]; } if (s < 0) { s = -s; } double sum = 0; for (int i = 0; i < observations.Length; i++) { double y = (observations[i] - t); sum += Math.Log(s * s + y * y); } return(-(n * Math.Log(s) - sum - n * Math.Log(Math.PI))); }; lbfgs.Gradient = (parameters) => { // Assume location is the first // parameter, shape is the second if (estimateT) { t = parameters[0]; } if (estimateS) { s = parameters[1]; } double sum1 = 0, sum2 = 0; for (int i = 0; i < observations.Length; i++) { double y = (observations[i] - t); sum1 += y / (s * s + y * y); sum2 += s / (s * s + y * y); } double dt = -2.0 * sum1; double ds = +2.0 * sum2 - n / s; double[] g = new double[2]; g[0] = estimateT ? dt : 0; g[1] = estimateS ? ds : 0; return(g); }; // Initialize using the sample median as starting // value for location, and half interquartile range // for shape. double[] values = { t, s }; // Minimize double error = lbfgs.Minimize(values); // Check solution t = lbfgs.Solution[0]; s = lbfgs.Solution[1]; } init(t, s); // Become the new distribution }
public void NoFunctionTest() { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2); Assert.Throws <InvalidOperationException>(() => target.Minimize(), ""); }
public void NoFunctionTest() { BroydenFletcherGoldfarbShanno target = new BroydenFletcherGoldfarbShanno(2); target.Minimize(); }
public static void FitCTF(float2[] data, Func <float[], float[]> approximation, float[] zeros, float[] peaks, out Cubic1D background, out Cubic1D scale) { float MinX = MathHelper.Min(data.Select(p => p.X)), MaxX = MathHelper.Max(data.Select(p => p.X)), ScaleX = 1f / (MaxX - MinX); float MinY = MathHelper.Min(data.Select(p => p.Y)), MaxY = MathHelper.Max(data.Select(p => p.Y)), ScaleY = 1f / (MaxY - MinY); if (float.IsNaN(ScaleY)) { ScaleY = 1f; } peaks = peaks.Where(v => v >= MinX && v <= MaxX).Where((v, i) => i % 1 == 0).ToArray(); zeros = zeros.Where(v => v >= MinX && v <= MaxX).Where((v, i) => i % 1 == 0).ToArray(); float2[] ScaledData = data.Select(p => new float2((p.X - MinX) * ScaleX, (p.Y - MinY) * ScaleY)).ToArray(); float StdY = MathHelper.StdDev(data.Select(p => p.Y).ToArray()); double[] Start = new double[zeros.Length + peaks.Length]; double[] NodeX = new double[zeros.Length + peaks.Length]; Cubic1D DataSpline = new Cubic1D(data); for (int i = 0; i < zeros.Length; i++) { NodeX[i] = (zeros[i] - MinX) * ScaleX; Start[i] = DataSpline.Interp(zeros[i]) - MinY; } { Cubic1D PreliminaryBackground = new Cubic1D(Helper.Zip(NodeX.Take(zeros.Length).Select(v => (float)v).ToArray(), Start.Take(zeros.Length).Select(v => (float)v).ToArray())); float[] PreliminaryInterpolated = PreliminaryBackground.Interp(data.Select(v => (v.X - MinX) * ScaleX).ToArray()); float2[] BackgroundSubtracted = data.Select((v, i) => new float2(v.X, v.Y - MinY - PreliminaryInterpolated[i])).ToArray(); Cubic1D BackgroundSpline = new Cubic1D(BackgroundSubtracted); for (int i = 0; i < peaks.Length; i++) { NodeX[i + zeros.Length] = (peaks[i] - MinX) * ScaleX; float PeakValue = BackgroundSpline.Interp(peaks[i]); Start[i + zeros.Length] = Math.Max(0.0001f, PeakValue); } } float[] DataX = ScaledData.Select(p => p.X).ToArray(); float[] OriginalDataX = data.Select(p => p.X).ToArray(); float[] SimulatedCTF = approximation(OriginalDataX); float2[] NodesBackground = new float2[zeros.Length]; for (int i = 0; i < NodesBackground.Length; i++) { NodesBackground[i] = new float2((float)NodeX[i], 0f); } float2[] NodesScale = new float2[peaks.Length]; for (int i = 0; i < NodesScale.Length; i++) { NodesScale[i] = new float2((float)NodeX[i + zeros.Length], 0f); } Func <double[], double> Eval = input => { float2[] NodesBackgroundCopy = new float2[NodesBackground.Length]; for (int i = 0; i < zeros.Length; i++) { NodesBackgroundCopy[i] = new float2(NodesBackground[i].X, (float)input[i]); } float2[] NodesScaleCopy = new float2[NodesScale.Length]; for (int i = 0; i < peaks.Length; i++) { NodesScaleCopy[i] = new float2(NodesScale[i].X, (float)input[i + zeros.Length]); } float[] InterpolatedBackground = new Cubic1D(NodesBackgroundCopy).Interp(DataX); float[] InterpolatedScale = new Cubic1D(NodesScaleCopy).Interp(DataX); double Sum = 0f; for (int i = 0; i < ScaledData.Length; i++) { double Diff = ScaledData[i].Y - (InterpolatedBackground[i] + SimulatedCTF[i] * (double)InterpolatedScale[i]) * ScaleY; Sum += Diff * Diff; if (InterpolatedScale[i] < 0.0005f) { Sum += (0.0005 - InterpolatedScale[i]) * 10; } } //return Math.Sqrt(Sum / data.Length) * 10; return(0); }; Func <double[], double[]> Gradient = input => { double[] Result = new double[input.Length]; //Parallel.For(0, input.Length, i => for (int i = 0; i < input.Length; i++) { double[] UpperInput = new double[input.Length]; input.CopyTo(UpperInput, 0); UpperInput[i] += 0.0001; double UpperValue = Eval(UpperInput); double[] LowerInput = new double[input.Length]; input.CopyTo(LowerInput, 0); LowerInput[i] -= 0.0001; double LowerValue = Eval(LowerInput); Result[i] = (UpperValue - LowerValue) / 0.0002; }//); return(Result); }; BroydenFletcherGoldfarbShanno Optimizer = new BroydenFletcherGoldfarbShanno(Start.Length, Eval, Gradient); Optimizer.Minimize(Start); { for (int i = 0; i < zeros.Length; i++) { NodesBackground[i] = new float2((float)NodeX[i] / ScaleX + MinX, (float)Optimizer.Solution[i] + MinY); } for (int i = 0; i < peaks.Length; i++) { NodesScale[i] = new float2((float)NodeX[i + zeros.Length] / ScaleX + MinX, Math.Max(0.001f, (float)Optimizer.Solution[i + zeros.Length])); } background = new Cubic1D(NodesBackground); scale = new Cubic1D(NodesScale); } }
public static Image AlignLocallyToTarget(Image map, Image target, int alignmentSize, int oversampling, out float3 shift, out float3 rotation) { float ScaleFactor = (float)alignmentSize / map.Dims.X; int3 DimsScaled = new int3(alignmentSize, alignmentSize, alignmentSize); #region Prepare Scaled & FFTed maps Image MapScaled = map.AsScaled(DimsScaled); map.FreeDevice(); Image TargetScaled = target.AsScaled(DimsScaled); target.FreeDevice(); TargetScaled.RemapToFT(true); TargetScaled.WriteMRC("d_targetscaled.mrc"); Image TargetScaledFT = TargetScaled.AsFFT(true); TargetScaled.Dispose(); Projector ProjMapScaled = new Projector(MapScaled, oversampling); Image TestFT = ProjMapScaled.Project(DimsScaled, new float3[1]); Image Test = TestFT.AsIFFT(true); Test.RemapFromFT(true); Test.WriteMRC("d_projected.mrc"); #endregion float3 CurShift = new float3(), CurRotation = new float3(); Func <double[], double> GetDiff = input => { CurShift = new float3((float)input[0], (float)input[1], (float)input[2]); CurRotation = new float3((float)input[3], (float)input[4], (float)input[5]) * (180f / map.Dims.X) * Helper.ToRad; CurRotation = Matrix3.EulerFromMatrix(Matrix3.RotateX(CurRotation.X) * Matrix3.RotateY(CurRotation.Y) * Matrix3.RotateZ(CurRotation.Z)) * Helper.ToDeg; Image TargetFTShifted = TargetScaledFT.AsShiftedVolume(-CurShift * ScaleFactor); Image MapRotatedFT = ProjMapScaled.Project(DimsScaled, new[] { CurRotation *Helper.ToRad }); TargetFTShifted.Subtract(MapRotatedFT); MapRotatedFT.Dispose(); GPU.MultiplySlices(TargetFTShifted.GetDevice(Intent.Read), TargetFTShifted.GetDevice(Intent.Read), TargetFTShifted.GetDevice(Intent.Write), (uint)TargetFTShifted.ElementsReal, 1); IntPtr d_Sum = GPU.MallocDevice(1); GPU.Sum(TargetFTShifted.GetDevice(Intent.Read), d_Sum, (uint)TargetFTShifted.ElementsReal, 1); TargetFTShifted.Dispose(); float[] h_Sum = new float[1]; GPU.CopyDeviceToHost(d_Sum, h_Sum, 1); GPU.FreeDevice(d_Sum); return(h_Sum[0]); }; Func <double[], double[]> GetGradient = input => { float Delta = 0.1f; double[] Result = new double[input.Length]; for (int i = 0; i < input.Length; i++) { double[] InputPlus = input.ToList().ToArray(); InputPlus[i] += Delta; double ScorePlus = GetDiff(InputPlus); double[] InputMinus = input.ToList().ToArray(); InputMinus[i] -= Delta; double ScoreMinus = GetDiff(InputMinus); Result[i] = (ScorePlus - ScoreMinus) / (Delta * 2); } return(Result); }; double[] StartParams = new double[6]; BroydenFletcherGoldfarbShanno Optimizer = new BroydenFletcherGoldfarbShanno(StartParams.Length, GetDiff, GetGradient); Optimizer.MaxIterations = 20; Optimizer.Minimize(StartParams); GetDiff(StartParams); shift = CurShift; rotation = CurRotation; #region Shift and rotate input map by determined values for final output ProjMapScaled.Dispose(); Image MapResult = map.AsShiftedVolume(shift); map.FreeDevice(); Projector ProjMapResult = new Projector(MapResult, 2); MapResult.Dispose(); Image MapResultFT = ProjMapResult.Project(map.Dims, new[] { rotation *Helper.ToRad }); ProjMapResult.Dispose(); MapResult = MapResultFT.AsIFFT(true); MapResultFT.Dispose(); MapResult.RemapFromFT(true); #endregion return(MapResult); }