public static FormulaGenerationArguments CreateRandom(Random random, Bounds<int> dimensionCountBounds, Bounds<int> minimalDepthBounds, Bounds leafProbabilityBounds, Bounds constantProbabilityBounds, Bounds constantBounds, IDictionary<Operator, Bounds> operatorAndMaxProbabilityBoundsMap, Operator[] obligatoryOperators, Bounds unaryVsBinaryOperatorsProbabilityBounds) { Dictionary<Operator, double> operatorAndProbabilityMap = operatorAndMaxProbabilityBoundsMap.ToDictionary(e => e.Key, e => random.Next(e.Value)); Operator[] unaryOperators = operatorAndMaxProbabilityBoundsMap.Keys.Where(op => op.Arity == 1).ToArray(); Operator[] binaryOperators = operatorAndMaxProbabilityBoundsMap.Keys.Where(op => op.Arity == 2).ToArray(); int unaryOperatorsToDeleteCount = random.Next(new Bounds<int>(0, unaryOperators.Length - 1)); int binaryOperatorsToDeleteCount = random.Next(new Bounds<int>(0, binaryOperators.Length - 1)); var unaryOperatorsToDelete = random.TakeDistinct(unaryOperators, unaryOperatorsToDeleteCount).Where(op => obligatoryOperators.All(o => o != op)); var binaryOperatorsToDelete = random.TakeDistinct(binaryOperators, binaryOperatorsToDeleteCount).Where(op => obligatoryOperators.All(o => o != op)); var operatorsToDelete = unaryOperatorsToDelete.Concat(binaryOperatorsToDelete); foreach (var op in operatorsToDelete) { operatorAndProbabilityMap.Remove(op); } double ubp = random.Next(unaryVsBinaryOperatorsProbabilityBounds); double ups = operatorAndProbabilityMap.Where(e => e.Key.Arity == 1).Sum(e => e.Value); double bps = operatorAndProbabilityMap.Where(e => e.Key.Arity == 2).Sum(e => e.Value); double correctionCoef = ubp / (1 - ubp) * bps / ups; operatorAndProbabilityMap.Select(e => e.Key).Where(op => op.Arity == 1).ToArray(). ForEach(op => operatorAndProbabilityMap[op] *= correctionCoef); return new FormulaGenerationArguments { DimensionsCount = random.Next(dimensionCountBounds), MinimalDepth = random.Next(minimalDepthBounds), LeafProbability = random.Next(leafProbabilityBounds), ConstantProbability = random.Next(constantProbabilityBounds), OperatorAndProbabilityMap = operatorAndProbabilityMap, CreateConstant = () => { double c = Math.Round(random.Next(constantBounds), 2); return Math.Abs(c - 0) < 0.01 ? 0.01 : c; } }; }