Last active
September 29, 2015 16:04
-
-
Save mwidjaja1/10601773 to your computer and use it in GitHub Desktop.
My first experience with C led me to the Nelder Mead Numerical Optimization algorithm, to find the local minimum.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Matthew Widjaja | |
Project 1: Nelder Mead Numerical Optimization | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <math.h> | |
main() | |
{ | |
/* --- Step 0: DECLARES INPUTS ------------------------------------ | |
** <These are the initial points used> | |
** ------------------------------------------------------------- */ | |
float x, y, z, newX, newY; //Variables for Equ Input | |
float xPt[] = {0.0, 1.2, 0.0}; //{Pt1, Pt2, Pt3} for X | |
float yPt[] = {0.0, 0.0, 0.8}; //{Pt1, Pt2, Pt3} for Y | |
float zPt[] = {0.0, 0.0, 0.0}; //{Pt1, Pt2, Pt3} for Z | |
/* --- Step 1: DECLARES SORTING & NEW VARIABLES ------------------- | |
** <These variables are first used in Step 3B, to sort nodes.> | |
** ------------------------------------------------------------- */ | |
float maxX, maxY, maxZ; //States values representing the Max | |
float medX, medY, medZ; //States values representing the Medium | |
float minX, minY, minZ; //States values representing the Min | |
int maxNode, medNode; //States which Node is Max & Med | |
/* --- Step 2: DECLARES STEP 3 VARIABLES --------------------------- | |
** <These variables are used in Step 3C-3E, to determine where | |
** the 4th node is, which case should be used, & when to stop.> | |
** ------------------------------------------------------------- */ | |
int i = 0; int trialI = 1; //3A & 3H: Creates a Counter | |
float mX, mY, rX, rY; //3C: Projects the 4th Node location | |
float cX, cY; //3E.1: Variable 'C' is for 'Case 2' | |
int caseMethod = 0; //Determines which case to use | |
float stopX = 1; //The difference between oldX & newX | |
float stopY = 1; //The difference between oldY & newY | |
float stopPt = 0.01; //Stop Variable Condition | |
/* --- Step 3: RUNS NELDER MEAD ------------------------------------ | |
** <This model continues until stopX & stopY are <= stopPt. When | |
** Step 3 finishes, new values are stored in the Step 0 Arrays.> | |
** -------------------------------------------------------------- */ | |
while (fabsf(stopX) >= stopPt && fabsf(stopY) >= stopPt) | |
{ | |
/* --- Step 3A: RETRIEVES OUTPUTS -------------------------------- | |
** <Uses Step 0 Array of initial points to solve f(x,y) to obtain | |
** outputs, which will be stored in the Z-Array.> | |
** ------------------------------------------------------------ */ | |
for(i = 0; i < 3; i++) { | |
x = xPt[i]; y = yPt[i]; | |
zPt[i] = pow(x,2) - (4*x) + pow(y,2) - y - (x*y); | |
} | |
/* --- Step 3B: DETERMINE MIN & MAX POINTS -------------------------- | |
** <We find the max vertex, by comparing each vertex with the other 2 | |
** vertexes in order to determine which vertexes are the min & max. | |
** Also, we assign an numerical value to 'i2' to note which of these | |
** cases are true, which will be used in Step 3F.> | |
** --------------------------------------------------------------- */ | |
if (zPt[0] >= zPt[1] && zPt[0] >= zPt[2]) { | |
maxNode = 1; maxZ = zPt[0]; maxX = xPt[0]; maxY = yPt[0]; | |
if (zPt[1] >= zPt[2]) { | |
medNode = 2; medZ = zPt[1]; medX = xPt[1]; medY = yPt[1]; | |
minZ = zPt[2]; minX = xPt[2]; minY = yPt[2]; | |
} | |
else { | |
medNode = 3; medZ = zPt[2]; medX = xPt[2]; medY = yPt[2]; | |
minZ = zPt[1]; minX = xPt[1]; minY = yPt[1]; | |
} | |
} | |
else if (zPt[1] >= zPt[0] && zPt[1] >= zPt[2]) { | |
maxNode = 2; maxZ = zPt[1]; maxX = xPt[1]; maxY = yPt[1]; | |
if (zPt[0] >= zPt[2]) { | |
medNode = 1; medZ = zPt[0]; medX = xPt[0]; medY = yPt[0]; | |
minZ = zPt[2]; minX = xPt[2]; minY = yPt[2]; | |
} | |
else { | |
medNode = 3; medZ = zPt[2]; medX = xPt[2]; medY = yPt[2]; | |
minZ = zPt[0]; minX = xPt[0]; minY = yPt[0]; | |
} | |
} | |
else if (zPt[2] >= zPt[0] && zPt[2] >= zPt[1]) { | |
maxNode = 3; maxZ = zPt[2]; maxX = xPt[2]; maxY = yPt[2]; | |
if (zPt[1] >= zPt[0]) { | |
medNode = 2; medZ = zPt[1]; medX = xPt[1]; medY = yPt[1]; | |
minZ = zPt[0]; minX = xPt[0]; minY = yPt[0]; | |
} | |
else { | |
medNode = 1; medZ = zPt[0]; medX = xPt[0]; medY = yPt[0]; | |
minZ = zPt[1]; minX = xPt[1]; minY = yPt[1];} | |
} | |
else | |
printf("Error at Min & Max Points \n"); | |
/* --- Step 3C: DETERMINE MIDPOINT ------------------------------ | |
** <We take the two minimum points to apply the Midpoint Formula | |
** and get the distance between the midpoint & min vertex.> | |
** ----------------------------------------------------------- */ | |
mX = 0.5 * (medX + minX); | |
mY = 0.5 * (medY + minY); | |
rX = (2 * mX) - maxX; | |
rY = (2 * mY) - maxY; | |
x = rX; y = rY; | |
z = pow(x,2) - (4*x) + pow(y,2) - y - (x*y); | |
/* --- Step 3D: DETERMINE LOGIC --------------------------------- | |
** <In relation to the replacing node, we determine if we have to | |
** reflect/extend or contract/shrink when placing our new node.> | |
** ----------------------------------------------------------- */ | |
if (z < medZ) | |
{caseMethod = 1;} | |
else | |
{caseMethod = 2;} | |
/* --- Step 3E.1: CASEMETHOD #01 ----------------- | |
** <This only applies to CaseMethod #01. Here, we | |
** either reflect shrink our new node.> | |
** -------------------------------------------- */ | |
if (caseMethod == 1) { | |
if (minZ < z) | |
{newX = rX; newY = rY; | |
} | |
else { | |
newX = (2 * rX) - mX; | |
newY = (2 * rY) - mY; | |
x = newX; y = newY; | |
z = pow(x,2) - (4*x) + pow(y,2) - y - (x*y); | |
if (z < minZ) | |
{newX = newX; newY = newY;} | |
else | |
{newX = rX; newY = rY;} | |
} | |
} | |
/* --- Step 3E.2: CASEMETHOD #02 ----------------- | |
** <This only applies to CaseMethod #02. Here, we | |
** either reflect shrink our new node.> | |
** -------------------------------------------- */ | |
if (caseMethod == 2) | |
{ | |
{if (z < maxZ) | |
{newX = rX; newY = rY;} | |
else | |
{newX = maxX; newY = maxY;}; | |
} | |
{cX = 0.5 * (mX + newX); | |
cY = 0.5 * (mY + newY); | |
x = cX; y = cY; | |
z = pow(x,2) - (4*x) + pow(y,2) - y - (x*y); | |
} | |
{if (z < maxZ) | |
{newX = cX; newY = cY;} | |
else | |
{cX = 0.5 * (minX + maxX); | |
cY = 0.5 * (minY + maxY); | |
x = cX; y = cY; | |
z = pow(x,2) - (4*x) + pow(y,2) - y - (x*y); | |
newX = cX; newY = cY; | |
caseMethod = 3; | |
} | |
} | |
} | |
/* --- Step 3F: ASSIGNING NEW VERTEX -------------------------------- | |
** <We replace the max node w. the newX & newY values from above.> | |
** --------------------------------------------------------------- */ | |
if (maxNode == 1) | |
{xPt[0] = newX; yPt[0] = newY;} | |
else if (maxNode == 2) | |
{xPt[1] = newX; yPt[1] = newY;} | |
else if (maxNode == 3) | |
{xPt[2] = newX; yPt[2] = newY;} | |
/* --- Step 3G: CASEMETHOD #03 ------------------------------------ | |
** <If z < maxZ from step 3E.2, we set mX & mY to also replace the | |
** medium node, in addition to having the max node replaced in 3F.> | |
** ------------------------------------------------------------- */ | |
if (caseMethod == 3) { | |
if (medNode == 1) | |
{xPt[0] = mX; yPt[0] = mY;} | |
else if (medNode == 2) | |
{xPt[1] = mX; yPt[1] = mY;} | |
else if (medNode == 3) | |
{xPt[2] = mX; yPt[2] = mY;} | |
} | |
/* --- Step 3H: STOP VALUE & TRIAL COUNTER ------------------------- | |
** <We get the difference between the new x & y and old x & y values | |
** to determine if we should stop. Also, we present the new values.> | |
** -------------------------------------------------------------- */ | |
trialI++; | |
printf("On Trial %d\n",trialI); | |
printf("1 = (%f,%f), 2 = (%f,%f), 3 = (%f,%f)\n\n",xPt[0],yPt[0],xPt[1],yPt[1],xPt[2],yPt[2]); | |
stopX = newX - maxX; | |
stopY = newY - maxY; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment