/// <summary>
        /// Check whether the points in the error profile have so little range that we
        /// consider ourselves to have converged
        /// </summary>
        /// <param name="convergenceTolerance"></param>
        /// <param name="errorProfile"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        static bool HasConverged(double convergenceTolerance, ErrorProfile errorProfile, double[] errorValues)
        {
            double range = 2 * Math.Abs(errorValues[errorProfile.HighestIndex] - errorValues[errorProfile.LowestIndex]) /
                           (Math.Abs(errorValues[errorProfile.HighestIndex]) + Math.Abs(errorValues[errorProfile.LowestIndex]) + JITTER);

            return(range < convergenceTolerance);
        }
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        /// <param name="scaleFactor"></param>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <param name="objectiveFunction"></param>
        /// <returns></returns>
        static double TryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector <double>[] vertices,
                                        double[] errorValues, IObjectiveFunction objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector <double> centroid = ComputeCentroid(vertices, errorProfile);

            // define the vector from the centroid to the high point
            Vector <double> centroidToHighPoint = vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector <double> newPoint = centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            // evaluate the new point
            objectiveFunction.EvaluateAt(newPoint);
            double newErrorValue = objectiveFunction.Value;

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex]    = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return(newErrorValue);
        }
Exemple #3
0
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        /// <param name="scaleFactor"></param>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static double _tryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector[] vertices,
                                                 double[] errorValues, ObjectiveFunctionDelegate objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector centroid = _computeCentroid(vertices, errorProfile);

            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            //TODO: should see if this is a good point by constraints, otherwise throw it out

            // evaluate the new point
            double newErrorValue = objectiveFunction(newPoint.Components);

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex]    = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return(newErrorValue);
        }
 public double StepAlgo(out Dictionary <string, Dictionary <string, double> > fitnessModeValue, out Dictionary <string, Dictionary <string, double> > absMaxErr)
 {
     errorProfile = _evaluateSimplex(errorValues);
     // attempt a reflection of the simplex
     reflectionPointValue = _tryToScaleSimplex(-1.0, ref errorProfile, vertices, errorValues, out fitnessModeValue, out absMaxErr);
     ++evaluationCount;
     if (reflectionPointValue >= errorValues[errorProfile.LowestIndex])
     {
         // it's better than the best point, so attempt an expansion of the simplex
         expansionPointValue = _tryToScaleSimplex(2.0, ref errorProfile, vertices, errorValues, out fitnessModeValue, out absMaxErr);
         ++evaluationCount;
     }
     else if (reflectionPointValue <= errorValues[errorProfile.NextHighestIndex])
     {
         // it would be worse than the second best point, so attempt a contraction to look
         // for an intermediate point
         double currentWorst          = errorValues[errorProfile.HighestIndex];
         double contractionPointValue = _tryToScaleSimplex(0.5, ref errorProfile, vertices, errorValues, out fitnessModeValue, out absMaxErr);
         ++evaluationCount;
         if (contractionPointValue <= currentWorst)
         {
             // that would be even worse, so let's try to contract uniformly towards the low point;
             // don't bother to update the error profile, we'll do it at the start of the
             // next iteration
             _shrinkSimplex(errorProfile, vertices, errorValues, out fitnessModeValue, out absMaxErr);
             evaluationCount += numVertices;     // that required one function evaluation for each vertex; keep track
         }
     }
     ComponenttoParamValue(vertices[errorProfile.LowestIndex].Components);//errorValues[errorProfile.LowestIndex]
     return(OptProblem.fitnessFunctions.Compute(out fitnessModeValue, out absMaxErr, true));
 }
