private static async Task IterateAllParametersNoRecursion(ApproachDefinition approachDefinition, List <AlgorithmParameter> parameters, RunDefinitionBuffer buffer) { //build arrays of possible values double[][] parameterRanges = new double[parameters.Count][]; for (int current = 0; current < parameters.Count; current++) { parameterRanges[current] = parameters[current].GetParamterRange(); } //now get the cartesian product of all the lists var allCombinations = Common.Crossproduct <double>(parameterRanges); foreach (var combination in allCombinations) { var index = 0; foreach (var value in combination) { if (parameters[index].ValueIsBoolean) { parameters[index].BooleanValue = value != 0; } else { parameters[index].NumericValue = value; } index++; } await buffer.AddAsync(new RunDefinition(approachDefinition)); //await Task.Delay(1); } }
private static void IterateSingleParameter(ApproachDefinition approach, AlgorithmParameter currentParameter, RunDefinitionBuffer buffer) { if (currentParameter.UseRange) { if (currentParameter.ValueIsBoolean) { //The boolean range is only 2 values...so we just set those two and recurse the other parameters currentParameter.BooleanValue = true; buffer.AddAsync(new RunDefinition(approach)); currentParameter.BooleanValue = false; buffer.AddAsync(new RunDefinition(approach)); } else { //this is a numerical range, so we recurse through all the parameters /* * NOTE: The double extension method of 'LessThanAlmostEqualTo' is used here * to avoid rounding errors due to binary representation of rational numbers * * DECIMAL datatype is more appropriate for this reason, * however is significantly slower than double. When dealing with * millions of iterations, the double vs decimal speed difference is meaningful */ for (double r = currentParameter.RangeStart; r.LessThanAlmostEqualTo(currentParameter.RangeEnd); r += currentParameter.RangeStep) { if (CancelGeneration) { return; //this will prevent an new definitions from buffering, but it still needs to unwind the stack } currentParameter.NumericValue = r; buffer.AddAsync(new RunDefinition(approach)); } } currentParameter.NumericValue = currentParameter.RangeStart; } else { buffer.AddAsync(new RunDefinition(approach)); } }
private static void SaveOrNext(ApproachDefinition approach, List <AlgorithmParameter> otherParameters, RunDefinitionBuffer buffer) { //we only save if there are no other parameters to iterate //this means this iteration definition is complete and all parameters have been set. if (otherParameters.Count == 0) { //create a run definition and buffer it. The buffer manages flushing/saving the run definitions buffer.AddAsync(new RunDefinition(approach)); } else { Task.Delay(1); //there are other parameters that need to be set before we can save the definition IterateAllParameters(approach, otherParameters, buffer); } }