Skip to content

Instantly share code, notes, and snippets.

@mwidjaja1
Last active September 29, 2015 16:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mwidjaja1/10601773 to your computer and use it in GitHub Desktop.
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.
/*
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