//Method in charge of performing the initial actions to convert a "Combination" variable into a ValidCombination one, that is: regression and first crosscheck of the //calculated values against the applicable error thresholds private ValidCombination createValidComb2(Combination curCombination, List<Input> inputs, CombValues xVals, CombValues yVals, Config curConfig) { ValidCombination curValidComb = new ValidCombination(); //Performing the corresponding regression to determine the polynomial fit matching the input conditions CurveFitting curFitting = new CurveFitting(); PolCurve curCurve = curFitting.performPolRegress(xVals, yVals); List<double> errors = new List<double>(); curValidComb.dependentVars.items = new List<CombinationItem>(curCombination.items); curValidComb.independentVar = curCurve.yValues.combination.items[0].variable; curValidComb.coeffs = curCurve.coeffs; //Loop applying the newly-created fit to all the input values and calculating the associated variables for (int i = 0; i < xVals.values.Count; i++) { double realVal = yVals.values[i].value; curValidComb.realVals.Add(realVal); RowVal curCalcVal = new RowVal(); curCalcVal.value = Common.valueFromPol(curCurve.coeffs, xVals.values[i].value); curCalcVal.weights = xVals.values[i].weights; curCalcVal.weights2 = xVals.values[i].weights2; curValidComb.calcVals.Add(curCalcVal); double curError = Common.errorCalcs(realVal, curCalcVal.value); curValidComb.errors.Add(curError); if (curError <= curConfig.fitConfig.averLimit) curValidComb.lowErrorCount = curValidComb.lowErrorCount + 1; } curValidComb.averError = curValidComb.errors.Average(x => x); bool isOK = false; if (curValidComb.averError <= curConfig.fitConfig.globalAver) { if ((double)curValidComb.lowErrorCount / (double)curValidComb.errors.Count >= curConfig.fitConfig.minPercBelowLimit) { isOK = true; } } if (!isOK) curValidComb = null; return curValidComb; }
//Method called to populate the corresponding RowVal variable, that is: value resulting from the given (combination + input values) and the contribution from each variable to it (weight) public static RowVal calculateXValue(Combination curCombination, List<Input> inputs, List<double> curRow) { RowVal curRowVal = new RowVal(); if (curCombination.items.Count == 1) { //Just one item. What means: just one variable with just one exponent int curIndex = curCombination.items[0].variable.index; curRowVal.value = applyExponent(curRow[0], curCombination.items[0].exponent); curRowVal.weights.Add(1.0); } else { //Combination formed by various items (i.e., variables, exponents and operations) List<double> curVals = new List<double>(); //To carry out the (sequential) calculations List<double> curVals2 = new List<double>(); //To determine the weights of all the variables after the calculations have been performed List<Operation> curOpers = new List<Operation>(); List<Operation> curOpers2 = new List<Operation>(); for (int i = 0; i < curCombination.items.Count; i++) { double curVal = applyExponent(curRow[i], curCombination.items[i].exponent); curVals.Add(curVal); curVals2.Add(curVal); curOpers.Add(curCombination.items[i].operation); curOpers2.Add(curCombination.items[i].operation); } int calcs = 0; while (calcs < 2) //Loop performing the operations of the combination in the right order (e.g., firstly multiplications and secondly additions) { calcs = calcs + 1; for (int i = 0; i < curVals.Count - 1; i++) { if (calcs == 1 && curOpers[i] == Operation.Multiplication) { double curVal = curVals[i] * curVals[i + 1]; curVals[i] = curVal; curVals.RemoveAt(i + 1); curOpers[i] = curOpers[i + 1]; curOpers.RemoveAt(i + 1); } else if (calcs == 2 && curOpers[i] == Operation.Addition) { double curVal = curVals[i] + curVals[i + 1]; curVals[i] = curVal; curVals.RemoveAt(i + 1); curOpers[i] = curOpers[i + 1]; curOpers.RemoveAt(i + 1); } } } curRowVal.value = curVals[0]; for (int i = 0; i < curVals2.Count; i++) { double curWeight = curRowVal.value == 0 ? 0 : Math.Abs(curVals2[i] / curRowVal.value); 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 curRowVal.weights.Add(curWeight); } if (curCombination.items.Count > 2) { //Accounting for multivariate weights (i.e., groups of multiplying variables) curRowVal.weights2 = calculateWeights2(curCombination, curVals2, curOpers2, curRowVal.value); } } return curRowVal; }
//Method actually creating a new ValidCombination variable and performing preliminary validity checks private ValidCombination newCombination(Combination curCombination, Variable yVar, List<Input> inputs, List<ValidCombination> allValidCombinations, Config curConfig) { //Performing the regression and the corresponding analysis to determine whether this specific combination should be stored or not CombValues xVals = Common.getCombinationListVals(curCombination, inputs); CombValues yVals = new CombValues(); yVals.combination = new Combination(); int maxDec = inputs[yVar.index].vals.Max(x => x <= Int32.MaxValue ? ((decimal)x - Convert.ToInt32((decimal)x)).ToString().Length - 2 : 0); if (maxDec < 0) maxDec = 0; Variable curVariable = new Variable() { index = yVar.index, input = inputs[yVar.index], noDec = maxDec }; CombinationItem curItem = new CombinationItem() { variable = curVariable, operation = new Operation(), exponent = 1.0 }; yVals.combination.items.Add(curItem); for (int row = 0; row < inputs[yVar.index].vals.Count; row++) { RowVal curRowVal = new RowVal(); curRowVal.value = inputs[yVar.index].vals[row]; curRowVal.weights.Add(1.0); yVals.values.Add(curRowVal); } Analysis curAnalysis = new Analysis(); ValidCombination curValidCombination = curAnalysis.createValidComb(curCombination, inputs, xVals, yVals, curConfig, true); if (curValidCombination != null && allValidCombinations.Count > 0) { if (alreadyStored(curValidCombination, allValidCombinations)) { curValidCombination = null; } } return curValidCombination; }