Exemple #5
0
        /// <summary>
        /// Examine all error values to determine the ErrorProfile
        /// </summary>
        private static ErrorProfile EvaluateSimplex(double[] errorValues)
        {
            ErrorProfile errorProfile = new ErrorProfile();

            if (errorValues[0] > errorValues[1])
            {
                errorProfile.HighestIndex     = 0;
                errorProfile.NextHighestIndex = 1;
            }
            else
            {
                errorProfile.HighestIndex     = 1;
                errorProfile.NextHighestIndex = 0;
            }

            for (int index = 0; index < errorValues.Length; index++)
            {
                double errorValue = errorValues[index];
                if (errorValue <= errorValues[errorProfile.LowestIndex])
                {
                    errorProfile.LowestIndex = index;
                }
                if (errorValue > errorValues[errorProfile.HighestIndex])
                {
                    errorProfile.NextHighestIndex = errorProfile.HighestIndex; // downgrade the current highest to next highest
                    errorProfile.HighestIndex     = index;
                }
                else if (errorValue > errorValues[errorProfile.NextHighestIndex] && index != errorProfile.HighestIndex)
                {
                    errorProfile.NextHighestIndex = index;
                }
            }

            return(errorProfile);
        }
        /// <summary>
        /// Check whether the points in the error profile have so little range that we
        /// consider ourselves to have converged
        /// </summary>
        /// <param name="errorProfile"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static bool _hasConverged(double convergenceTolerance, ErrorProfile errorProfile, double[] errorValues)
        {
            double range = 2 * Math.Abs(errorValues[errorProfile.HighestIndex] - errorValues[errorProfile.LowestIndex]) /
                           (Math.Abs(errorValues[errorProfile.HighestIndex]) + Math.Abs(errorValues[errorProfile.LowestIndex]) + JITTER);

            if (range < convergenceTolerance)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Contract the simplex uniformly around the lowest point
        /// </summary>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        private static void _shrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues,
                                           ObjectiveFunctionDelegate objectiveFunction, double[] tt, double[] Y)
        {
            Vector lowestVertex = vertices[errorProfile.LowestIndex];

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != errorProfile.LowestIndex)
                {
                    vertices[i]    = (vertices[i].Add(lowestVertex)).Multiply(0.5);
                    errorValues[i] = objectiveFunction(vertices[i].Components, tt, Y);
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Contract the simplex uniformly around the lowest point
        /// </summary>
        private static void ShrinkSimplex(ErrorProfile errorProfile, Vector <double>[] vertices, double[] errorValues,
                                          ObjectiveFunctionDelegate objectiveFunction)
        {
            Vector <double> lowestVertex = vertices[errorProfile.LowestIndex];

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != errorProfile.LowestIndex)
                {
                    vertices[i]    = (vertices[i].Add(lowestVertex)).Multiply(0.5);
                    errorValues[i] = objectiveFunction(vertices[i].ToArray());
                }
            }
        }
Exemple #9
0
        /// <summary>
        /// Contract the simplex uniformly around the lowest point
        /// </summary>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <param name="objectiveFunction"></param>
        private static void ShrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues,
                                          Func <Vector, double> objectiveFunction)
        {
            Vector lowestVertex = vertices[errorProfile.LowestIndex];

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != errorProfile.LowestIndex)
                {
                    vertices[i]    = vertices[i].Add(lowestVertex).Multiply(0.5);
                    errorValues[i] = objectiveFunction(vertices[i]);
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Compute the centroid of all points except the worst
        /// </summary>
        /// <param name="vertices"></param>
        /// <param name="errorProfile"></param>
        /// <returns></returns>
        private static Vector ComputeCentroid(Vector[] vertices, ErrorProfile errorProfile)
        {
            int numVertices = vertices.Length;
            // find the centroid of all points except the worst one
            var centroid = new Vector(numVertices - 1);

            for (int i = 0; i < numVertices; i++)
            {
                if (i != errorProfile.HighestIndex)
                {
                    centroid = centroid.Add(vertices[i]);
                }
            }
            return(centroid.Multiply(1.0d / (numVertices - 1)));
        }
        /// <summary>
        /// Compute the centroid of all points except the worst
        /// </summary>
        /// <param name="vertices"></param>
        /// <param name="errorProfile"></param>
        /// <returns></returns>
        static Vector <double> ComputeCentroid(Vector <double>[] vertices, ErrorProfile errorProfile)
        {
            int numVertices = vertices.Length;
            // find the centroid of all points except the worst one
            Vector <double> centroid = new LinearAlgebra.Double.DenseVector(numVertices - 1);

            for (int i = 0; i < numVertices; i++)
            {
                if (i != errorProfile.HighestIndex)
                {
                    centroid = centroid.Add(vertices[i]);
                }
            }
            return(centroid.Multiply(1.0d / (numVertices - 1)));
        }
        /// <summary>
        /// Contract the simplex uniformly around the lowest point
        /// </summary>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <param name="objectiveFunction"></param>
        static void ShrinkSimplex(ErrorProfile errorProfile, Vector <double>[] vertices, double[] errorValues,
                                  IObjectiveFunction objectiveFunction)
        {
            Vector <double> lowestVertex = vertices[errorProfile.LowestIndex];

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != errorProfile.LowestIndex)
                {
                    vertices[i] = (vertices[i].Add(lowestVertex)).Multiply(0.5);
                    objectiveFunction.EvaluateAt(vertices[i]);
                    errorValues[i] = objectiveFunction.Value;
                }
            }
        }
        /// <summary>
        /// Contract the simplex uniformly around the lowest point
        /// </summary>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        private static void _shrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues, out Dictionary <string, Dictionary <string, double> > fitnessModeValue, out Dictionary <string, Dictionary <string, double> > absMaxErr)
        {
            Vector lowestVertex = vertices[errorProfile.LowestIndex];

            fitnessModeValue = null; // we don't need those output
            absMaxErr        = null;

            for (int i = 0; i < vertices.Length; i++)
            {
                if (i != errorProfile.LowestIndex)
                {
                    vertices[i] = (vertices[i].Add(lowestVertex)).Multiply(0.5);
                    ComponenttoParamValue(vertices[i].Components);
                    errorValues[i] = OptProblem.fitnessFunctions.Compute(out fitnessModeValue, out absMaxErr, false);
                }
            }
        }
