static void Main(string[] args) { #region Intro Console.WriteLine(@" /////////////////////////////////////// Task: Lab 2 - Gradient Descent Written By: Christopher W. Blake Date: 22 Nov. 2016 /////////////////////////////////////// Description: Creates 2 different seach algorithms for finding the minimum of a given function f(x) in a range. It then tests these results and prints them to the console. 1. First-order gradient descent method. (one – dimensional minimization method for choosing the step) 2. Second-order gradient descent method (division method for choosing the step) Verification: f(0.5, -0.44963) = 0.27696 /////////////////////////////////////// "); #endregion //Required accuracy values List <double> epsValues = new List <double> { 0.1, 0.01, 0.001 }; //accuracy //Objective function Func <DV, D> f = delegate(DV x) { D x1 = x[0]; D x2 = x[1]; return(x1 * x1 + x2 * x2 + AD.Exp(x2 * x2) - x1 + 2 * x2); //return AD.Pow(x1-7, 2) + AD.Pow(x2-3, 2); }; #region 1.) First Order, One-Dimensional Method //Show the table header Console.WriteLine("----- Gradient Search, First Order, One-Dimensional Method -----"); Console.WriteLine(" eps X1 X2 f(x) Calcs F Calcs Gr"); foreach (double eps in epsValues) { //Get solution int calcsF; int calcsGradient; DV startPoint = new DV(new D[] { 0, 0 }); DV xMin = Optimization.GradientDescent.FirstOrder_OneDimensionalMethod(f, startPoint, eps, out calcsF, out calcsGradient); //determine number of decimal places to show int dp = BitConverter.GetBytes(decimal.GetBits((decimal)eps)[3])[2] + 1; //Show on console Console.WriteLine("{0,8}{1,8:F" + dp + "}{2,8:F" + dp + "}{3,8:F" + dp + "}{4,8}{5,8}", eps, (double)xMin[0], (double)xMin[1], (double)f(xMin), calcsF, calcsGradient); } #endregion DV[] xFirstOrder_DivMethod = null; double[] fxFirstOrder_DivMethod = null; #region 2.) First Order, Division Method //Show the table header Console.WriteLine(); Console.WriteLine("----- Gradient Search, First Order, Division Method -----"); Console.WriteLine(" eps X1 X2 f(x) Calcs F Calcs dF"); foreach (double eps in epsValues) { //Get solution int calcsF; int calcsGradient; DV startPoint = new DV(new D[] { 0, 0 }); DV xMin = Optimization.GradientDescent.FirstOrder_DivisionMethod(f, startPoint, eps, out calcsF, out calcsGradient, out xFirstOrder_DivMethod, out fxFirstOrder_DivMethod); //determine number of decimal places to show int dp = BitConverter.GetBytes(decimal.GetBits((decimal)eps)[3])[2] + 1; //Show on console Console.WriteLine("{0,8}{1,8:F" + dp + "}{2,8:F" + dp + "}{3,8:F" + dp + "}{4,8}{5,8}", eps, (double)xMin[0], (double)xMin[1], (double)f(xMin), calcsF, calcsGradient); } #endregion DV[] xSecondOrder_FullStep = null; double[] fxSecondOrder_FullStep = null; #region 3.) Second Order - Newtons Method, FullStep //Show the table header Console.WriteLine(); Console.WriteLine("----- Gradient Search, Second Order, FullStep -----"); Console.WriteLine(" eps X1 X2 f(x) Calcs F Calcs Gr Calcs Hess"); //Show Results for each accuracy foreach (double eps in epsValues) { //Get solution int calcsF; int calcsGradient; int calcsHessian; DV startPoint = new DV(new D[] { 0, 0 }); DV xMin = Optimization.GradientDescent.SecondOrder_FullStep(f, startPoint, eps, out calcsF, out calcsGradient, out calcsHessian, out xSecondOrder_FullStep, out fxSecondOrder_FullStep); //determine number of decimal places to show int dp = BitConverter.GetBytes(decimal.GetBits((decimal)eps)[3])[2] + 1; //Show on console Console.WriteLine("{0,8}{1,8:F" + dp + "}{2,8:F" + dp + "}{3,8:F" + dp + "}{4,8}{5,8}{6,8}", eps, (double)xMin[0], (double)xMin[1], (double)f(xMin), calcsF, calcsGradient, calcsHessian); } #endregion #region 4.) Second Order - Newtons Method, Division Method //Show the table header Console.WriteLine(); Console.WriteLine("----- Gradient Search, Second Order, Division Method -----"); Console.WriteLine(" eps X1 X2 f(x) Calcs F Calcs Gr Calcs Hess"); //Show Results for each accuracy foreach (double eps in epsValues) { //Get solution int calcsF; int calcsGradient; int calcsHessian; DV startPoint = new DV(new D[] { 0, 0 }); DV xMin = Optimization.GradientDescent.SecondOrder_DivisionMethod(f, startPoint, eps, out calcsF, out calcsGradient, out calcsHessian); //determine number of decimal places to show int dp = BitConverter.GetBytes(decimal.GetBits((decimal)eps)[3])[2] + 1; //Show on console Console.WriteLine("{0,8}{1,8:F" + dp + "}{2,8:F" + dp + "}{3,8:F" + dp + "}{4,8}{5,8}{6,8}", eps, (double)xMin[0], (double)xMin[1], (double)f(xMin), calcsF, calcsGradient, calcsHessian); } #endregion //Below is all extra work that she asked for (for fun) in class #region 5.) Speed Comparison, First Order, Div method DV xStarFirstOrder_DivMethod = xFirstOrder_DivMethod[xFirstOrder_DivMethod.Length - 1]; Console.WriteLine(); Console.WriteLine("---- Speed (q), First Order, Division Method --- "); Console.WriteLine("K X1 X2 qX1 qX2"); for (int k = 0; k < xFirstOrder_DivMethod.Length - 1; k++) { //Display row information Console.Write("{0}: {1,10:F3}{2,10:F3}", k, (double)xFirstOrder_DivMethod[k][0], (double)xFirstOrder_DivMethod[k][1]); if (k > 0 && k < xFirstOrder_DivMethod.Length - 2) { DV x = xFirstOrder_DivMethod[k] - xStarFirstOrder_DivMethod; DV xNext = xFirstOrder_DivMethod[k - 1] - xStarFirstOrder_DivMethod; double qX1 = AD.Abs(xNext[0] - xStarFirstOrder_DivMethod[0]); double qX2 = AD.Abs(xNext[1] - xStarFirstOrder_DivMethod[1]); Console.Write("{0,10:F3}{1,10:F3}", qX1, qX2); } Console.WriteLine(); } #endregion #region 6.) Speed Comparison, Second Order, Full Step DV xStarSecondOrder_FullStep = xSecondOrder_FullStep[xSecondOrder_FullStep.Length - 1]; Console.WriteLine(); Console.WriteLine("---- Speed (q), Second Order, Full Step --- "); Console.WriteLine("K X1 X2 qX1 qX2"); for (int k = 0; k < xSecondOrder_FullStep.Length - 1; k++) { //Display row information Console.Write("{0}: {1,10:F3}{2,10:F3}", k, (double)xSecondOrder_FullStep[k][0], (double)xSecondOrder_FullStep[k][1]); if (k > 0 && k < xSecondOrder_FullStep.Length - 2) { DV x = xSecondOrder_FullStep[k] - xStarSecondOrder_FullStep; DV xNext = xSecondOrder_FullStep[k - 1] - xStarSecondOrder_FullStep; double qX1 = AD.Abs(xNext[0] - xStarSecondOrder_FullStep[0]); double qX2 = AD.Abs(xNext[1] - xStarSecondOrder_FullStep[1]); Console.Write("{0,10:F3}{1,10:F3}", qX1, qX2); } Console.WriteLine(); } #endregion //Wait for use to click something to exit Console.ReadKey(); }
// Define a function whose derivative you need // F(x) = Sin(x^2 - Exp(x)) public static D F(D x) { return(AD.Sin(x * x - AD.Exp(x))); }
static void Main(string[] args) { //Required accuracy values List <double> epsValues = new List <double> { 0.1, 0.01, 0.001 }; //accuracy //Functions Func <DV, D> objFunc = delegate(DV x) { D x1 = x[0]; D x2 = x[1]; // return AD.Pow(x1 - 2, 2) + AD.Pow(x2 - 2, 2); //(1-x1)^2 - 10(x2-x1^2)^2 + x1^2 - 2x1*x2 + exp(-x1-x2) return(AD.Pow(1.0 - x1, 2) //(1-x1)^2 - 10 * AD.Pow(x2 - AD.Pow(x1, 2), 2) // - 10(x2-x1^2)^2 + AD.Pow(x1, 2) // + x1^2 - 2 * x1 * x2 // - 2x1*x2 + AD.Exp(-x1 - x2)); //exp(-x1 - x2) }; Func <D, D> penalty = delegate(D t) { if (t < 0) { return(0); } else { //return -100000; return(1000000 * AD.Pow(t, 2)); } }; Func <DV, D> objFunc_penalized = delegate(DV x) { D x1 = x[0]; D x2 = x[1]; //Constraints //Example: x >= 1 -----------------------> 1 - x <= 0 //x1^2 + x2^2 <= 16 ---------> x1^2 + x2^2 - 16 <= 0 //(x2 - x1)^2 + x1 <= 6 ---------> (x2 - x1) ^ 2 + x1 - 6 <= 0 //x1 + x2 >= 2 ---------> 2 - x1 - x2 <= 0 //Combine objective function and penalty functions return(0 + objFunc(x) + penalty(AD.Pow(x1, 2) + AD.Pow(x2, 2) - 16) + penalty(AD.Pow(x2 - x1, 2) + x1 - 6) + penalty(2 - x1 - x2) ); }; //Get results int calcsF; int calcsGradient; int calcsHessian; DV[] xLocations = null; double[] fx = null; epsValues = new List <double> { 0.1, 0.01, 0.001 }; //accuracy #region 1.) Penalty Function, First Order, One-Dimensional Method //Show the table header Console.WriteLine("----- Gradient Search, First Order, One-Dimensional Method -----"); Console.WriteLine(" eps X1 X2 f(x) Calcs F Calcs Gr"); foreach (double eps in epsValues) { //Perform calculation //DV startPoint = new DV(new D[] { 2, 2 }); DV startPoint = new DV(new D[] { 1, 2 }); var xMin = Optimization.GradientDescent.FirstOrder_OneDimensionalMethod(objFunc_penalized, startPoint, eps, out calcsF, out calcsGradient, out xLocations, out fx); //determine number of decimal places to show int dp = BitConverter.GetBytes(decimal.GetBits((decimal)eps)[3])[2] + 1; //Display result on console if (xMin != null) { Console.WriteLine("{0,10}{1,10:F" + dp + "}{2,10:F" + dp + "}{3,12:F" + dp + "}{4,10}{5,10}", eps, (double)xMin[0], (double)xMin[1], (double)objFunc_penalized(xMin), calcsF, calcsGradient); } } #endregion #region 3.) Save results to file, for display in matlab //Accuracy of the mesh DV start = new DV(new D[] { 0, 0 }); //x1 DV end = new DV(new D[] { 5, 5 }); //x2 D accuracy = 0.05; //Create the data mesh file Optimization.DataGeneration.MakeDataFile(@"..\..\..\..\ObjFunctionSurfacePoints.txt", objFunc_penalized, start, end, accuracy); //Save descent path to file Optimization.DataGeneration.SaveDescentToFile(@"..\..\..\..\DescentPath.txt", xLocations, fx); #endregion Console.ReadKey(); }