示例#1
0
        public override float FitnessScore(Species species, SimulationCache simulationCache)
        {
            var microbeSpecies = (MicrobeSpecies)species;

            // No cannibalism
            if (microbeSpecies == prey)
            {
                return(0.0f);
            }

            var behaviourScore = microbeSpecies.Behaviour.Aggression / Constants.MAX_SPECIES_AGGRESSION;

            var microbeSpeciesHexSize = microbeSpecies.BaseHexSize;
            var predatorSpeed         = microbeSpecies.BaseSpeed;

            predatorSpeed += simulationCache.GetEnergyBalanceForSpecies(microbeSpecies, patch).FinalBalance;

            // It's great if you can engulf this prey, but only if you can catch it
            var engulfScore = 0.0f;

            if (microbeSpeciesHexSize / preyHexSize >
                Constants.ENGULF_SIZE_RATIO_REQ && !microbeSpecies.MembraneType.CellWall)
            {
                engulfScore = Constants.AUTO_EVO_ENGULF_PREDATION_SCORE;
            }

            engulfScore *= predatorSpeed > preySpeed ? 1.0f : Constants.AUTO_EVO_ENGULF_LUCKY_CATCH_PROBABILITY;

            var pilusScore   = 0.0f;
            var oxytoxyScore = 0.0f;

            foreach (var organelle in microbeSpecies.Organelles)
            {
                if (organelle.Definition.HasComponentFactory <PilusComponentFactory>())
                {
                    pilusScore += Constants.AUTO_EVO_PILUS_PREDATION_SCORE;
                    continue;
                }

                foreach (var process in organelle.Definition.RunnableProcesses)
                {
                    if (process.Process.Outputs.ContainsKey(oxytoxy))
                    {
                        oxytoxyScore += process.Process.Outputs[oxytoxy] * Constants.AUTO_EVO_TOXIN_PREDATION_SCORE;
                    }
                }
            }

            // Pili are much more useful if the microbe can close to melee
            pilusScore *= predatorSpeed > preySpeed ? 1.0f : Constants.AUTO_EVO_ENGULF_LUCKY_CATCH_PROBABILITY;

            // predators are less likely to use toxin against larger prey, unless they are opportunistic
            if (preyHexSize > microbeSpeciesHexSize)
            {
                oxytoxyScore *= microbeSpecies.Behaviour.Opportunism / Constants.MAX_SPECIES_OPPORTUNISM;
            }

            // Intentionally don't penalize for osmoregulation cost to encourage larger monsters
            return(behaviourScore * (pilusScore + engulfScore + microbeSpeciesHexSize + oxytoxyScore));
        }
示例#2
0
        public void WeightedStrategyTest()
        {
            var data              = CreateMarketData();
            var investorProvider  = CreateInvestorProvider();
            var marketDataCache   = CreateMarketDataCache(data);
            var simulationCache   = new SimulationCache();
            var simulationFactory = new SimulatorFactory(marketDataCache, simulationCache);
            var ratingService     = new RatingService(marketDataCache, simulationFactory, investorProvider);
            var strategyFactory   = CreateStrategyFactory(marketDataCache, simulationCache, investorProvider, ratingService);
            var deltaStrategy     = strategyFactory.Create(new DeltaParameters());
            var volumeStrategy    = strategyFactory.Create(new VolumeParameters());
            var _ = simulationFactory.Create <BacktestingSimulator>()
                    .Evaluate(deltaStrategy, investorProvider.Current).ToArray();
            var __ = simulationFactory.Create <BacktestingSimulator>()
                     .Evaluate(volumeStrategy, investorProvider.Current).ToArray();

            var parameters = new WeightedParameters
            {
                Weights = new Dictionary <IStrategy, double>
                {
                    { deltaStrategy, 0d },
                    { volumeStrategy, 0d }
                }
            };
            var strategy = strategyFactory.Create(parameters);
            var target   = simulationFactory.Create <BacktestingSimulator>()
                           .Evaluate(strategy, investorProvider.Current);

            var actual = ToApprovedString(target);

            Approvals.Verify(actual);
        }
