/// <summary> /// Parameters for GEM. /// </summary> /// <param name="NGrenade"> /// Number of grenades on each iteration. <paramref name="NGrenade"/> >= 1. /// </param> /// <param name="NShrapnel"> /// Number of shrapnel for each grenade. <paramref name="NShrapnel"/> >= 1. /// </param> /// <param name="Imax"> /// The number of iteration. <paramref name="Imax"/> >= 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"/> > 0. /// </param> /// <param name="RadiusReduct"> /// The coefficient of radius reduction. <paramref name="RadiusReduct"/> > 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"/> > <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"/> < <paramref name="Mmax"/>. </para> /// </param> /// <param name="DesiredMinimum"> /// The number of desired minimums. <paramref name="DesiredMinimum"/> >= 1. /// </param> /// <param name="Psin"> /// The exponent for determine weight optimal search direction m_osd. <paramref name="Psin"/> /// > 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); } } }