public IteratedLocalSearch(double[] masks, SingleTrajectoryContinuousSolver local_search, TerminationEvaluationMethod local_search_termination_condition, CreateRandomNeighborhoodMethod generator = null)
        {
            mLocalSearch = local_search;
            mLocalSearchTerminationCondition = local_search_termination_condition;


            mMasks = (double[])masks.Clone();
            mNeighborSolutionProvider = generator;
            if (mNeighborSolutionProvider == null)
            {
                mNeighborSolutionProvider = (x, index, constraints) =>
                {
                    double[] lower_bounds = null;
                    double[] upper_bounds = null;

                    if (mLowerBounds == null || mUpperBounds == null)
                    {
                        Tuple <double[], double[]> bounds = null;
                        if (constraints is Tuple <double[], double[]> )
                        {
                            bounds = constraints as Tuple <double[], double[]>;
                        }
                        else
                        {
                            throw new InvalidCastException();
                        }

                        lower_bounds = bounds.Item1;
                        upper_bounds = bounds.Item2;
                    }
                    else
                    {
                        lower_bounds = mLowerBounds;
                        upper_bounds = mUpperBounds;
                    }

                    if (lower_bounds.Length < x.Length)
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                    if (upper_bounds.Length < x.Length)
                    {
                        throw new ArgumentOutOfRangeException();
                    }

                    double[] x_p = (double[])x.Clone();

                    for (int i = 0; i < mMasks.Length; ++i)
                    {
                        int    mindex  = (index + i) % x_p.Length;
                        double new_val = mMasks[i] > 0 ? x[(index + i)] + RandomEngine.Gauss(0, mMasks[i]) : x[(index + i) % x.Length];
                        new_val = System.Math.Max(lower_bounds[mindex], new_val);
                        new_val = System.Math.Min(upper_bounds[mindex], new_val);

                        x_p[mindex] = new_val;
                    }
                    return(x_p);
                };
            }
        }
        public StochasticHillClimber(double[] masks, CreateRandomNeighborhoodMethod generator = null)
        {
            mMasks             = (double[])masks.Clone();
            mSolutionGenerator = generator;
            if (mSolutionGenerator == null)
            {
                mSolutionGenerator = (x, index, constraints) =>
                {
                    double[] lower_bounds = null;
                    double[] upper_bounds = null;
                    if (mLowerBounds == null || mUpperBounds == null)
                    {
                        Tuple <double[], double[]> bounds = null;
                        if (constraints is Tuple <double[], double[]> )
                        {
                            bounds = constraints as Tuple <double[], double[]>;
                        }
                        else
                        {
                            throw new InvalidCastException();
                        }

                        lower_bounds = bounds.Item1;
                        upper_bounds = bounds.Item2;
                    }
                    else
                    {
                        lower_bounds = mLowerBounds;
                        upper_bounds = mUpperBounds;
                    }

                    if (lower_bounds.Length < x.Length)
                    {
                        throw new ArgumentOutOfRangeException();
                    }
                    if (upper_bounds.Length < x.Length)
                    {
                        throw new ArgumentOutOfRangeException();
                    }

                    double[] x_p = (double[])x.Clone();

                    for (int i = 0; i < mMasks.Length; ++i)
                    {
                        int    mindex  = (index + i) % x_p.Length;
                        double new_val = mMasks[i] > 0 ? x[(index + i)] + RandomEngine.Gauss(0, mMasks[i]) : x[(index + i) % x.Length];
                        new_val = System.Math.Max(lower_bounds[mindex], new_val);
                        new_val = System.Math.Min(upper_bounds[mindex], new_val);

                        x_p[mindex] = new_val;
                    }
                    return(x_p);
                };
            }
        }