/// <summary>
        /// Parameters for GEM.
        /// </summary>
        /// <param name="NGrenade">
        /// Number of grenades on each iteration. <paramref name="NGrenade"/> &gt;= 1.
        /// </param>
        /// <param name="NShrapnel">
        /// Number of shrapnel for each grenade. <paramref name="NShrapnel"/> &gt;= 1.
        /// </param>
        /// <param name="Imax">
        /// The number of iteration. <paramref name="Imax"/> &gt;= 1.
        /// </param>
        /// <param name="InitRadiusGrenade">
        /// The initial radius of the grenade territory. Maximum value is equal 2 * sqrt(n), where
        /// n-dimension space. <paramref name="InitRadiusGrenade"/> &gt; 0.
        /// </param>
        /// <param name="RadiusReduct">
        /// The coefficient of radius reduction. <paramref name="RadiusReduct"/> &gt; 1.
        /// </param>
        /// <param name="ProbabilityCollision">
        /// Probability of collision. <paramref name="NGrenade"/> in (0;1).
        /// </param>
        /// <param name="Mmax">
        /// <para>
        /// Maximum value of exponent for reduce the radius of explosion. <paramref name="Mmax"/> in (0;1].
        /// </para>
        /// <para> <paramref name="Mmax"/> &gt; <paramref name="Mmin"/>. </para>
        /// </param>
        /// <param name="Mmin">
        /// <para>
        /// Minimum value of exponent for reduce the radius of explosion. <paramref name="Mmin"/> in [0;1).
        /// </para>
        /// <para> <paramref name="Mmin"/> &lt; <paramref name="Mmax"/>. </para>
        /// </param>
        /// <param name="DesiredMinimum">
        /// The number of desired minimums. <paramref name="DesiredMinimum"/> &gt;= 1.
        /// </param>
        /// <param name="Psin">
        /// The exponent for determine weight optimal search direction m_osd. <paramref name="Psin"/>
        /// &gt; 0.
        /// </param>
        /// <exception cref="ArgumentException"> If conditions for parameters do not performed. </exception>
        public GEMParams(int NGrenade, int NShrapnel, int Imax, double InitRadiusGrenade,
                         double RadiusReduct = 100, double ProbabilityCollision = 0.8, double Psin = 5, double Mmin = 0.1, double Mmax = 0.9, int DesiredMinimum = 1)
        {
            if (NGrenade < 1)
            {
                throw new ArgumentException($"{nameof(NGrenade)} (actual value is {NGrenade}) must be > 0.", nameof(NGrenade));
            }
            if (NShrapnel < 1)
            {
                throw new ArgumentException($"{nameof(NShrapnel)} (actual value is {NShrapnel}) must be > 0.", nameof(NShrapnel));
            }
            if (Imax < 1)
            {
                throw new ArgumentException($"{nameof(Imax)}  (actual value is {Imax}) must be > 0.", nameof(Imax));
            }
            if (DesiredMinimum < 1)
            {
                throw new ArgumentException($"{nameof(DesiredMinimum)}  (actual value is {DesiredMinimum}) must be > 0.", nameof(DesiredMinimum));
            }

            if (RadiusReduct < 1)
            {
                throw new ArgumentException($"{nameof(RadiusReduct)} (actual value is {RadiusReduct}) must be > 1.", nameof(RadiusReduct));
            }

            if (CmpDouble.AlmostEqual(0, ProbabilityCollision, -Constants.EPS_EXPONENT / 2) || ProbabilityCollision < 0)
            {
                throw new ArgumentException($"{nameof(ProbabilityCollision)} (actual value is {ProbabilityCollision})  too small or less than 0.", nameof(ProbabilityCollision));
            }

            if (CmpDouble.AlmostEqual(1, ProbabilityCollision, 2) || ProbabilityCollision > 1)
            {
                throw new ArgumentException($"{nameof(ProbabilityCollision)} (actual value is {ProbabilityCollision}) must be < 1.", nameof(ProbabilityCollision));
            }

            if (Mmax < 0 || Mmax > 1 || Mmax < Mmin)
            {
                throw new ArgumentException($"{nameof(Mmax)}  (actual value is {Mmax}) must be in (0;1] and {nameof(Mmax)} > {nameof(Mmin)} (actual value is {Mmin}).", nameof(Mmax));
            }

            if (Mmin < 0 || Mmin > 1)
            {
                throw new ArgumentException($"{nameof(Mmin)}  (actual value is {Mmin}) must be in [0;1)", nameof(Mmin));
            }

            this.IsParamsInit      = true;
            this.DesiredMin        = DesiredMinimum;
            this.NGrenade          = NGrenade;
            this.NShrapnel         = NShrapnel;
            this.Imax              = Imax;
            this.InitRadiusGrenade = InitRadiusGrenade;
            this.RadiusReduct      = RadiusReduct;
            this.Pts  = ProbabilityCollision;
            this.Mmax = Mmax;
            this.Mmin = Mmin;
            this.Psin = Psin;
        }
        /// <summary>
        /// Searching OSD and Xosd position.
        /// </summary>
        /// <param name="WhichGrenade"></param>
        /// <param name="Dimension"></param>
        private void FindOSD(int WhichGrenade, int Dimension)
        {
            LinkedList <Agent> ortogonalArray = new LinkedList <Agent>();

            // Generate 2 * n shrapnels along coordinate axis. 1 in positive direction. 1 in negative direction.
            bool isAddToList = false;

            Agent tempAgent = new Agent(Dimension, 1);

            bool isPosDirection = true;

            for (int i = 0; i < 2 * Dimension; i++)
            {
                // Reuse an allocated memory, if 'tempAgent' was not added to the array, otherwise
                // allocate a new memory.
                if (isAddToList)
                {
                    tempAgent = new Agent(Dimension, 1);
                }

                isAddToList = true;

                tempAgent.Point.SetAt(_grenades[WhichGrenade].Point);

                // The positive direction along the coordinate axis.
                if (isPosDirection)
                {
                    if (CmpDouble.AlmostEqual(_grenades[WhichGrenade].Point[i / 2], 1, Exponent: 1))
                    {
                        tempAgent.Point[i / 2] = 1;
                    }
                    else
                    {
                        tempAgent.Point[i / 2] = _uniformRand.URandVal(_grenades[WhichGrenade].Point[i / 2], 1);
                    }
                }
                // The negative direction along the coordinate axis.
                else
                {
                    if (CmpDouble.AlmostEqual(_grenades[WhichGrenade].Point[i / 2], -1, Exponent: 1))
                    {
                        tempAgent.Point[i / 2] = -1;
                    }
                    else
                    {
                        tempAgent.Point[i / 2] = _uniformRand.URandVal(-1, _grenades[WhichGrenade].Point[i / 2]);
                    }
                }

                // Change direction.
                isPosDirection = !isPosDirection;

                // If shrapnel and grenade too near, then shrapnel deleted.
                for (int j = 0; j < _parameters.NGrenade; j++)
                {
                    if (j != WhichGrenade)
                    {
                        if (PointND.Distance(tempAgent.Point, _grenades[j].Point) <= _radiusGrenade)
                        {
                            isAddToList = false;
                            break;
                        }
                    }
                }

                if (isAddToList)
                {
                    tempAgent.Eval(_targetFuncWithTransformedCoords);
                    ortogonalArray.AddLast(tempAgent);
                }
            }

            // Determine position Xosd.
            _xosd = null;

            if (ortogonalArray.Count != 0)
            {
                _xosd = ortogonalArray.First.Value;

                foreach (Agent item in ortogonalArray)
                {
                    if (item.Objs[0] < _xosd.Objs[0])
                    {
                        _xosd = item;
                    }
                }
            }

            // Determine position Xcur.
            _xcur = _grenades[WhichGrenade];

            // If grenade does not be in a neighborhood of the other grenades, then xcur = null.
            for (int j = 0; j < _parameters.NGrenade; j++)
            {
                if (j != WhichGrenade)
                {
                    if (PointND.Distance(_grenades[j].Point, _grenades[WhichGrenade].Point) <= _radiusGrenade)
                    {
                        _xcur = null;
                        break;
                    }
                }
            }

            // Vector dosd.
            _dosd = _xosd == null ? null : _xosd.Point - _grenades[WhichGrenade].Point;

            // Normalization vector.
            if (_dosd != null)
            {
                double norm = _dosd.Norm();

                if (CmpDouble.AlmostEqual(norm, 0.0, 2))
                {
                    _dosd = null;
                }
                else
                {
                    _dosd.MultiplyByInplace(1 / norm);
                }
            }
        }