示例#3
0
        public override float FitnessScore(Species species, SimulationCache simulationCache)
        {
            var microbeSpecies = (MicrobeSpecies)species;

            var energyBalance = simulationCache.GetEnergyBalanceForSpecies(microbeSpecies, patch);

            // Don't penalize species that can't move at full speed all the time as much here
            var chunkEaterSpeed = Math.Max(microbeSpecies.BaseSpeed + energyBalance.FinalBalance,
                                           microbeSpecies.BaseSpeed / 3);

            // We ponder the score for each compound by its amount, leading to pondering in proportion of total
            // quantity, with a constant factor that will be eliminated when making ratios of scores for this niche.
            var score = energyCompounds.Sum(c => EnergyGenerationScore(microbeSpecies, c.Key) * c.Value);

            score *= chunkEaterSpeed * species.Behaviour.Activity;

            // If the species can't engulf, then they are dependent on only eating the runoff compounds
            if (microbeSpecies.MembraneType.CellWall ||
                microbeSpecies.BaseHexSize < chunkSize * Constants.ENGULF_SIZE_RATIO_REQ)
            {
                score *= Constants.AUTO_EVO_CHUNK_LEAK_MULTIPLIER;
            }

            // Chunk (originally from marine snow) food source penalizes big creatures that try to rely on it
            score /= energyBalance.TotalConsumptionStationary;

            return(score);
        }
示例#4
0
        protected static IEnumerable <SimulationState> SimulateStrategy(
            IEnumerable <MarketData> data,
            Func <StrategyFactory, IStrategy> createStrategyFunc,
            bool initialiseRatingService = false)
        {
            var investorProvider = CreateInvestorProvider();

            var marketDataCache = CreateMarketDataCache(data);
            var simulationCache = new SimulationCache();

            var simulatorFactor = new SimulatorFactory(marketDataCache, simulationCache);
            var simulator       = simulatorFactor.Create <BacktestingSimulator>();
            var ratingService   = new RatingService(
                marketDataCache,
                simulatorFactor,
                investorProvider);
            var strategyFactory = CreateStrategyFactory(
                marketDataCache,
                simulationCache,
                investorProvider,
                ratingService);
            var strategy = createStrategyFunc(strategyFactory);

            if (initialiseRatingService)
            {
                ratingService.RateMarketData();
            }

            return(simulator.Evaluate(strategy, investorProvider.Current));
        }
示例#5
0
        protected static Dictionary <string, SimulationState> SimulateStrategy(
            IEnumerable <MarketData> data,
            IParameters[] parameters)
        {
            var investorProvider = CreateInvestorProvider();

            var marketDataCache = CreateMarketDataCache(data);
            var simulationCache = new SimulationCache();

            var simulatorFactor = new SimulatorFactory(marketDataCache, simulationCache);
            var simulator       = simulatorFactor.Create <BacktestingSimulator>();
            var ratingService   = new RatingService(marketDataCache, simulatorFactor, investorProvider);
            var strategyFactory = CreateStrategyFactory(marketDataCache, simulationCache, investorProvider, ratingService);

            var results = new Dictionary <string, SimulationState>();

            foreach (var p in parameters)
            {
                var strategy = strategyFactory.Create(p);
                var state    = simulator.Evaluate(strategy, investorProvider.Current);
                results[strategy.StrategyType.GetDescription()] = state.Last();
            }

            return(results);
        }
示例#6
0
        public override float FitnessScore(Species species, SimulationCache simulationCache)
        {
            var microbeSpecies = (MicrobeSpecies)species;

            var energyCreationScore = EnergyGenerationScore(microbeSpecies, compound);

            var energyCost = simulationCache
                             .GetEnergyBalanceForSpecies(microbeSpecies, patch)
                             .TotalConsumptionStationary;

            return(energyCreationScore / energyCost);
        }