Exemple #14
0
        private void RetryProcess()
        {
            bool newVersion = base.GetBoolProperty(Constants.SOProperties.ErrorLog.TryNewVersion);
            int  procInstId = base.GetIntProperty(Constants.SOProperties.ErrorLog.ProcessInstanceId, true);

            base.ServiceBroker.Service.ServiceObjects[0].Properties.InitResultTable();
            DataTable results = base.ServiceBroker.ServicePackage.ResultTable;

            WorkflowManagementServer mngServer = new WorkflowManagementServer();

            using (mngServer.CreateConnection())
            {
                mngServer.Open(BaseAPIConnectionString);

                ErrorProfile           all         = mngServer.GetErrorProfiles()[0];
                ErrorLogCriteriaFilter errorfilter = new ErrorLogCriteriaFilter();
                errorfilter.AddRegularFilter(ErrorLogFields.ProcInstID, Comparison.Equals, procInstId);
                ErrorLogs errors = mngServer.GetErrorLogs(all.ID, errorfilter);

                if (errors.Count != 1)
                {
                    throw new ApplicationException(string.Format("Could not retrieve process (with id: {0}). Got {1} results.", procInstId, errors.Count));
                }

                int errorId = errors[0].ID;

                if (newVersion)
                {
                    int newVersionNumber = 0;
                    ProcessInstanceCriteriaFilter procFilter = new ProcessInstanceCriteriaFilter();
                    procFilter.AddRegularFilter(ProcessInstanceFields.ProcInstID, Comparison.Equals, procInstId);
                    ProcessInstances procs          = mngServer.GetProcessInstancesAll(procFilter);
                    Processes        procesVersions = mngServer.GetProcessVersions(procs[0].ProcSetID);
                    foreach (Process proc in procesVersions)
                    {
                        if (proc.VersionNumber > newVersionNumber)
                        {
                            newVersionNumber = proc.VersionNumber;
                        }
                    }
                    mngServer.SetProcessInstanceVersion(procInstId, newVersionNumber);
                }
                mngServer.RetryError(procInstId, errorId, string.Format("Process Retry using {0}", base.ServiceBroker.Service.ServiceObjects[0].Name));
            }
        }
