private Individual[] TryMutateWithParallelOptions(Array <Individual> population, ParallelOptions options) { var failedAttempts = 0L; var mutants = new Individual[_mutantsPerGeneration]; Parallel.For( fromInclusive: 0, toExclusive: mutants.Length, parallelOptions: options, (long index, ParallelLoopState loopState) => { while (true) { var updatedFailedAttempts = Interlocked.Read(ref failedAttempts); if (updatedFailedAttempts >= _maximumFailedAttemptsPerGeneration) { loopState.Stop(); } var mutationCandidate = Random.Choice(population); var mutated = _individualMutator.TryMutate(original: mutationCandidate); if (mutated is null) { updatedFailedAttempts = Interlocked.Increment(ref failedAttempts); } else { mutants[index] = mutated; break; } } }); return(mutants); }
public Rule?TryCreateRule(ReadOnlySpan <Rule> existingRules) { var seedsIndices = _seedSelector.FindSeedsIndices(existingRules); if (seedsIndices.IsEmpty) { return(null); } var seedIndex = Random.Choice(seedsIndices); var seed = _dataset.GetInstanceData(seedIndex); var boxes = _boxConverter.FromRules(existingRules); if (_runExpensiveSanityChecks) { for (int i = 0; i < boxes.Length; i++) { var box = boxes[i]; if (box.Contains(seed)) { throw new InvalidOperationException(); } } } var dimensionExpansionOrder = NaturalRange.CreateShuffled( inclusiveStart: 0, exclusiveEnd: _dataset.FeatureCount); var secureRectangle = _boxCreator.TryCreateLargestNonIntersectingRectangle( seedIndex: seedIndex, existingHyperRectangles: boxes, dimensionExpansionOrder: dimensionExpansionOrder); if (secureRectangle is null) { return(null); } if (_runExpensiveSanityChecks) { for (int i = 0; i < boxes.Length; i++) { var box = boxes[i]; if (_rectangleIntersector.IntersectsInAllDimension(secureRectangle, box)) { throw new InvalidOperationException(); } } } var secureRectangleCoverage = _coverageComputer.ComputeCoverage(secureRectangle); var coveredInstancesIndices = secureRectangleCoverage.IndicesOfCoveredInstances.ToArray(); if (coveredInstancesIndices.Length == 0) { return(null); } var coveredInstancesDistancesToSeed = _dataset.ComputeDistances( targetInstanceIndex: seedIndex, otherInstancesIndices: coveredInstancesIndices); Array.Sort( keys: coveredInstancesDistancesToSeed, items: coveredInstancesIndices); var instancesToCover = Math.Min(_targetNumberOfInstancesToCover, coveredInstancesIndices.Length); var relevantInstances = coveredInstancesIndices .AsSpan() .Slice(start: 0, length: instancesToCover); var ruleAntecedent = _antecedentCreator.CreateAntecedent( seedIndex: seedIndex, nearestInstancesIndices: relevantInstances); if (ruleAntecedent is null) { return(null); } var ruleConsequent = _consequentCreator.CreateConsequent(relevantInstances); return(new Rule( antecedent: ruleAntecedent, consequent: ruleConsequent)); }