示例#7
0
        public void Setup()
        {
            ConfigurationManager.AppSettings["BacktestingDate"] = "2010-07-01";
            ConfigurationManager.AppSettings["CacheSize"]       = "2000";
            ConfigurationManager.AppSettings["DataPath"]        = "MarketData.csv";
            ConfigurationManager.AppSettings["RelativePath"]    = @"../../../";

            var marketData      = CreateMarketData();
            var marketDataCache = CreateMarketDataCache(marketData);

            var investor = new Investor {
                DailyFunds = 10, OrderDelayDays = 3
            };
            var investorProvider = CreateInvestorProvider();

            var simulationCache = new SimulationCache();

            var simulationFactory = new SimulatorFactory(marketDataCache, simulationCache);
            var ratingService     = new RatingService(
                marketDataCache,
                simulationFactory,
                investorProvider);


            var strategyFactory = CreateStrategyFactory(
                marketDataCache,
                simulationCache,
                investorProvider,
                ratingService);

            var marketDataRepository        = new Mock <IRepository <MarketData> >();
            var simulationResultsRepository = new Mock <IRepository <SimulationResult> >();

            _target = new ResultsProvider(
                marketDataCache,
                marketDataRepository.Object,
                ratingService,
                simulationResultsRepository.Object);

            _target.Initialise();

            var strategy        = strategyFactory.Create(new HolidayEffectParameters());
            var stateJson       = File.ReadAllText(@"HolidayEffectSimulationState.json");
            var simulationState = JsonConvert.DeserializeObject <SimulationState[]>(stateJson);
            var resultsToAdd    = new ConcurrentDictionary <IStrategy, SimulationState[]>();

            resultsToAdd.TryAdd(strategy, simulationState);

            _target.AddResults(investor, resultsToAdd);
        }
示例#8
0
        public static void Simulate(SimulationConfiguration parameters)
        {
            var random = new Random();
            var cache  = new SimulationCache();

            var speciesToSimulate = CopyInitialPopulationsToResults(parameters);

            IEnumerable <KeyValuePair <int, Patch> > patchesToSimulate = parameters.OriginalMap.Patches;

            // Skip patches not configured to be simulated in order to run faster
            if (parameters.PatchesToRun.Count > 0)
            {
                patchesToSimulate = patchesToSimulate.Where(p => parameters.PatchesToRun.Contains(p.Value));
            }

            var patchesList = patchesToSimulate.ToList();

            while (parameters.StepsLeft > 0)
            {
                RunSimulationStep(parameters, speciesToSimulate, patchesList, random, cache,
                                  parameters.AutoEvoConfiguration);
                --parameters.StepsLeft;
            }
        }
示例#9
0
 /// <summary>
 ///   Provides a fitness metric to determine population adjustments for species in a patch.
 /// </summary>
 /// <param name="microbe">The species to be evaluated.</param>
 /// <param name="simulationCache">
 ///   Cache that should be used to reduce amount of times expensive computations are run
 /// </param>
 /// <returns>
 ///   A float to represent score. Scores are only compared against other scores from the same FoodSource,
 ///   so different implementations do not need to worry about scale.
 /// </returns>
 public abstract float FitnessScore(Species microbe, SimulationCache simulationCache);