Exemple #15
0
        private void GetErrors()
        {
            string profile = base.GetStringProperty(Constants.SOProperties.ErrorLog.Profile);

            if (string.IsNullOrEmpty(profile))
            {
                profile = "All";
            }

            base.ServiceBroker.Service.ServiceObjects[0].Properties.InitResultTable();
            DataTable results = base.ServiceBroker.ServicePackage.ResultTable;

            WorkflowManagementServer mngServer = this.ServiceBroker.K2Connection.GetConnection <WorkflowManagementServer>();

            using (mngServer.Connection)
            {
                ErrorProfile prof = mngServer.GetErrorProfile(profile);
                if (prof == null)
                {
                    throw new Exception(string.Format(Resources.ProfileNotFound, profile));
                }

                ErrorLogs errors = mngServer.GetErrorLogs(prof.ID);

                foreach (ErrorLog e in errors)
                {
                    DataRow r = results.NewRow();
                    r[Constants.SOProperties.ErrorLog.ProcessInstanceId] = e.ProcInstID;
                    r[Constants.SOProperties.ErrorLog.ProcessName]       = e.ProcessName;
                    r[Constants.SOProperties.ErrorLog.Folio]             = e.Folio;
                    r[Constants.SOProperties.ErrorLog.ErrorDescription]  = e.Description;
                    r[Constants.SOProperties.ErrorLog.ErrorItem]         = e.ErrorItemName;
                    r[Constants.SOProperties.ErrorLog.ErrorDate]         = e.ErrorDate;
                    r[Constants.SOProperties.ErrorLog.ErrorId]           = e.ID;
                    r[Constants.SOProperties.ErrorLog.TypeDescription]   = e.TypeDescription;
                    r[Constants.SOProperties.ErrorLog.ExecutingProcId]   = e.ExecutingProcID;
                    r[Constants.SOProperties.ErrorLog.StackTrace]        = e.StackTrace;
                    results.Rows.Add(r);
                }
            }
        }
