32 public RacesVariantsGenerator(IProgress<double> progressIteration =
null, IProgress<double> progressSolution =
null,
int requiredVariantsCount = 100,
int maxIterations = 100000,
double minScoreThreshold = 90,
int maxGroupSize = 3,
double maxOneElementGroupPercentage = 0.15)
34 _progressIteration = progressIteration;
35 _progressSolution = progressSolution;
36 _maxGroupSize = maxGroupSize;
37 _minScoreThreshold = minScoreThreshold;
38 _maxOneElementGroupPercentage = maxOneElementGroupPercentage;
39 _requiredVariantsCount = requiredVariantsCount;
40 _maxIterations = maxIterations;
52 ConcurrentBag<RacesVariant> bestRaces =
new ConcurrentBag<RacesVariant>();
54 int foundVariants = 0;
58 Parallel.For(0, _maxIterations,
new ParallelOptions() { MaxDegreeOfParallelism = (int)(0.25 * Environment.ProcessorCount) }, (i, state) =>
60 if (cancellationToken.IsCancellationRequested || bestRaces.Count >= _requiredVariantsCount)
71 if (score >= _minScoreThreshold)
73 bestRaces.Add(candidate);
74 Interlocked.Increment(ref foundVariants);
77 Interlocked.Increment(ref attempts);
80 double iterationProgress = (double)attempts / _maxIterations;
81 double solutionProgress = (double)foundVariants / _requiredVariantsCount;
84 _progressIteration?.Report(iterationProgress * 100);
85 _progressSolution?.Report(solutionProgress * 100);
87 }, cancellationToken);
89 return bestRaces.OrderByDescending(r => r.Score).Take(_requiredVariantsCount).ToList();
100 List<List<PersonStart>> groups =
new List<List<PersonStart>>();
101 List<List<PersonStart>> shuffledSets = sets.OrderBy(_ => _random.Next()).ToList();
102 int oneElementGroupsCount = 0;
104 foreach (List<PersonStart>
set in shuffledSets)
106 HashSet<PersonStart> remainingElements =
new HashSet<PersonStart>(
set.OrderBy(_ => _random.Next()));
108 while (remainingElements.Count > 0)
110 int maxSize = Math.Min(_maxGroupSize, remainingElements.Count);
111 int minSize = Math.Max(2, (
int)(maxSize * 0.5));
113 int groupSize = _random.Next(minSize, maxSize + 1);
114 List<PersonStart> selectedGroup = remainingElements.Take(groupSize).ToList();
116 if (selectedGroup.Count == 1)
118 oneElementGroupsCount++;
121 groups.Add(selectedGroup);
123 remainingElements.Remove(item);
128 if ((
double)oneElementGroupsCount / groups.Count > _maxOneElementGroupPercentage)
134 foreach (var group
in groups)
136 variant.Races.Add(
new Race(group));
148 private List<List<PersonStart>>
MergeSmallGroups(List<List<PersonStart>> groups, List<List<PersonStart>> sets)
150 List<List<PersonStart>> result =
new();
151 HashSet<int> mergedIndices =
new();
153 for (
int i = 0; i < groups.Count; i++)
155 if (mergedIndices.Contains(i))
158 var groupA = groups[i];
161 if (groupA.Count >= 1)
169 for (
int j = i + 1; j < groups.Count; j++)
171 if (mergedIndices.Contains(j))
174 var groupB = groups[j];
176 if (groupA.Count + groupB.Count <= _maxGroupSize &&
177 AreFromSameSet(groupA.Concat(groupB).ToList(), sets))
179 result.Add(groupA.Concat(groupB).ToList());
180 mergedIndices.Add(i);
181 mergedIndices.Add(j);