示例#10
0
        /// <summary>
        ///   The heart of the simulation that handles the processed parameters and calculates future populations.
        /// </summary>
        private static void SimulatePatchStep(SimulationConfiguration simulationConfiguration, Patch patch,
                                              IEnumerable <Species> genericSpecies, Random random, SimulationCache cache,
                                              AutoEvoConfiguration autoEvoConfiguration)
        {
            _ = random;

            var  populations = simulationConfiguration.Results;
            bool trackEnergy = simulationConfiguration.CollectEnergyInformation;

            // This algorithm version is for microbe species
            var species = genericSpecies.Select(s => (MicrobeSpecies)s).ToList();

            // Skip if there aren't any species in this patch
            if (species.Count < 1)
            {
                return;
            }

            var energyBySpecies = new Dictionary <MicrobeSpecies, float>();

            foreach (var currentSpecies in species)
            {
                energyBySpecies[currentSpecies] = 0.0f;
            }

            bool strictCompetition = autoEvoConfiguration.StrictNicheCompetition;

            var niches = new List <FoodSource>
            {
                new EnvironmentalFoodSource(patch, Sunlight, Constants.AUTO_EVO_SUNLIGHT_ENERGY_AMOUNT),
                new CompoundFoodSource(patch, Glucose),
                new CompoundFoodSource(patch, HydrogenSulfide),
                new CompoundFoodSource(patch, Iron),
                new ChunkFoodSource(patch, "marineSnow"),
                new ChunkFoodSource(patch, "ironSmallChunk"),
                new ChunkFoodSource(patch, "ironBigChunk"),
            };

            foreach (var currentSpecies in species)
            {
                niches.Add(new HeterotrophicFoodSource(patch, currentSpecies));
            }

            foreach (var niche in niches)
            {
                // If there isn't a source of energy here, no need for more calculations
                if (niche.TotalEnergyAvailable() <= MathUtils.EPSILON)
                {
                    continue;
                }

                var fitnessBySpecies  = new Dictionary <MicrobeSpecies, float>();
                var totalNicheFitness = 0.0f;
                foreach (var currentSpecies in species)
                {
                    float thisSpeciesFitness;

                    if (strictCompetition)
                    {
                        // Softly enforces https://en.wikipedia.org/wiki/Competitive_exclusion_principle
                        // by exaggerating fitness differences
                        thisSpeciesFitness =
                            Mathf.Max(Mathf.Pow(niche.FitnessScore(currentSpecies, cache), 2.5f), 0.0f);
                    }
                    else
                    {
                        thisSpeciesFitness = Mathf.Max(niche.FitnessScore(currentSpecies, cache), 0.0f);
                    }

                    fitnessBySpecies[currentSpecies] = thisSpeciesFitness;
                    totalNicheFitness += thisSpeciesFitness;
                }

                // If no species can get energy this way, no need for more calculations
                if (totalNicheFitness <= MathUtils.EPSILON)
                {
                    continue;
                }

                foreach (var currentSpecies in species)
                {
                    var energy = fitnessBySpecies[currentSpecies] * niche.TotalEnergyAvailable() / totalNicheFitness;

                    // If this species can't gain energy here, don't count it (this also prevents it from appearing
                    // in food sources (if that's not what we want), if the species doesn't use this food source
                    if (energy <= MathUtils.EPSILON)
                    {
                        continue;
                    }

                    energyBySpecies[currentSpecies] += energy;

                    if (trackEnergy)
                    {
                        populations.AddTrackedEnergyForSpecies(currentSpecies, patch, niche,
                                                               fitnessBySpecies[currentSpecies], energy, totalNicheFitness);
                    }
                }
            }

            foreach (var currentSpecies in species)
            {
                var energyBalanceInfo = cache.GetEnergyBalanceForSpecies(currentSpecies, patch);

                // Modify populations based on energy
                var newPopulation = (long)(energyBySpecies[currentSpecies]
                                           / energyBalanceInfo.FinalBalanceStationary);

                if (trackEnergy)
                {
                    populations.AddTrackedEnergyConsumptionForSpecies(currentSpecies, patch, newPopulation,
                                                                      energyBySpecies[currentSpecies], energyBalanceInfo.FinalBalanceStationary);
                }

                // TODO: this is a hack for now to make the player experience better, try to get the same rules working
                // for the player and AI species in the future.
                if (currentSpecies.PlayerSpecies)
                {
                    // Severely penalize a species that can't osmoregulate
                    if (energyBalanceInfo.FinalBalanceStationary < 0)
                    {
                        newPopulation /= 10;
                    }
                }
                else
                {
                    // Severely penalize a species that can't move indefinitely
                    if (energyBalanceInfo.FinalBalance < 0)
                    {
                        newPopulation /= 10;
                    }
                }

                // Can't survive without enough population
                if (newPopulation < Constants.AUTO_EVO_MINIMUM_VIABLE_POPULATION)
                {
                    newPopulation = 0;
                }

                populations.AddPopulationResultForSpecies(currentSpecies, patch, newPopulation);
            }
        }
示例#11
0
 private static void RunSimulationStep(SimulationConfiguration parameters, List <Species> species,
                                       IEnumerable <KeyValuePair <int, Patch> > patchesToSimulate, Random random, SimulationCache cache,
                                       AutoEvoConfiguration autoEvoConfiguration)
 {
     foreach (var entry in patchesToSimulate)
     {
         // Simulate the species in each patch taking into account the already computed populations
         SimulatePatchStep(parameters, entry.Value,
                           species.Where(item => parameters.Results.GetPopulationInPatch(item, entry.Value) > 0),
                           random, cache, autoEvoConfiguration);
     }
 }