//Method calculating the list of Weight2 associated with the corresponding row/combination. Weight2 involve always more than one variable (connected by multiplication) private static List<Weight2> calculateWeights2(Combination curCombination, List<double> curVals2, List<Operation> curOpers2, double rowVal) { List<Weight2> curWeights2 = new List<Weight2>(); for (int i = 0; i < curVals2.Count; i++) { if (i < curVals2.Count - 1 && curOpers2[i] == Operation.Multiplication) { Weight2 curWeight2 = new Weight2(); curWeight2.combItems.Add(curCombination.items[i]); curWeight2.combValue = curVals2[i]; i = i + 1; curWeight2.combItems.Add(curCombination.items[i]); curWeight2.combValue = curWeight2.combValue * curVals2[i]; while (i < curVals2.Count - 1) { if (curOpers2[i] == Operation.Multiplication) { i = i + 1; curWeight2.combItems.Add(curCombination.items[i]); curWeight2.combValue = curWeight2.combValue * curVals2[i]; } else { i = i - 1; break; } } curWeights2.Add(curWeight2); } else if (i == 0 || curOpers2[i - 1] != Operation.Multiplication) { curWeights2.Add(new Weight2() { combValue = curVals2[i], combItems = new List<CombinationItem>() { curCombination.items[i] } }); } } if (curWeights2.Count > 1) { foreach (Weight2 item in curWeights2) { double curWeight = rowVal == 0 ? -1 : Math.Abs(item.combValue / rowVal); if (curWeight > 1 || curWeight < 0) curWeight = 1.0; //This variable is meant to dismiss variables not relevant at all (i.e., being consistently very small); any other situation does not really matter item.combWeight = curWeight; } } else { curWeights2 = new List<Weight2>(); } return curWeights2; }
//Looking at the weights2 variable to determine whether there are group of factors (e.g., var1*var2) which should better be removed private ValidCombination removeMultiRedundant(ValidCombination curValidComb, List<Input> inputs, CombValues yVals, Config curConfig) { List<Weight2> allWeights2 = new List<Weight2>(); for (int i = 0; i < curValidComb.calcVals[0].weights2.Count; i++) { //i2 avoids the warning "Using the iteration variable in a lambda expression is..." //which, curiously, is only shown in VB.NET (even with Option Strict Off!), but not in C# (even though this "problem" is common to both) int i2 = i; Weight2 curWeight2 = new Weight2(); curWeight2.combWeight = curValidComb.calcVals.Average(x => x.weights2[i2].combWeight); curWeight2.combItems = new List<CombinationItem>(curValidComb.calcVals[0].weights2[i].combItems); allWeights2.Add(curWeight2); } bool goAhead = allWeights2.FirstOrDefault(x => x.combWeight >= curConfig.limitVals.tooRelevantWeight) != null; goAhead = goAhead ? goAhead : allWeights2.FirstOrDefault(x => x.combWeight <= 0.5 * curConfig.limitVals.maxErrorToIgnoreVar) != null; if (goAhead) { //One of the variables contributes in a much more relevant way (to the final calculated value) than all the other ones in the combination List<int> itemsToIgnore = new List<int>(); for (int i = 0; i < allWeights2.Count; i++) { if (allWeights2[i].combWeight < curConfig.limitVals.tooRelevantWeight) { //The current variable might be irrelevant. The analysis performed in the following lines consists basically in removing this variable and comparing the resulting errors (with vs. without it) Combination tempDependent = new Combination(); tempDependent.items = curValidComb.dependentVars.items.Except(allWeights2[i].combItems).ToList(); if (ignoreItem(tempDependent, curValidComb, inputs, yVals, curConfig)) { itemsToIgnore.AddRange(allWeights2[i].combItems.Select(x => x.variable.index)); } } } if (itemsToIgnore.Count > 0) { curValidComb = validCombWithIgnoredItems(curValidComb, itemsToIgnore, inputs, yVals, curConfig, true); } } return curValidComb; }