Exemple #1
0
CostFunction CostFunction::sqrError()
{
    auto f = [](float output, float expected) {
        float diff = output - expected;
        return 0.5f * diff * diff;
    };
    return CostFunction(f);
}
Exemple #2
0
void WriteToMem(int num_measures)
{
	int i, ii, j;
	char laux[LONGSTRINGSIZE];
	double currentcost;

	i=1; /*It must start with 1*/
	while (measure[i].search[0] != '\0') { /*LTspice special case*/
		switch(spice) {
			case 1: /*Eldo*/
				break;
			case 2: /*HSPICE*/
				break;
			case 3: /*LTspice*/
				/*Str2Lower(laux);*/
				ii=strpos2(measure[i].data, "=", 1);                         /* LTspice measurement format is different than Eldo and HSPICE  */
				if (ii) {                                                    /* so specific code is added in here to cope with the difference */
					strsub(laux, measure[i].data, ii+1, LONGSTRINGSIZE); /*                                                               */
					strcpy(measure[i].data, laux);                       /*                                                               */
					if (strpos2(laux, "dB,", 1)) {                               /*Is the measurement a complex AC signal?*/
						ii=1;
						if (strpos2(measure[i].search, "phase", 1))
							ReadSubKey(laux, measure[i].data, &ii, ',', 0xB0, 0); /*measure the AC phase    */
						else
							ReadSubKey(laux, measure[i].data, &ii, '(', 'd', 0);  /*measure the AC magnitude*/
						strcpy(measure[i].data, laux);
					}
				}
				break;
			case 4: /*Spectre*/
				break;
			case 50: /*Qucs*/
				break;
			case 51: /*ngspice*/
				break;
			case 100: /*general*/
				break;
			default:
				printf("errfunc.c - WriteToMem -- Something unexpected has happened!\n");
				exit(EXIT_FAILURE);
		}
		i++;
	}
	DoMath(num_measures); /*'MATH=&...'; information is in the variable 'measured_data'*/

	i=1; /*It must start with 1*/
	while (measure[i].search[0] != '\0') {
		strcpy(laux, UNIQUECHAR);
		ii=0;
		ii=     strpos2(measure[i].var_name, laux, 1); /*if UNIQUECHAR is inexisting in measure[i].var_name and in Str2Lower(UNIQUECHAR)      */
		Str2Lower(laux);                               /*as well, this means we are processing a "MEASURE_VAR" line with intermediate data.   */
		ii=ii + strpos2(measure[i].var_name, laux, 1); /*ALL OTHERS MUST enter the following 'if' to have its measure[i].data processed       */
		if (ii >1) {
			ii=0;                                  /*UNIQUECHAR must be the first character. If not, this is an intermediate "MEASURE_VAR"*/
		}
		if (ii) {
			strcpy(laux, UNIQUECHAR);
			ii=(int)strlen(laux);
			strsub(laux, measure[i].var_name, ii+1, LONGSTRINGSIZE);             /*1- find output measure variable                                   */
										             /*   by copying the last part of the string starting from UNIQUECHAR*/
			j=0;
			while (strcasecmp(laux, measurements[j].meas_symbol)) {              /*2- get its order in measurements[i]                               */
				if (measurements[j].meas_symbol[0] == '\0') { /*if symbol is not found*/
					printf("errfunc.c - WriteToMem -- Symbol from SPICE simulation not found in memory: %s\n", laux);
					exit(EXIT_FAILURE);
				}
				j++;
			}

			if ((int)strlen(measure[i].data)) {
				strcpy(laux, measure[i].data);                               /*3- read measurement                                               */
				StripSpaces(laux);
			} else {
				#ifdef DEBUG
				i--;                             /* to keep the same code from initialize.c */
				sprintf(lkk, "%i", i);                    /* to remove integer added in (*) */
				ii=(int)strlen(lkk);                      /* to remove integer added in (*) */
				strcpy(lkk, measurements[i].meas_symbol); /* to remove integer added in (*) */
				lkk[(int)strlen(lkk)-ii]='\0';            /* to remove integer added in (*) */

				printf("errfunc.c - WriteToMem -- Data not read for measurement in *.cfg: %s\n", lkk);
				fflush(stdout); /*Sometimes the simulation does not converge, and so do not exit*/

				i++;
				#endif
			}

			measurements[j].measured_value=asc2real(laux, 1, (int)strlen(laux)); /*4- convert it to double                                           */

			if (!fcmp(measurements[j].measured_value, 0)) {                      /*5- check NaN and other text strings                               */
				if ((laux[0] < 43) || (laux[0] > 57) ) /*if its text*/
					if (measurements[j].objective_constraint == 1) /*1=MIN*/
						measurements[j].measured_value=+1e+30; /*so that a large cost is later assigned*/
					if (measurements[j].objective_constraint == 2) /*2=MAX*/
						measurements[j].measured_value=-1e+30; /*so that a large cost is later assigned*/
					if (measurements[j].objective_constraint == 4) /*4=LE*/
						measurements[j].measured_value=+1e+30; /*so that a large cost is later assigned*/
					if (measurements[j].objective_constraint > 4)  /*5=GE, 6=EQ*/
						measurements[j].measured_value=-1e+30; /*so that a large cost is later assigned*/
			}
		}
		i++;
	}

/*----------------------------------------------------------------------------*/
	/**/
	/*Step5: find cost*/
	currentcost=CostFunction();
	if (maxcost<currentcost)
		maxcost=currentcost;


	/**/
	/*Step6: save log information to file <hostname>.log*/
	if (LOG) {
		LogtoFile(currentcost);
	}
/*----------------------------------------------------------------------------*/
}
void MBO_Object::MBO()
{
	vector<Agent> tempElitism;
	Agent bestAgent;

	// Write final results to output.txt
	ofstream fout;  //输出文件
	fout.open("output.txt", ios::out | ios::app);  //输出文件

	if (!fout.is_open())
	{
		cout << "Error opening file"; exit(1);
	}

	// 重定向
	streambuf *coutbackup;
	coutbackup = cout.rdbuf(fout.rdbuf());  //用 rdbuf() 重新定向

	CostFunction(ag);
	PopSort(ag);
	bestAgent = ag[0];
	total_fit = ag[0].fit;

	// Begin the optimization loop
	for (int t = 0; t < max_t; ++t)
	{
		// Elitism strategy
		for (int ik = 0; ik < keep; ++ik)
		{
			tempElitism.push_back(ag.at(ik));
		}

		//////////////////    Divide the whole population into two subpopulations % % % %%%
		//	 Divide the whole population into Population1(Land1) and Population2(Land2)
		//	according to their fitness.
		//	 The monarch butterflies in Population1 are better than or equal to Population2.
		//	 Of course, we can randomly divide the whole population into Population1 and Population2.
		//	 We do not test the different performance between two ways.
		for (int popindex = 0; popindex < Popsize; ++popindex)
		{
			if (popindex < numButterfly1)
			{
				ag1[popindex] = ag[popindex];
			}
			else
			{
				ag2[popindex - numButterfly1] = ag[popindex];
			}
		}

		// Migration operator
		for (int k1 = 0; k1 < numButterfly1; ++k1)
		{
			for (int parnum1 = 0; parnum1 < dim; ++parnum1)
			{
				if (random(0.0, 1.0) * period <= partition)
				{
					int r2 = round(random(0, numButterfly1-1));
					Land1[parnum1] = ag1[r2].pos[parnum1];
				}
				else
				{
					int r3 = round(random(0, numButterfly2-1));
					Land1[parnum1] = ag2[r3].pos[parnum1];
				}
			}
			ag[k1].pos = Land1;
		}

		// Butterfly adjusting operator
		for (int k2 = 0; k2 < numButterfly2; ++k2)
		{
			auto scale = maxStepSize / pow(t+1, 2); // Smaller step for local walk
			// R = exprnd(MU) returns an array of random numbers chosen from the
			// exponential distribution with mean parameter MU
			int StepSzie = ceil(exprnd(2 * max_t));
			auto delataX = LevyFlight(StepSzie, dim);

			for (int parnum2 = 0; parnum2 < dim; ++parnum2)
			{
				if (random(0.0, 1.0) >= partition)
				{
					Land2[parnum2] = bestAgent.pos[parnum2];
				}
				else
				{
					int r4 = round(random(0, numButterfly2-1));
					Land2[parnum2] = ag2[r4].pos[1];
					if (random(0.0, 1.0) > BAR)
					{
						Land2[parnum2] = Land2[parnum2] + scale*(delataX[parnum2] - 0.5);
					}
				}
			}
			ag[numButterfly1 + k2].pos = Land2;
		}

		FeasibleFunction(ag);
		CostFunction(ag);
		PopSort(ag);
		bestAgent = ag[0];

		if (ag[0].fit < total_fit)
		{
			total_fit = ag[0].fit;
		}
		std::cout << total_fit << "   "; 

		// Replace the worst with the previous generation's elites.
		for (int ik = 0; ik < keep; ++ik)
		{
			ag.at(Popsize - ik - 1) = tempElitism.at(ik);
		}
		tempElitism.clear();

	}  // end for max_t


	// Close the file
	fout.close();

	cout.rdbuf(coutbackup);  //取消,恢复屏幕输出
}
Exemple #4
0
//=============================================================================
// PROCEDURE
//    CostFunction
//-----------------------------------------------------------------------------
// ARGUMENTS
//    mX - The current iteration of the n-dimensional X vector of stockpile 
//       percentages.
//    mAssay - The m x n matrix of assays of the stockpiles. This matrix may
//       contain all the assays including the irrelevant elements.
//    mSoftConstraints - a 4 x m matrix of constraints of the assay elements.
//       The 1st row is a row of minima (greater-than) constraints. The 2nd row
//       is contains the maxima (less-than) constraints. The 3rd and 4th rows
//       contain the constraint weightings (I call alpha's) for the 1st and 2nd
//       rows respectively. If an element of the 3rd or 4th row is 0, the
//       corresponding constraint in the 1st or 2nd row is ignored.
//    mSoftRatios - a p x 5 matrix of ratio constraints where p is the number
//       of constraints. The 1st and 2nd columns are the indices of the
//       dividend (numerator, I call gamma_i) and divisor (denominator, I call
//       gamma_j) of the ratio respectively. 
//       The 3rd column is the ratio constraint (I call r). 
//       The 4th column is the weighting (alpha).
//       The 5th (last) column is a boolean representing whether the ratio
//       constraint is a greater-than (1) or less-than (0) constraint. i.e. if
//       column 5 = 1, then the inequality constraint is:
//             (gamma_i/gamma_j) > r
//    dCost - return value - the calculated cost in.
//    mFirstDeriv - return value - the vector first partial derivative of the
//       cost function at the current vector x.
//-----------------------------------------------------------------------------
// RETURN
//    Success or otherwise of the call.
//=============================================================================
FUNCEXPORT
bool Optimise1stOrder(  double dBlendTonnes,
                        const ZMat & mAssays, 
                        const ZMat & mHardConstraints,
                        const ZMat & mSoftConstraints, 
                        const ZMat & mSoftRatios,
                        ZMat & mX)
{
   bool  bReturn = true;

   ZMat  *pAssays       = NULL;
   ZMat  *px            = NULL;
   ZMat  *pHardMaxs     = NULL;
   ZMat  *pHardMins     = NULL;
   ZMat  *pconstrained  = NULL;

   OptimiseSetLastErr("");


   try
   {
      int   m = mAssays.RowCount();
      int   n_orig = mAssays.ColCount();
      int   n;
      int   nXi;
      int   nRow;

      if (mX.RowCount() != n_orig)
      {
         //printf("X row dimension incompatible with Assay matrix\n");
         OptimiseSetLastErr("X row dimension incompatible with Assay matrix");
		 OptimiseSetLastErr("Last Search Fail: Incompatible Inputs");
         return false;
      }

      ZMat  HardMins_orig(mHardConstraints.Transpose().SubMat(":,0"));  // 1st column is mins.
      ZMat  HardMaxs_orig(mHardConstraints.Transpose().SubMat(":,1"));  // 2nd column is max's

      //% Check. If the sum of the elements of the HardMaxs_orig < 1 or the sum of
      //% the elements of HardMins_orig > 1, we have an unsolvable solution.
      //if (sum(HardMins_orig) > 1) | (sum(HardMaxs_orig) < 1)
      //   error ('Unsolveable problem due to hard constraints');
      //end
      if ((ZMat::Sum(HardMins_orig) > 1) || (ZMat::Sum(HardMaxs_orig) < 1))
      {
         printf("The hard contraints are inconsistent\n");
         OptimiseSetLastErr("The hard contraints are inconsistent");
	     OptimiseSetLastStatus("Last Search Fail: Hard Constraint Inconsistent");
         return false;
      }

      //% Check. If any of the maxs are less than the mins, we also have a
      //% nonsolvable problem.
      //for j = 1:n_orig,
      //   if (HardMins_orig(j) > HardMaxs_orig(j))
      //      error (['Unsolveable problem due to hard constraints for stockpile ', j]);
      //   end
      //end
      for (int j = 0; j < n_orig; j++)
      {
         if (HardMins_orig[j][0] > HardMaxs_orig[j][0])
         {
            //printf("The hard contraints are inconsistent\n");
            OptimiseSetLastErr("The hard contraints are inconsistent");
			OptimiseSetLastStatus("Last Search Fail: Hard Constraint Inconsistent");
            return false;
         }
      }

      //% Start x off with valid values. That is the sum of the elements = 1
      //% and all elements lie between their associated hard minima and maxima.
      //HardRange = HardMaxs_orig - HardMins_orig;
      //temp = (1 - sum(HardMins_orig))/sum(HardRange);
      //x_orig = HardMins_orig + temp*HardRange;
      ZMat HardRange = HardMaxs_orig - HardMins_orig;
      double temp = (1.0 - ZMat::Sum(HardMins_orig))/ZMat::Sum(HardRange);
      ZMat  x_orig(HardMins_orig + HardRange*temp);
      //% DEBUG
      // ZMat  x_orig("[0.4;0.6]");
      //% END DEBUG

      // Do some checks on the SoftConstraints matrix for consistency. In the
      // algorithm we check to see if the weighting is non-zero and, if so, we
      // 

      //% Next we determine which elements of the x vector are fully
      //% constrained. If we find any, we'll reduce the order of the problem.
      //% We store the constraint info in the constrained_orig vector below, one
      //% for each element of the x vector. 0 is not constrained, 1 is 
      //% constrained at a minima and 2 is constrained at a maxima. If 
      //% minima = maxima, then the value will be 3.
      //constrained_orig = zeros(n_orig,1);
      //constrained_count = 0;
      //for index = 1:n_orig,
      //    if ((HardMaxs_orig(index) - HardMins_orig(index)) < epsilon)
      //        constrained_orig(index) = 3;
      //        constrained_count = constrained_count + 1;
      //    end
      //end
      ZMat  constrained_orig(n_orig, 1, 0.0);
      int   constrained_count = 0;
      for (int index = 0; index < n_orig; index++)
      {
         if ((HardMaxs_orig[index][0] - HardMins_orig[index][0]) < dEpsilon)
         {
            constrained_orig[index][0] = 3;
            constrained_count++;
         }  // IF
      }


      if (constrained_count > 0)
      {
         // % we need to reduce the order of the problem
         // n = n_orig - constrained_count;
         // nXi = 1;
         // assays = zeros(m,n);
         // x = zeros(n,1);
         // HardMaxs = ones(n,1);
         // HardMins = zeros(n,1);
         // constrained = zeros(n,1);

         n           = n_orig - constrained_count;
         nXi         = 0;
         pAssays     = new ZMat(m, n, 0.0);
         px          = new ZMat(n, 1, 0.0);
         pHardMaxs   = new ZMat(n, 1, 1.0);
         pHardMins   = new ZMat(n,1, 0.0);
         pconstrained = new ZMat(n,1, 0.0);

         //for i = 1:n_orig,
         //   if (constrained_orig(i) ~= 3)
         //         x(nXi) = x_orig(i);
         //         assays(:,nXi) = assays_orig(:,i);
         //         HardMaxs(nXi) = HardMaxs_orig(i);
         //         HardMins(nXi) = HardMins_orig(i);
         //         nXi = nXi + 1;
         //   end
         //end
         for (int i = 0; i < n_orig; i++)
            if (constrained_orig[i][0] != 3)
            {
               (*px)[nXi][0] = x_orig[i][0];
               for (nRow = 0; nRow < pAssays->RowCount(); nRow++)
                  (*pAssays)[nRow][nXi] = mAssays[nRow][i];
               (*pHardMaxs)[nXi][0] = HardMaxs_orig[i][0];
               (*pHardMins)[nXi][0] = HardMins_orig[i][0];
               nXi++;
            }
      }
      else
      {
         //n = n_orig;
         //x = x_orig;
         //assays = assays_orig;
         //constrained = constrained_orig;
         //HardMaxs = HardMaxs_orig;
         //HardMins = HardMins_orig;
         n = n_orig;
         px          = new ZMat(x_orig);
         pAssays     = new ZMat(mAssays);
         pconstrained= new ZMat(constrained_orig);
         pHardMaxs   = new ZMat(HardMaxs_orig);
         pHardMins   = new ZMat(HardMins_orig);
      }


      //% Now we begin the iterative search.
      //% First some initial conditions
      //iter = 1;
      //cost_km1 = 1e12;
      //[cost_k, Del] = CostFunction12(x, assays, SoftConstraints, SoftAlphas, SoftRatios, 0);

      //% We record the current maximum step size we will take along the normalised
      //% derivative vector in the negative direction (i.e. towards zero) in:
      //max_step_size = n*1/sqrt(2);
      int      iter = 1;
      double   cost_km1 = 1e12;
      double   cost_k;

      ZMat  mFirstDeriv(n,1,0.0);

      if (!CostFunction(*px, *pAssays, mSoftConstraints, mSoftRatios, cost_k, mFirstDeriv))
      {
         OptimiseSetLastErr("Cost Function Failed");
         bReturn = false;
         goto __FreeMemory;
      }

      //% We record the current maximum step size we will take along the normalised
      //% derivative vector in the negative direction (i.e. towards zero) in:
      double   max_step_size = n*1/sqrt(2.0);
      ZMat     NextStep(n, 1, 0.0);

      // while (abs(cost_k - cost_km1) > epsilon) & (iter < 100)
      while ((fabs(cost_k - cost_km1) > dEpsilon) && (iter < 100))
      {
         //cost_km1 = cost_k;
         //% Calculate the conventional Newton step
         //NextStep = -1*Del;
         cost_km1 = cost_k;
         // % Calculate the conventional Newton step
         NextStep = mFirstDeriv*(-1.0);
           
         //% Next we constrain the step to lying on the x1 + x2 + ... + xn =
         //% 1 surface. To do this, the NextStep vector must have a net sum
         //% of zero.
         //NextStep = NextStep - ones(n,1)*sum(NextStep/n);
         ZMat  ones(n,1,1.0);
         NextStep -= ones*(ZMat::Sum(NextStep)/double(n));
          
         //% Next we move through the step and work out which elements of the
         //% x vector are in constraint. If they are, we work out if the
         //% current step will maintain this constraint and if so we remove
         //% that element from the adjusted step.
         //constraint_count = 0;
         //for index = 1:n,
         //   if (constrained(index) > 0)
         //         if (constrained(index) == 3)
         //            NextStep(index) = 0;
         //            constraint_count = constraint_count + 1;
         //         elseif (constrained(index) == 1) % minima, greater-than
         //            if (NextStep(index) > 0)
         //               constrained(index) = 0;
         //            else
         //               NextStep(index) = 0;
         //               constraint_count = constraint_count + 1;
         //            end
         //         elseif (constrained(index) == 2) % maxima, less-than
         //            if (NextStep(index) < 0)
         //               constrained(index) = 0;
         //            else
         //               NextStep(index) = 0;
         //               constraint_count = constraint_count + 1;
         //            end
         //         end
         //   end
         int   constraint_count = 0;
         for (int index = 0; index < n; index++)
         {
            int   nConstraintType = Round((*pconstrained)[index][0]);
            switch(nConstraintType)
            {
            case 3:
               NextStep[index][0] = 0;
               constraint_count++;
               break;
            case 1:  //  minima, greater-than
               if (NextStep[index][0] > 0)
                  (*pconstrained)[index][0] = 0;
               else
               {
                  NextStep[index][0] = 0;
                  constraint_count++;
               }
               break;
            case 2:  // maxima, less-than
               if (NextStep[index][0] < 0)
                  (*pconstrained)[index][0] = 0;
               else
               {
                  NextStep[index][0] = 0;
                  constraint_count++;
               }
               break;
            case 0:
            default:
               break;
            }  // SWITCH
         }  // FOR
          
         // % If all elements are in constraint, we terminate.
         //if (constraint_count >= (n-1))
         //   break;  
         //end
         if (constraint_count >= (n-1))
		 {
		  //LogWarning("Optimise1stOrder", 0,"Optimiser Exiting At Iteration %d: All elements in constraint",iter);
			OptimiseSetLastErr("All elements in constraint");
			OptimiseSetLastStatus("Last Search Fail: Exit on All Elements under Constraint");
			bReturn = false;
            break;  
		 }
          
         //% We correct those elements of the NextStep that correspond to
         //% elements of the x vector not in constraint, so that the
         //% NextStep vector again complies with the equality condition.
         //correction = sum(NextStep)/(n - constraint_count);
         //for index = 1:n,
         //   if (constrained(index) == 0) % not constrained
         //         NextStep(index) = NextStep(index) - correction;
         //   end
         //end
         double correction = ZMat::Sum(NextStep)/double(n - constraint_count);
         for (index = 0; index < n; index++)
            if ((*pconstrained)[index][0] == 0)  // % not constrained
               NextStep[index][0] -= correction;
          
         //% If the NextStep at this point is so pathetically small as to generate
         //% significant errors because of rounding problems, we call it a day.
         //significant_element_found = 0;
         //for index = 1:n,
         //   if (abs(NextStep(index)) > epsilon)
         //         significant_element_found = 1;
         //         break;
         //   end
         //end
         //if (significant_element_found == false)
         //   break;  % Terminate the optimisation search.
         //end
         bool  significant_element_found = false;
         for (index = 0; index < n; index++)
         {
            if (fabs(NextStep[index][0]) > dEpsilon)
            {
               significant_element_found = true;
               break;
            }
         }
         if (!significant_element_found)
		 {
		  ////LogWarning("Optimise1stOrder", 0,"Optimiser next step to small - search complete"
			OptimiseSetLastStatus("Last Search Fail: Step Too Small");
            break;  // Terminate the optimisation search.
		 } 
         // Next we normalise the NextStep vector.
         // NextStep = NextStep/sqrt(NextStep'*NextStep);
         NextStep /= sqrt((NextStep.Transpose()*NextStep)[0][0]);

         //% Next we work how far we can go before out current vector runs into a
         //% hard constraint. We will use gamma as the scalar multiplier of the
         //% NextStep vector to specify the distance we'll move. This will be
         //% constrained to the range 0 to gamma_max where gamma_max corresponds
         //% to the movement along the vector to the nearest constraint, or to
         //% max_step_size.
         //gamma_max = max_step_size; 
         //for index = 1:n,
         //   if (constrained(index) == 0) % Not currently constrained.
         //         if (abs(NextStep(index)) > epsilon)
         //            if (NextStep(index) > 0)
         //               this_gamma_max = (HardMaxs(index) - x(index))/NextStep(index);
         //            else % NextStep(index) < 0
         //               this_gamma_max = (HardMins(index) - x(index))/NextStep(index);
         //            end
         //            if (this_gamma_max < gamma_max)
         //               gamma_max = this_gamma_max;
         //            end
         //         end
         //   end
         //end
         double   gamma_max = max_step_size; 
         double   this_gamma_max;
         for (index = 0; index < n; index++)
         {
            if ((*pconstrained)[index][0] == 0) //  % Not currently constrained.
            {
               if (fabs(NextStep[index][0]) > dEpsilon)
               {
                  if (NextStep[index][0] > 0)
                     this_gamma_max = ((*pHardMaxs)[index][0] - (*px)[index][0])/NextStep[index][0];
                  else //  NextStep(index) < 0
                     this_gamma_max = ((*pHardMins)[index][0] - (*px)[index][0])/NextStep[index][0];

				  if (this_gamma_max < dEpsilon)
			      {
				   // TO DO: Work out actual stockpile number from index
				   //LogWarning("Optimise1stOrder", 0,"Optimiser running into hard constraint for non-empty stockpile %d",index);
				  }

                  if (this_gamma_max < gamma_max)
				  {
                     gamma_max = this_gamma_max;
				  }

               }  // IF
            }
         }  // FOR

         // If we find the maximum step we can take is no step at all, we
         // terminate.
         if (gamma_max < dEpsilon)
		 {
      //LogWarning("Optimise1stOrder", 0,"Optimiser Exiting At Iteration %d: Running into hard constraint",iter);
      OptimiseSetLastErr("Running into hard constraint");
			OptimiseSetLastStatus("Last Search Fail: Exit on Hard Constraint");
			bReturn = false;
            break;
		 }
          
         //% If the NextStep at this point is so pathetically small as to generate
         //% significant errors because of rounding problems, we call it a day.
         //significant_element_found = 0;
         //for index = 1:n,
         //   if (abs(NextStep(index)) > epsilon)
         //         significant_element_found = 1;
         //         break;
         //   end
         //end
         //if (significant_element_found == false)
         //   break;  % Terminate the optimisation search.
         //end
         significant_element_found = false;
         for (index = 0; index < n; index++)
         {
            if (fabs(NextStep[index][0]) > dEpsilon)
            {
               significant_element_found = true;
               break;
            }
         }
         if (!significant_element_found)
		 {
	    ////LogWarning("Optimise1stOrder", 0,"Optimiser next step to small - exiting"
      OptimiseSetLastErr("Step Too Small");
			OptimiseSetLastStatus("Last Search Fail: Step Too Small");
			bReturn = false;
            break;  // Terminate the optimisation search.
		 }
         //% Now we implement a Golden section search. We currently have two
         //% bounds. The current position x, and x + NextStep*gamma_max. We want
         //% to find the value of gamma <= gamma_max that minimises the cost
         //% function.
         //gamma_lo = 0;
         //gamma_hi = gamma_max;
         //gamma_range = gamma_max;
         //gamma_1 = gamma_hi - gamma_range*golden_ratio;
         //gamma_2 = gamma_lo + gamma_range*golden_ratio;
         //cost_lo = cost_k;
         //cost_hi = CostFunction1(x + gamma_hi*NextStep, assays, SoftConstraints, SoftAlphas, SoftRatios, 0);
         //cost_1 =  CostFunction1(x + gamma_1 *NextStep, assays, SoftConstraints, SoftAlphas, SoftRatios, 0);
         //cost_2 =  CostFunction1(x + gamma_2 *NextStep, assays, SoftConstraints, SoftAlphas, SoftRatios, 0);
         double   gamma;
         double   gamma_lo = 0;
         double   gamma_hi = gamma_max;
         double   gamma_range = gamma_max;
         double   gamma_1 = gamma_hi - gamma_range*golden_ratio;
         double   gamma_2 = gamma_lo + gamma_range*golden_ratio;
         double   cost_lo = cost_k;
         double   cost_hi;
         double   cost_1;
         double   cost_2;
         CostFunction((*px) + NextStep*gamma_hi, *pAssays, mSoftConstraints, mSoftRatios, cost_hi);
         CostFunction((*px) + NextStep*gamma_1 , *pAssays, mSoftConstraints, mSoftRatios, cost_1);
         CostFunction((*px) + NextStep*gamma_2 , *pAssays, mSoftConstraints, mSoftRatios, cost_2);

         //for i = 0:20,
         //   if (cost_1 < cost_2)
         //         gamma_hi = gamma_2;
         //         cost_hi = cost_2;
         //         gamma_range = gamma_hi - gamma_lo;
         //         gamma_2 = gamma_1;
         //         cost_2 = cost_1;
         //         gamma_1 = gamma_hi - gamma_range*golden_ratio;
         //         cost_1 = CostFunction1(x + gamma_1 *NextStep, assays, SoftConstraints, SoftAlphas, SoftRatios, 0);
         //   else
         //         gamma_lo = gamma_1;
         //         cost_lo = cost_1;
         //         gamma_range = gamma_hi - gamma_lo;
         //         gamma_1 = gamma_2;
         //         cost_1 = cost_2;
         //         gamma_2 = gamma_lo + gamma_range*golden_ratio;
         //         cost_2 = CostFunction1(x + gamma_2 *NextStep, assays, SoftConstraints, SoftAlphas, SoftRatios, 0);
         //   end
         //end
         for (int i = 0; i < 20; i++)
         {
            if (cost_1 < cost_2)
            {
               gamma_hi = gamma_2;
               cost_hi = cost_2;
               gamma_range = gamma_hi - gamma_lo;
               gamma_2 = gamma_1;
               cost_2 = cost_1;
               gamma_1 = gamma_hi - gamma_range*golden_ratio;
               CostFunction((*px) + NextStep*gamma_1, *pAssays, mSoftConstraints, mSoftRatios, cost_1);
            }
            else
            {
               gamma_lo = gamma_1;
               cost_lo = cost_1;
               gamma_range = gamma_hi - gamma_lo;
               gamma_1 = gamma_2;
               cost_1 = cost_2;
               gamma_2 = gamma_lo + gamma_range*golden_ratio;
               CostFunction((*px) + NextStep*gamma_2, *pAssays, mSoftConstraints, mSoftRatios, cost_2);
            }
         }
          
         //if (cost_1 < cost_2)
         //   gamma = gamma_1;
         //   cost_k = cost_1;
         //else
         //   gamma = gamma_2;
         //   cost_k = cost_2;
         //end
         if (cost_1 < cost_2)
         {
            gamma = gamma_1;
            cost_k = cost_1;
         }
         else
         {
            gamma = gamma_2;
            cost_k = cost_2;
         }

         //% Just in case the cost function is montonically decreasing in the
         //% direction of the vector, we also check to see if the constrained
         //% limit is in fact the lowest point.
         //if (cost_hi < cost_k) 
         //   gamma = gamma_hi;
         //   cost_k = cost_hi;
         //end
         if (cost_hi < cost_k) 
         {
            gamma = gamma_hi;
            cost_k = cost_hi;
         }
          
         // Now we actually perform the step ...
         // x = x + gamma*NextStep;
         (*px) += NextStep*gamma;
          
         //% ... and we re-call the CostFunction since we need the first
         //% derivative.
         //[cost_k, Del] = CostFunction12(x, assays, SoftConstraints, SoftAlphas, SoftRatios, 0);
         CostFunction(*px, *pAssays, mSoftConstraints, mSoftRatios, cost_k, mFirstDeriv);
          
         //% Reduce the maximum step size by the maximum of 2/3 of the current max
         //% size or the actual step taken.
         //max_step_size = max(max_step_size*0.2, gamma);
         max_step_size = Max(max_step_size*0.2, gamma);

         // Now we update the constraint vector to reflect the new constraint status.
         for (int index = 0; index < n; index++)
         {
            double   dx = (*px)[index][0];
            (*pconstrained)[index][0] = 0;
            if (dx <= ((*pHardMins)[index][0] + dEpsilon))
            {
               if (dx >= ((*pHardMaxs)[index][0] - dEpsilon))
                  (*pconstrained)[index][0] = 3;
               else
                  (*pconstrained)[index][0] = 1;
            }
            else if (dx >= ((*pHardMaxs)[index][0] - dEpsilon))
               (*pconstrained)[index][0] = 2;
         }  // FOR

         iter++;
      }  //% WHILE

      // Now we reconstruct the original x vector
      //nXi = 1;
      //for i = 1:n_orig,
      //   if (constrained_orig(i) ~= 3)
      //      x_orig(i) = x(nXi);
      //      nXi = nXi + 1;
      //   end
      //end
      nXi = 0;
      for (int i = 0; i < n_orig; i++)
      {
         if (constrained_orig[i][0] != 3)
         {
            x_orig[i][0] = (*px)[nXi][0];
            nXi++;
         }  // IF
      }  // FOR

      mX = x_orig;

	  if (iter > 100)
	  {
		//LogWarning("Optimise1stOrder", 0,"Optimiser finished searching in %d iterations",iter);
    OptimiseSetLastErr("Exit after 100 iterations");
    OptimiseSetLastStatus("Last Search Fail: Exit after 100 iterations");
		bReturn = false;
	  }
	  else
	  {
	    if ((fabs(cost_k - cost_km1) <= dEpsilon) && (bReturn))
			OptimiseSetLastStatus("Last Search OK: Converged");
	  }

   }  // TRY
   catch(...)
   {
      OptimiseSetLastErr("An exception occurred during calculation");
      OptimiseSetLastStatus("Last Search Fail: Exit on Exception");
      bReturn = false;
   }

__FreeMemory:
   if (pAssays != NULL)
      delete pAssays;
   if (px != NULL)
      delete px;
   if (pHardMaxs != NULL)
      delete pHardMaxs;
   if (pHardMins != NULL)
      delete pHardMins;
   if (pconstrained != NULL)
      delete pconstrained;

   return bReturn;
}