public void FindMinimum_LogOutputToConsole_OutputNonEmpty() { const int n = 9; var x = Enumerable.Repeat(0.1, n).ToArray(); Bobyqa.FindMinimum(Rosen, n, x, null, null, -1, 1.0, 1.0e-8, 1, 2000, Console.Out); }
public void FindMinimum_HS04_ReturnsValidMinimum() { var xx = new[] { 1.125, 0.125 }; Bobyqa.FindMinimum((n, x) => Math.Pow(x[0] + 1.0, 3.0) / 3.0 + x[1], 2, xx, new[] { 1.0, 0.0 }, null, 4); Assert.AreEqual(1.0, xx[0], TOL); Assert.AreEqual(0.0, xx[1], TOL); }
public void FindMinimum_IntermedRosenbrock_ReturnsValidMinimum() { var xx = new[] { 1.0, -1.0 }; Bobyqa.FindMinimum((n, x) => 10.0 * Math.Pow(x[0] * x[0] - x[1], 2.0) + Math.Pow(1.0 + x[0], 2.0), 2, xx); Assert.AreEqual(-1.0, xx[0], TOL); Assert.AreEqual(1.0, xx[1], TOL); }
public void FindMinimum_BobyqaTestCase_ReturnStatusNormal(int m, int npt) { // Test problem for BOBYQA, the objective function being the sum of // the reciprocals of all pairwise distances between the points P_I, // I=1,2,...,M in two dimensions, where M=N/2 and where the components // of P_I are X(2*I-1) and X(2*I). Thus each vector X of N variables // defines the M points P_I. The initial X gives equally spaced points // on a circle. Four different choices of the pairs (N,NPT) are tried, // namely (10,16), (10,21), (20,26) and (20,41). Convergence to a local // minimum that is not global occurs in both the N=10 cases. The details // of the results are highly sensitive to computer rounding errors. The // choice IPRINT=2 provides the current X and optimal F so far whenever // RHO is reduced. The bound constraints of the problem require every // component of X to be in the interval [-1,1]. var n = 2 * m; var x0 = new double[n]; var xl = new double[n]; var xu = new double[n]; const double bdl = -1.0; const double bdu = 1.0; for (var i = 0; i < n; ++i) { xl[i] = bdl; xu[i] = bdu; } Console.WriteLine("{0}2D output with M ={1,4}, N ={2,4} and NPT ={3,4}", Environment.NewLine, m, n, npt); for (var j = 1; j <= m; ++j) { var temp = 2.0 * Math.PI * j / m; x0[2 * j - 2] = Math.Cos(temp); x0[2 * j - 1] = Math.Sin(temp); } const int iprint = 2; const int maxfun = 500000; const double rhobeg = 1.0E-1; const double rhoend = 1.0E-6; var optimizer = new Bobyqa(n, this.BobyqaTestCalfun, xl, xu) { InterpolationConditions = npt, TrustRegionRadiusStart = rhobeg, TrustRegionRadiusEnd = rhoend, PrintLevel = iprint, MaximumFunctionCalls = maxfun }; const OptimizationStatus expected = OptimizationStatus.Normal; var actual = optimizer.FindMinimum(x0).Status; Assert.AreEqual(expected, actual); }
public void FindMinimum_HS05_ReturnsValidMinimum() { var xx = new[] { 0.0, 0.0 }; Bobyqa.FindMinimum( (n, x) => Math.Sin(x[0] + x[1]) + Math.Pow(x[0] - x[1], 2.0) - 1.5 * x[0] + 2.5 * x[1] + 1, 2, xx, new[] { -1.5, -3.0 }, new[] { 4.0, 3.0 }); Assert.AreEqual(0.5 - Math.PI / 3.0, xx[0], TOL); Assert.AreEqual(-0.5 - Math.PI / 3.0, xx[1], TOL); }
public void FindMinimum_LogOutputToConsole_OutputNonEmpty() { const int n = 9; var optimizer = new Bobyqa(n, this.Rosen) { Logger = Console.Out }; optimizer.FindMinimum(Enumerable.Repeat(0.1, n).ToArray()); }
public void FindMinimum_IntermedRosenbrock_ReturnsValidMinimum() { var optimizer = new Bobyqa( 2, (n, x) => 10.0 * Math.Pow(x[0] * x[0] - x[1], 2.0) + Math.Pow(1.0 + x[0], 2.0)); var summary = optimizer.FindMinimum(new[] { 1.0, -1.0 }); Assert.AreEqual(-1.0, summary.X[0], TOL); Assert.AreEqual(1.0, summary.X[1], TOL); }
public void FindMinimum_HS04_ReturnsValidMinimum() { var optimizer = new Bobyqa(2, (n, x) => Math.Pow(x[0] + 1.0, 3.0) / 3.0 + x[1], new[] { 1.0, 0.0 }, null) { InterpolationConditions = 4 }; var result = optimizer.FindMinimum(new[] { 1.125, 0.125 }); Assert.AreEqual(1.0, result.X[0], TOL); Assert.AreEqual(0.0, result.X[1], TOL); }
public void FindMinimum_LogOutput_OutputNonEmpty() { const int n = 9; var x = Enumerable.Repeat(0.1, n).ToArray(); using (var logger = new StringWriter()) { Bobyqa.FindMinimum(Rosen, n, x, null, null, -1, 1.0, 1.0e-8, 1, 2000, logger); Assert.Greater(logger.ToString().Length, 0); } }
public void FindMinimum_HS05_ReturnsValidMinimum() { var optimizer = new Bobyqa( 2, (n, x) => Math.Sin(x[0] + x[1]) + Math.Pow(x[0] - x[1], 2.0) - 1.5 * x[0] + 2.5 * x[1] + 1, new[] { -1.5, -3.0 }, new[] { 4.0, 3.0 }); var result = optimizer.FindMinimum(new[] { 0.0, 0.0 }); Assert.AreEqual(0.5 - Math.PI / 3.0, result.X[0], TOL); Assert.AreEqual(-0.5 - Math.PI / 3.0, result.X[1], TOL); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object can be used to retrieve data from input parameters and /// to store data in output parameters.</param> protected override void SolveInstance(IGH_DataAccess DA) { Mesh mesh = new Mesh(); List <double> initialValues = new List <double>(); double desiredWidth = 0.0; double lambda = 0.0; double nu = 0.0; if (!DA.GetData(0, ref mesh)) { return; } if (!DA.GetDataList(1, initialValues)) { return; } if (!DA.GetData(2, ref desiredWidth)) { return; } if (!DA.GetData(3, ref lambda)) { return; } if (!DA.GetData(4, ref nu)) { return; } mesh.FaceNormals.ComputeFaceNormals(); GeodesicsFromLevelSets levelSets = new GeodesicsFromLevelSets(mesh, initialValues, desiredWidth, lambda, nu); var optimizer = new Bobyqa(mesh.Vertices.Count, levelSets.Compute); optimizer.MaximumFunctionCalls = 200; double[] x = initialValues.ToArray(); var result = optimizer.FindMinimum(x); List <double> finalValues = new List <double>(result.X); List <double> divergence = levelSets.ComputeDivergence(false); DA.SetDataList(1, levelSets.Gradient); DA.SetDataList(2, divergence); DA.SetDataList(3, levelSets.VertexVoronoiArea); DA.SetData(4, result.F); DA.SetDataList(5, finalValues); }
public List <Curve> GenerateSubCurves(double[] _startData, double[] _xl, double[] _xu) { // Generate Initial values and variable Bounds for the optimization problem. // Only using first variable for now, the extra variable is just to make it work. double[] startData = _startData; double[] xl = _xl; double[] xu = _xu; List <Curve> pieceWiseList = new List <Curve>(); pieceWiseList.Add(selectedGeodesic); if (bestFitInterval.Length != 0) { pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, bestFitInterval[0], bestFitInterval[1]); if (bestFitInterval[1] < (perpGeodesics.Count - 1)) { List <Curve> tempGeodesics = perpGeodesics.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); List <double> tempParameters = perpParameters.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); Vector3d tangent = pieceWiseList[0].TangentAtEnd; double t; tempGeodesics[0].ClosestPoint(pieceWiseList[0].PointAtEnd, out t); tempParameters[0] = t; BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter / 2, false, 0, threshold, tangent); var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); var tempResult = tempOptimizer.FindMinimum(startData); pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu)); } if (bestFitInterval[0] > 0) { List <Curve> tempGeodesics = perpGeodesics.GetRange(0, bestFitInterval[0] + 1); List <double> tempParameters = perpParameters.GetRange(0, bestFitInterval[0] + 1); double t; Vector3d tangent = pieceWiseList[0].TangentAtStart; tempGeodesics[tempGeodesics.Count - 1].ClosestPoint(pieceWiseList[0].PointAtStart, out t); tempParameters[tempGeodesics.Count - 1] = t; BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter / 2, false, tempGeodesics.Count - 1, threshold, -tangent); var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); var tempResult = tempOptimizer.FindMinimum(startData); pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu)); } } return(pieceWiseList); }
public void FindMinimum_ConstrainedRosenWithAdditionalInterpolationPoints_ReturnsValidMinimum(int n, int maxAdditionalPoints) { var xl = Enumerable.Repeat(-1.0, n).ToArray(); var xu = Enumerable.Repeat(2.0, n).ToArray(); var expected = Enumerable.Repeat(1.0, n).ToArray(); for (var num = 1; num <= maxAdditionalPoints; ++num) { Console.WriteLine("\nNumber of additional points = {0}", num); var npt = 2 * n + 1 + num; var x = Enumerable.Repeat(0.1, n).ToArray(); Bobyqa.FindMinimum(Rosen, n, x, xl, xu, npt, -1, 1.0e-8, 1, 3000, Console.Out); CollectionAssert.AreEqual(expected, x, new DoubleComparer(1.0e-6)); } }
public void FindMinimum_LogOutput_OutputNonEmpty() { const int n = 9; var optimizer = new Bobyqa(n, this.Rosen) { Logger = Console.Out }; using (var logger = new StringWriter()) { optimizer.Logger = logger; optimizer.FindMinimum(Enumerable.Repeat(0.1, n).ToArray()); Assert.Greater(logger.ToString().Length, 0); } }
/// <summary> /// Finds central point of all lines with BOBYQA using weight /// <param name="list">Array of lines</param> /// <returns>Returns central Point or Vector3D(NaN,NaN,NaN) on error</returns> /// </summary> private static Point3D bobyqaCentralPointWithWeight(Ray3D[] lines) { gLines = lines; var xyz = new[] { 0.0, 0.0, 0.0 }; var lBounds = new[] { -30.0, -30.0, -30.0 }; var uBounds = new[] { 30.0, 30.0, 30.0 }; var status = Bobyqa.FindMinimum(calfunBobyqaWeight, 3, xyz, lBounds, uBounds, -1, -1, -1, 1, 10000, Console.Out); if (status == BobyqaExitStatus.Normal) { return(new Point3D(xyz[0], xyz[1], xyz[2])); } else { return(new Point3D(Double.NaN, Double.NaN, Double.NaN)); } }
public void FindMinimum_ConstrainedRosenWithAdditionalInterpolationPoints_ReturnsValidMinimum(int n, int maxAdditionalPoints) { var xl = Enumerable.Repeat(-1.0, n).ToArray(); var xu = Enumerable.Repeat(2.0, n).ToArray(); var expected = Enumerable.Repeat(1.0, n).ToArray(); var optimizer = new Bobyqa(n, this.Rosen, xl, xu) { TrustRegionRadiusEnd = 1.0e-8, MaximumFunctionCalls = 3000, Logger = Console.Out }; for (var num = 1; num <= maxAdditionalPoints; ++num) { Console.WriteLine("\nNumber of additional points = {0}", num); optimizer.InterpolationConditions = 2 * n + 1 + num; var result = optimizer.FindMinimum(Enumerable.Repeat(0.1, n).ToArray()); CollectionAssert.AreEqual(expected, result.X, new DoubleComparer(1.0e-6)); } }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object can be used to retrieve data from input parameters and /// to store data in output parameters.</param> protected override void SolveInstance(IGH_DataAccess DA) { Mesh mesh = new Mesh(); List <double> initialValues = new List <double>(); double desiredWidth = 0.0; double lambda = 0.0; double nu = 0.0; int maxCalls = 0; int optim = 0; double objective = 10; if (!DA.GetData(0, ref mesh)) { return; } if (!DA.GetDataList(1, initialValues)) { return; } if (!DA.GetData(2, ref desiredWidth)) { return; } if (!DA.GetData(3, ref lambda)) { return; } if (!DA.GetData(4, ref nu)) { return; } if (!DA.GetData(5, ref maxCalls)) { return; } if (!DA.GetData(6, ref optim)) { return; } if (!DA.GetData(7, ref objective)) { return; } mesh.FaceNormals.ComputeFaceNormals(); GeodesicsFromLevelSets levelSets = new GeodesicsFromLevelSets(mesh, initialValues, desiredWidth, lambda, nu); var optimizer = new Bobyqa(mesh.Vertices.Count, levelSets.Compute); optimizer.MaximumFunctionCalls = maxCalls; double[] x = initialValues.ToArray(); var func = new LevelSetOpt(levelSets); var opt = new clsOptNelderMead(func); //if (optim == 1) opt = new clsOptNelderMead(func); //if (optim == 2) opt = new clsOptSimulatedAnnealing(func); //if (optim == 3) opt = new clsFireFly(func); opt.IsUseCriterion = false; opt.InitialPosition = initialValues.ToArray(); opt.Iteration = maxCalls; double finalError = 0; bool retry = false; do { double[] resultX = { }; if (optim == 0) { var result = optimizer.FindMinimum(x); finalError = result.F; resultX = result.X; } else if (optim > 0) { // Nelder mead & simulated annealing opt.Init(); while (opt.DoIteration(100) == false) { var eval = opt.Result.Eval; //my criterion if (eval < 10) { break; } Console.WriteLine("Iter: {0} Eval: {1}", opt.IterationCount, opt.Result.Eval); } finalError = opt.Result.Eval; clsUtil.DebugValue(opt); } //if (optim == 0) { // String str = "Optimization ended with an error of" + finalError + "\nDo you wish to run again using this results as input?"; // if (MessageBox.Show(str, "Optimization Ended", MessageBoxButtons.YesNo, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1) == DialogResult.Yes) // { // x = resultX; // retry = true; // } // else // { // retry = false; // } //} } while (retry == true); //levelSets = func.levelSets; List <double> desiredLevels = new List <double>(); double max = 0.0; double min = 0.0; for (int i = 0; i < levelSets.VertexValues.Count; i++) { double value = levelSets.VertexValues[i]; if (i == 0) { max = value; min = value; } if (value < min) { min = value; } if (value > max) { max = value; } } double diff = max - min; int levelCount = (int)(diff / desiredWidth); for (int j = 0; j <= levelCount; j++) { desiredLevels.Add(min + (j * desiredWidth)); } DataTree <Line> pattern = levelSets.DrawLevelSetCurves(desiredLevels); List <double> divergence = levelSets.ComputeDivergence(false); List <double> divergenceNorm = levelSets.ComputeDivergence(true); DA.SetDataTree(0, pattern); DA.SetDataList(1, levelSets.Gradient); DA.SetDataList(2, divergence); DA.SetDataList(3, levelSets.VertexVoronoiArea); DA.SetData(4, finalError); DA.SetDataList(5, levelSets.VertexValues); DA.SetDataList(6, divergenceNorm); }
public List <Curve> GeneratePiecewiseGeodesicCurve(Mesh mesh, List <double> perpParameters, List <Curve> perpGeodesics, int maxIter, bool bothDir, int startIndex, double threshold, Vector3d dir) { // Generate Initial values and variable Bounds for the optimization problem. // Only using first variable for now, the extra variable is just to make it work. Random rnd = new Random(); double limit = 0.35; double start = (rnd.NextDouble() * limit) - (limit / 2); double[] startData = { start, 0 }; double[] xl = new double[] { -limit * Math.PI, -1 }; double[] xu = new double[] { limit *Math.PI, 1 }; // Generate bestfit G BestFitPieceWiseGeodesic bestFitG = new BestFitPieceWiseGeodesic(mesh, perpGeodesics, perpParameters, maxIter, bothDir, startIndex, threshold, dir); // Run optimization var optimizer = new Bobyqa(2, bestFitG.ComputeError, xl, xu); var result = optimizer.FindMinimum(startData); // If no best fit is found, gradually increase angle if (bestFitG.bestFitInterval.Length == 0 || result.F > 0.1) { do { limit += 0.05; Debug.WriteLine("Limit increased :" + limit); start = (rnd.NextDouble() * limit) - (limit / 2); startData[0] = start; xl = new double[] { -limit * Math.PI, -1 }; xu = new double[] { limit *Math.PI, 1 }; optimizer = new Bobyqa(2, bestFitG.ComputeError, xl, xu); result = optimizer.FindMinimum(startData); //Debug.WriteLine("Result: " + result.F + " Interval: " + bestFitG.bestFitInterval[0] + "-" + bestFitG.bestFitInterval[1]); } while (limit < 0.35); AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "No best interval found?!"); if (bestFitG.bestFitInterval.Length == 0) { return new List <Curve>() { bestFitG.selectedGeodesic } } ; } //Debug.WriteLine("Result: " + result.F + " Interval: " + bestFitG.bestFitInterval[0] + "-" + bestFitG.bestFitInterval[1]); // Split the curve double domainLength = bestFitG.bestFitInterval[1] - bestFitG.bestFitInterval[0]; Curve splitC = bestFitG.selectedGeodesic; splitC.Domain = new Interval(0, 1); List <Curve> pieceWiseList = new List <Curve>(); if (domainLength < perpGeodesics.Count - 4) { // Generate piecewise at end if (bestFitG.bestFitInterval[1] < perpGeodesics.Count - 3) { // Get reference point for splitting //var refInt = Intersection.CurveCurve(splitC, perpGeodesics[(bestFitG.bestFitInterval[1] - 1)], 0.0, 0.0); //double refT = refInt[0].ParameterA; // Get intersection with end point var endInt = Intersection.CurveCurve(splitC, perpGeodesics[(bestFitG.bestFitInterval[1])], 0.0, 0.0); var endParam = endInt[0].ParameterA; Point3d refPoint = splitC.PointAt(endParam / 2); // Split the curve Curve[] splitGs = splitC.Split(endParam); // Select the correct curve foreach (Curve g in splitGs) { double t; g.ClosestPoint(refPoint, out t); double distance = refPoint.DistanceTo(g.PointAt(t)); if (distance < 0.01) { splitC = g; break; } } List <double> paramsAtEnd = new List <double>(perpParameters); paramsAtEnd.RemoveRange(0, bestFitG.bestFitInterval[1]); List <Curve> geodsAtEnd = new List <Curve>(perpGeodesics); geodsAtEnd.RemoveRange(0, bestFitG.bestFitInterval[1]); // Replace first parameter with the parameter of the piecewise curve endpoint at the perpGeod. var events = Intersection.CurveCurve(geodsAtEnd[0], bestFitG.selectedGeodesic, 0.0, 0.0); paramsAtEnd[0] = events[0].ParameterA; // Get the best next best fit geodesic at end pieceWiseList.AddRange(GeneratePiecewiseAtEnd(mesh, paramsAtEnd, geodsAtEnd, maxIter, 0, threshold)); } //// Generate piecewise at start //if (bestFitG.bestFitInterval[0] > 3) //{ // var refInt = Intersection.CurveCurve(splitC, perpGeodesics[(bestFitG.bestFitInterval[0] + 2)], 0.0, 0.0); // Point3d refPoint = refInt[0].PointB; // // Get intersection with end point // var startInt = Intersection.CurveCurve(splitC, perpGeodesics[(bestFitG.bestFitInterval[0])], 0.0, 0.0); // var startParam = startInt[0].ParameterA; // // Split the curve // Curve[] splitGs = splitC.Split(startParam); // // Select the correct curve // foreach (Curve g in splitGs) // { // double t; // g.ClosestPoint(refPoint, out t); // double distance = refPoint.DistanceTo(g.PointAt(t)); // if (distance < 0.01) // { // splitC = g; // break; // } // } // List<double> paramsAtStart = new List<double>(perpParameters); // paramsAtStart.RemoveRange(bestFitG.bestFitInterval[0], (perpParameters.Count - 1) - bestFitG.bestFitInterval[0] - 1); // List<Curve> geodsAtStart = new List<Curve>(perpGeodesics); // geodsAtStart.RemoveRange(bestFitG.bestFitInterval[0], (perpGeodesics.Count - 1) - bestFitG.bestFitInterval[0] - 1); // // Replace first parameter with the parameter of the piecewise curve endpoint at the perpGeod. // paramsAtStart.Reverse(); // geodsAtStart.Reverse(); // var events = Intersection.CurveCurve(geodsAtStart[0], bestFitG.selectedGeodesic, 0.0, 0.0); // paramsAtStart[0] = events[0].ParameterA; // Vector3d vector = -splitC.TangentAtStart; // // This would be the same as at end, but with a first step flipping the direction of the perpGeodesics list. // /pieceWiseList.AddRange(GeneratePiecewiseAtStart(mesh, paramsAtStart, geodsAtStart, maxIter, 0, threshold, vector)); //} pieceWiseList.Add(splitC); } else { pieceWiseList.Add(bestFitG.selectedGeodesic); } //pieceWiseList = bestFitG.GenerateSubCurves(startData, xl, xu, 0); return(pieceWiseList); }
protected override void SolveInstance(IGH_DataAccess DA) { // Properties Mesh mesh = null; List <Curve> perpGeodesics = new List <Curve>(); List <double> perpParameters = new List <double>(); int maxIter = 0; bool bothDir = false; int startIndex = 0; mesh = null; perpGeodesics = new List <Curve>(); perpParameters = new List <double>(); double threshold = 0.0; // Set the input data if (!DA.GetData(0, ref mesh)) { return; } if (!DA.GetDataList(1, perpGeodesics)) { return; } if (!DA.GetDataList(2, perpParameters)) { return; } if (!DA.GetData(3, ref maxIter)) { return; } if (!DA.GetData(4, ref bothDir)) { return; } if (!DA.GetData(5, ref startIndex)) { return; } if (!DA.GetData(6, ref threshold)) { return; } // Data validation if (maxIter == 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "MaxIter cannot be 0"); } if (!mesh.IsValid) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh is invalid"); } if (perpGeodesics.Count < 2) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "There must be at least 2 perpendicular geodesics"); } if (perpParameters.Count != perpGeodesics.Count) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Curves and Params list must have the same number of items"); } // Generate Initial values and variable Bounds for the optimization problem. // Only using first variable for now, the extra variable is just to make it work. double[] startData = { 0.010, 0 }; double[] xl = new double[] { -0.15, -1 }; double[] xu = new double[] { 0.15, 1 }; BestFitPieceWiseGeodesic bestFitG = new BestFitPieceWiseGeodesic(mesh, perpGeodesics, perpParameters, maxIter, bothDir, startIndex, threshold, Vector3d.Unset); var optimizer = new Bobyqa(2, bestFitG.ComputeError, xl, xu); var result = optimizer.FindMinimum(startData); if (bestFitG.bestFitInterval.Length == 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "No best interval found?!"); return; } // Sub curves methods go here List <Curve> pieceWiseList = new List <Curve>(); pieceWiseList = bestFitG.GenerateSubCurves(startData, xl, xu); DA.SetDataList(0, pieceWiseList); DA.SetDataList(1, result.X); }
/// <summary> /// Generates the sub curves. /// </summary> /// <returns>The sub curves.</returns> /// <param name="_startData">Start data.</param> /// <param name="_xl">Xl.</param> /// <param name="_xu">Xu.</param> /// <param name="type">Generation type: 0 for doubleside, 1 for end side, -1 for start side of curve</param> public List <Curve> GenerateSubCurves(double[] _startData, double[] _xl, double[] _xu, int type) { // Generate Initial values and variable Bounds for the optimization problem. // Only using first variable for now, the extra variable is just to make it work. double[] startData = _startData; double[] xl = _xl; double[] xu = _xu; List <Curve> pieceWiseList = new List <Curve>(); pieceWiseList.Add(selectedGeodesic); if (bestFitInterval.Length != 0) { switch (type) { // End point case 1: pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, 0, bestFitInterval[1]); break; // Start point case -1: pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, bestFitInterval[0], perpGeodesics.Count - 1); break; default: pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, bestFitInterval[0], bestFitInterval[1]); break; } if ((bestFitInterval[1] < (perpGeodesics.Count - 1)) && (type == 0 || type == 1)) { List <Curve> tempGeodesics = perpGeodesics.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); List <double> tempParameters = perpParameters.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); Vector3d tangent = pieceWiseList[0].TangentAtEnd; double t; tempGeodesics[0].ClosestPoint(pieceWiseList[0].PointAtEnd, out t); tempParameters[0] = t; BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter, false, 0, threshold, tangent); var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); var tempResult = tempOptimizer.FindMinimum(startData); if (tempBestFit.bestFitInterval.Length == 0) { pieceWiseList[0] = selectedGeodesic; //No best fit found } else { pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu, 1)); } } //if (bestFitInterval[0] > 0 && (type == 0 || type == -1)) //{ // List<Curve> tempGeodesics = perpGeodesics.GetRange(0, bestFitInterval[0] + 1); // List<double> tempParameters = perpParameters.GetRange(0, bestFitInterval[0] + 1); // double t; // Vector3d tangent = pieceWiseList[0].TangentAtStart; // //tangent.Rotate(Math.PI, mesh.NormalAt(mesh.ClosestMeshPoint(pieceWiseList[0].PointAtStart, 0.0))); // tempGeodesics[tempGeodesics.Count - 1].ClosestPoint(pieceWiseList[0].PointAtStart, out t); // tempParameters[tempGeodesics.Count - 1] = t; // BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter, false, tempGeodesics.Count - 1, threshold, -tangent); // var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); // var tempResult = tempOptimizer.FindMinimum(startData); // if (tempBestFit.bestFitInterval.Length == 0) // { // pieceWiseList.Add(tempBestFit.selectedGeodesic); // No best fit found; // } // else // { // tempBestFit.selectedGeodesic.Reverse(); // pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu, -1)); // } //} } return(pieceWiseList); }