Exemple #16
0
        private void GetErrors()
        {
            string profile = base.GetStringProperty(Constants.SOProperties.ErrorLog.Profile);

            if (string.IsNullOrEmpty(profile))
            {
                profile = "All";
            }

            base.ServiceBroker.Service.ServiceObjects[0].Properties.InitResultTable();
            DataTable results = base.ServiceBroker.ServicePackage.ResultTable;

            WorkflowManagementServer mngServer = new WorkflowManagementServer();

            using (mngServer.CreateConnection())
            {
                mngServer.Open(BaseAPIConnectionString);

                //TODO: catch exception on this?
                ErrorProfile prof   = mngServer.GetErrorProfile(profile);
                ErrorLogs    errors = mngServer.GetErrorLogs(prof.ID);

                foreach (ErrorLog e in errors)
                {
                    DataRow r = results.NewRow();
                    r[Constants.SOProperties.ErrorLog.ProcessInstanceId] = e.ProcInstID;
                    r[Constants.SOProperties.ErrorLog.ProcessName]       = e.ProcessName;
                    r[Constants.SOProperties.ErrorLog.Folio]             = e.Folio;
                    r[Constants.SOProperties.ErrorLog.ErrorDescription]  = e.Description;
                    r[Constants.SOProperties.ErrorLog.ErrorItem]         = e.ErrorItemName;
                    r[Constants.SOProperties.ErrorLog.ErrorDate]         = e.ErrorDate;
                    r[Constants.SOProperties.ErrorLog.ErrorId]           = e.ID;
                    r[Constants.SOProperties.ErrorLog.TypeDescription]   = e.TypeDescription;
                    r[Constants.SOProperties.ErrorLog.ExecutingProcId]   = e.ExecutingProcID;
                    r[Constants.SOProperties.ErrorLog.StackTrace]        = e.StackTrace;
                    results.Rows.Add(r);
                }
            }
        }
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        /// <param name="scaleFactor"></param>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static double _tryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector[] vertices, double[] errorValues, out Dictionary <string, Dictionary <string, double> > fitnessModeValue, out Dictionary <string, Dictionary <string, double> > absMaxErr)
        {
            // find the centroid through which we will reflect
            Vector centroid = _computeCentroid(vertices, errorProfile);

            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            // evaluate the new point
            ComponenttoParamValue(newPoint.Components);
            double newErrorValue = OptProblem.fitnessFunctions.Compute(out fitnessModeValue, out absMaxErr, false);

            // if it's better, replace the old high point
            if (newErrorValue > errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex]    = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return(newErrorValue);
        }
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        /// <param name="scaleFactor"></param>
        /// <param name="errorProfile"></param>
        /// <param name="vertices"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static double _tryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector[] vertices, 
            double[] errorValues, ObjectiveFunctionDelegate objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector centroid = _computeCentroid(vertices, errorProfile);
            #if DEBUG
            Console.WriteLine("centroid:" + centroid.ToString());
            #endif
            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            // evaluate the new point
            double newErrorValue = objectiveFunction(newPoint.Components);

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex] = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return newErrorValue;
        }
 /// <summary>
 /// Contract the simplex uniformly around the lowest point
 /// </summary>
 /// <param name="errorProfile"></param>
 /// <param name="vertices"></param>
 /// <param name="errorValues"></param>
 private static void _shrinkSimplex(ErrorProfile errorProfile, Vector[] vertices, double[] errorValues, 
     ObjectiveFunctionDelegate objectiveFunction)
 {
     Vector lowestVertex = vertices[errorProfile.LowestIndex];
     for (int i = 0; i < vertices.Length; i++)
     {
         if (i != errorProfile.LowestIndex)
         {
             vertices[i] = (vertices[i].Add(lowestVertex)).Multiply(0.5);
             errorValues[i] = objectiveFunction(vertices[i].Components);
         }
     }
 }
        /// <summary>
        /// Check whether the points in the error profile have so little range that we
        /// consider ourselves to have converged
        /// </summary>
        /// <param name="errorProfile"></param>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static bool _hasConverged(double convergenceTolerance, ErrorProfile errorProfile, double[] errorValues)
        {
            double range = 2 * Math.Abs(errorValues[errorProfile.HighestIndex] - errorValues[errorProfile.LowestIndex]) /
                (Math.Abs(errorValues[errorProfile.HighestIndex]) + Math.Abs(errorValues[errorProfile.LowestIndex]) + JITTER);

            if (range < convergenceTolerance)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Examine all error values to determine the ErrorProfile
        /// </summary>
        /// <param name="errorValues"></param>
        /// <returns></returns>
        private static ErrorProfile _evaluateSimplex(double[] errorValues)
        {
            ErrorProfile errorProfile = new ErrorProfile();
            if (errorValues[0] > errorValues[1])
            {
                errorProfile.HighestIndex = 0;
                errorProfile.NextHighestIndex = 1;
            }
            else
            {
                errorProfile.HighestIndex = 1;
                errorProfile.NextHighestIndex = 0;
            }

            for (int index = 0; index < errorValues.Length; index++)
            {
                double errorValue = errorValues[index];
                if (errorValue <= errorValues[errorProfile.LowestIndex])
                {
                    errorProfile.LowestIndex = index;
                }
                if (errorValue > errorValues[errorProfile.HighestIndex])
                {
                    errorProfile.NextHighestIndex = errorProfile.HighestIndex; // downgrade the current highest to next highest
                    errorProfile.HighestIndex = index;
                }
                else if (errorValue > errorValues[errorProfile.NextHighestIndex] && index != errorProfile.HighestIndex)
                {
                    errorProfile.NextHighestIndex = index;
                }
            }

            return errorProfile;
        }
 /// <summary>
 /// Compute the centroid of all points except the worst
 /// </summary>
 /// <param name="vertices"></param>
 /// <param name="errorProfile"></param>
 /// <returns></returns>
 private static Vector _computeCentroid(Vector[] vertices, ErrorProfile errorProfile)
 {
     int numVertices = vertices.Length;
     // find the centroid of all points except the worst one
     Vector centroid = new Vector(numVertices - 1);
     for (int i = 0; i < numVertices; i++)
     {
         if (i != errorProfile.HighestIndex)
         {
             centroid = centroid.Add(vertices[i]);
         }
     }
     return centroid.Multiply(1.0d / (numVertices - 1));
 }
        /// <summary>
        /// Test a scaling operation of the high point, and replace it if it is an improvement
        /// </summary>
        private static double TryToScaleSimplex(double scaleFactor, ref ErrorProfile errorProfile, Vector<double>[] vertices, 
                                          double[] errorValues, ObjectiveFunctionDelegate objectiveFunction)
        {
            // find the centroid through which we will reflect
            Vector centroid = ComputeCentroid(vertices, errorProfile);

            // define the vector from the centroid to the high point
            Vector centroidToHighPoint = (Vector) vertices[errorProfile.HighestIndex].Subtract(centroid);

            // scale and position the vector to determine the new trial point
            Vector newPoint = (Vector) centroidToHighPoint.Multiply(scaleFactor).Add(centroid);

            // evaluate the new point
            double newErrorValue = objectiveFunction(newPoint.ToArray());

            // if it's better, replace the old high point
            if (newErrorValue < errorValues[errorProfile.HighestIndex])
            {
                vertices[errorProfile.HighestIndex] = newPoint;
                errorValues[errorProfile.HighestIndex] = newErrorValue;
            }

            return newErrorValue;
        }