コード例 #1
0
        ///<summary>
        /// Create and run a Fleet MSO that attempts to find the optimum fleet composition to raid this defense
        ///</summary>
        public double EvaluateDefense()
        {
            BalanceDefense();
            Console.WriteLine("\tSolving for optimum fleet to raid defense composition ["
                              + String.Join(",", defense.DefenseCounts)
                              + "]");

            Random rand = new Random();

            FleetSwarm[] fleetSwarms = new FleetSwarm[Program.NumSwarms];
            for (int i = 0; i < Program.NumSwarms; ++i)
            {
                fleetSwarms[i] = new FleetSwarm(defense);
            }
            Fleet  gBestFleet   = new Fleet();
            double gBestProfits = double.MinValue;

            for (int i = 0; i < Program.NumSwarms; ++i)
            {
                if (fleetSwarms[i].lBestProfits > gBestProfits)
                {
                    gBestProfits = fleetSwarms[i].lBestProfits;
                    gBestFleet.CopyFleet(fleetSwarms[i].lBestFleet);
                    PrintCurrentNewBestFleetComposition(gBestFleet.ShipCounts, gBestProfits, -1);
                }
            }


            var gBestList = new List <(int, double)>
            {
                (-1, gBestProfits)
            };


            int epoch = 0;
            int epochsSinceImprovement = 0;

            while (epoch < (Program.MaxEpochsInner) && epochsSinceImprovement < 500)
            {
                ++epoch;
                ++epochsSinceImprovement;

                //if (epoch < Program.MaxEpochs && epoch % 5 == 0)
                //{
                //    Console.WriteLine("Defense[" + String.Join(",", defense) + "], "
                //                        + " Epoch " + epoch
                //                        + ", Global Best Minimal Attack Cost = " + bestGlobalMinAttackCost.ToString("F4"));
                //}

                for (int i = 0; i < Program.NumSwarms; ++i) // each swarm
                {
                    // Shuffle(sequence, rand); // move particles in random sequence
                    for (int j = 0; j < Program.NumParticles; ++j) // each particle
                    {
                        //Check if Particle dies
                        double p1 = rand.NextDouble();
                        if (fleetSwarms[i].fleetParticles[j].consecutiveNonImproves * p1 > 20)
                        {
                            fleetSwarms[i].fleetParticles[j] = new FleetParticle(defense);              // new random position

                            if (fleetSwarms[i].fleetParticles[j].profits > fleetSwarms[i].lBestProfits) // new swarm best by luck?
                            {
                                fleetSwarms[i].lBestProfits = fleetSwarms[i].fleetParticles[j].pBestProfits;
                                fleetSwarms[i].lBestFleet.CopyFleet(fleetSwarms[i].fleetParticles[j].fleet);

                                if (fleetSwarms[i].fleetParticles[j].profits > gBestProfits) // if a new swarm best, maybe also a new global best?
                                {
                                    //need to repeat Defense evaluation to avoid outliers skewing results
                                    double moreAccurateProfits = fleetSwarms[i].fleetParticles[j].EvaluateFleet(20);
                                    if (moreAccurateProfits > gBestProfits)
                                    {
                                        epochsSinceImprovement = 0;

                                        gBestProfits = moreAccurateProfits;
                                        gBestFleet.CopyFleet(fleetSwarms[i].fleetParticles[j].fleet);
                                        PrintCurrentNewBestFleetComposition(gBestFleet.ShipCounts, gBestProfits, epoch);
                                        gBestList.Add((epoch, gBestProfits));
                                    }
                                }
                            }
                        }
                        // an alternative is to maintain a particle age and die with high prob after a certain age reached
                        // another option is to maintain particle health/weakness (related to either ratio of times improved / loop count
                        // or number consecutive improves or consecutive non-improves) and die with high prob when health is low

                        double p2 = rand.NextDouble();
                        if (p2 < Program.ProbImmigrate)
                        {
                            int           otherSwarm    = rand.Next(0, Program.NumSwarms);
                            int           otherParticle = rand.Next(0, Program.NumParticles);
                            FleetParticle tmp           = fleetSwarms[i].fleetParticles[j];
                            fleetSwarms[i].fleetParticles[j] = fleetSwarms[otherSwarm].fleetParticles[otherParticle];
                            fleetSwarms[otherSwarm].fleetParticles[otherParticle] = tmp;

                            if (fleetSwarms[i].fleetParticles[j].pBestProfits > fleetSwarms[otherSwarm].lBestProfits) // new (other) swarm best?
                            {
                                fleetSwarms[otherSwarm].lBestProfits = fleetSwarms[i].fleetParticles[j].pBestProfits;
                                fleetSwarms[otherSwarm].lBestFleet.CopyFleet(fleetSwarms[i].fleetParticles[j].bestLocalFleet);
                            }
                            if (fleetSwarms[otherSwarm].fleetParticles[otherParticle].pBestProfits > fleetSwarms[i].lBestProfits) // new (curr) swarm best?
                            {
                                fleetSwarms[i].lBestProfits = fleetSwarms[otherSwarm].fleetParticles[otherParticle].pBestProfits;
                                fleetSwarms[i].lBestFleet.CopyFleet(fleetSwarms[otherSwarm].fleetParticles[otherParticle].fleet);
                            }
                            // not possible for a new global best
                        }

                        for (int k = 0; k < Program.FleetDims; ++k) // update velocity. each x position component
                        {
                            double r1 = rand.NextDouble();
                            double r2 = rand.NextDouble();
                            double r3 = rand.NextDouble();

                            fleetSwarms[i].fleetParticles[j].velocity[k] = (
                                (Program.Inertia * fleetSwarms[i].fleetParticles[j].velocity[k])
                                + (Program.GravityLocal * r1 * (fleetSwarms[i].fleetParticles[j].bestLocalFleet.ShipCounts[k]
                                                                - fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k])
                                   )
                                + (Program.GravitySwarm * r2 * (fleetSwarms[i].lBestFleet.ShipCounts[k]
                                                                - fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k])
                                   )
                                + (Program.GravityGlobal * r3 * (gBestFleet.ShipCounts[k]
                                                                 - fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k])
                                   )
                                );

                            //if (fleetSwarms[i].fleetParticles[j].velocity[k] < minX) // constrain velocities
                            //    fleetSwarms[i].fleetParticles[j].velocity[k] = minX;
                            //else if (fleetSwarms[i].fleetParticles[j].velocity[k] > maxX)
                            //    fleetSwarms[i].fleetParticles[j].velocity[k] = maxX;
                        }

                        for (int k = 0; k < Program.FleetDims; ++k) // update position
                        {
                            fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k] += (int)fleetSwarms[i].fleetParticles[j].velocity[k];
                            // constrain all xi
                            if (fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k] < 0)
                            {
                                fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k] = 0;
                            }
                            else if (fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k]
                                     > (int)((10 * Program.DefenseValue) / (ulong)Program.FleetUnitsTotalCosts[k]))
                            {
                                //fleetSwarms[i].fleetParticles[j].fleetComposition[k] = (maxX - minX) * rand.NextDouble() + minX;
                                fleetSwarms[i].fleetParticles[j].fleet.ShipCounts[k] = (int)(rand.NextDouble()
                                                                                             * (10 * Program.DefenseValue) / Program.FleetUnitsTotalCosts[k]);
                            }
                        }

                        // update error
                        fleetSwarms[i].fleetParticles[j].EvaluateFleet();

                        // check if new best error for this fleet
                        if (fleetSwarms[i].fleetParticles[j].profits > fleetSwarms[i].fleetParticles[j].pBestProfits)
                        {
                            fleetSwarms[i].fleetParticles[j].consecutiveNonImproves = 0;
                            fleetSwarms[i].fleetParticles[j].pBestProfits           = fleetSwarms[i].fleetParticles[j].profits;
                            fleetSwarms[i].fleetParticles[j].bestLocalFleet.CopyFleet(fleetSwarms[i].fleetParticles[j].fleet);

                            if (fleetSwarms[i].fleetParticles[j].profits > fleetSwarms[i].lBestProfits) // new swarm best?
                            {
                                fleetSwarms[i].lBestProfits = fleetSwarms[i].fleetParticles[j].profits;
                                fleetSwarms[i].fleetParticles[j].bestLocalFleet.CopyFleet(fleetSwarms[i].fleetParticles[j].fleet);

                                if (fleetSwarms[i].fleetParticles[j].profits > gBestProfits) // new global best?
                                {
                                    //Simulate again with more trials to avoid outliers messing with results
                                    double moreAccurateProfits = fleetSwarms[i].fleetParticles[j].EvaluateFleet(20);
                                    if (moreAccurateProfits > gBestProfits)
                                    {
                                        epochsSinceImprovement = 0;

                                        fleetSwarms[i].fleetParticles[j].pBestProfits = moreAccurateProfits;
                                        fleetSwarms[i].lBestProfits = moreAccurateProfits;
                                        gBestProfits = moreAccurateProfits;
                                        gBestFleet.CopyFleet(fleetSwarms[i].fleetParticles[j].fleet);
                                        PrintCurrentNewBestFleetComposition(gBestFleet.ShipCounts, gBestProfits, epoch);
                                        gBestList.Add((epoch, gBestProfits));
                                    }
                                }
                            }
                        }
                    } // each particle
                }     // each swarm
            }         // while
            string fleetStr = String.Join(", ", gBestFleet.ShipCounts);

            Console.WriteLine("\tBest fleet found: " + fleetStr);
            Console.WriteLine("\t\tProfits per hour: " + gBestProfits);
            var pm = new PlotModel {
                Title = "Defense: " + String.Join(", ", defense.DefenseCounts),
                PlotAreaBorderThickness = new OxyThickness(0),
                Subtitle = "\nBest Fleet: " + String.Join(", ", gBestFleet.ShipCounts),
            };
            var categoryAxis = new OxyPlot.Axes.CategoryAxis {
                AxislineStyle = LineStyle.Solid, TickStyle = TickStyle.None
            };
            var value = new List <DataPoint>();

            for (int i = 0; i < gBestList.Count; i++)
            {
                value.Add(new DataPoint(gBestList[i].Item1, gBestList[i].Item2));
            }


            pm.Axes.Add(new OxyPlot.Axes.LinearAxis
            {
                Position      = AxisPosition.Left,
                Minimum       = 0,
                Maximum       = 1.05 * Math.Abs(gBestList[gBestList.Count - 1].Item2),
                MajorStep     = 4_000_000,
                MinorStep     = 1_000_000,
                AxislineStyle = LineStyle.Solid,
                TickStyle     = TickStyle.Crossing,
                StringFormat  = "0,0"
            });
コード例 #2
0
 public void CopyFleet(Fleet sourceFleet)
 {
     Array.Copy(sourceFleet.ShipCounts, ShipCounts, Program.FleetDims);
 }