//Method returning the "Gauss coefficients" associated with the input values
        public GaussJordanCoeff getGaussJordanCoeffs(CombValues xValues, CombValues yValues)
        {
            LeastSquaresCoeff curLeastSquares = new LeastSquaresCoeff();

            for (int i = 0; i < xValues.values.Count; i++)
            {
                double curX2 = xValues.values[i].value * xValues.values[i].value;

                curLeastSquares.sumX1 = curLeastSquares.sumX1 + xValues.values[i].value;
                curLeastSquares.sumX2 = curLeastSquares.sumX2 + curX2;
                curLeastSquares.sumX12 = curLeastSquares.sumX12 + (xValues.values[i].value * curX2);
                curLeastSquares.sumX1Y = curLeastSquares.sumX1Y + (xValues.values[i].value * yValues.values[i].value);
                curLeastSquares.sumX22 = curLeastSquares.sumX22 + (curX2 * curX2);
                curLeastSquares.sumX2Y = curLeastSquares.sumX2Y + (curX2 * yValues.values[i].value);
                curLeastSquares.sumY = curLeastSquares.sumY + yValues.values[i].value;
            }

            //Coeffs of the associated matrix to be solved by Gauss-Jordan elimination (i.e., ordered as displayed in the comment below)
            GaussJordanCoeff curGaussJordan = new GaussJordanCoeff();
            curGaussJordan.a[0, 0] = xValues.values.Count;
            curGaussJordan.a[0, 1] = curLeastSquares.sumX1;
            curGaussJordan.a[0, 2] = curLeastSquares.sumX2;
            curGaussJordan.a[1, 0] = curLeastSquares.sumX1;
            curGaussJordan.a[1, 1] = curLeastSquares.sumX2;
            curGaussJordan.a[1, 2] = curLeastSquares.sumX12;
            curGaussJordan.a[2, 0] = curLeastSquares.sumX2;
            curGaussJordan.a[2, 1] = curLeastSquares.sumX12;
            curGaussJordan.a[2, 2] = curLeastSquares.sumX22;

            curGaussJordan.b[0] = curLeastSquares.sumY;
            curGaussJordan.b[1] = curLeastSquares.sumX1Y;
            curGaussJordan.b[2] = curLeastSquares.sumX2Y;

            return curGaussJordan;
        }
Exemple #2
0
        //The original combination ("Combination" class), generated in the combinatorics part, requires from quite a few actions to become a valid combination, that is:
        //a dependent variable in one of the output fits. This method performs this conversion
        public ValidCombination createValidComb(Combination curCombination, List<Input> inputs, CombValues xVals, CombValues yVals, Config curConfig, bool checkModify)
        {
            ValidCombination curValidComb = createValidComb2(curCombination, inputs, xVals, yVals, curConfig);

            if (curValidComb != null)
            {
                if(checkModify) curValidComb = modifyFit(curValidComb, inputs, yVals, curConfig);

                if(curValidComb != null) curValidComb = assessComb(curValidComb, curConfig);
            }

            return curValidComb;
        }
Exemple #3
0
        //This function creates an instance of one of the classes more commonly used during the calculations (i.e., CombValues) and associates to it the value resulting from the given combination
        public static CombValues getCombinationListVals(Combination curCombination, List<Input> inputs)
        {
            CombValues curVals = new CombValues();
            curVals.combination = curCombination;

            for (int row = 0; row < inputs[0].vals.Count; row++)
            {
                List<double> curRow = new List<double>();
                if (curCombination.items.Count == 1)
                {
                    int curIndex = curCombination.items[0].variable.index;
                    double curVal = inputs[curIndex].vals[row];
                    curRow.Add(curVal);
                }
                else
                {
                    for (int i = 0; i < curCombination.items.Count; i++)
                    {
                        int curIndex = curCombination.items[i].variable.index;
                        double curVal = inputs[curIndex].vals[row];
                        curRow.Add(curVal);
                    }
                }

                curVals.values.Add(calculateXValue(curCombination, inputs, curRow));
            }

            return curVals;
        }
 public PolCurve()
 {
     coeffs = new PolCoeffs();
     xValues = new CombValues();
     yValues = new CombValues();
 }
        //Method performing the 2nd degree polynomial regression (only one being considered at the moment)
        public PolCurve performPolRegress(CombValues xValues, CombValues yValues)
        {
            PolCurve curCurve = new PolCurve();
            try
            {
                curCurve.xValues = xValues;
                curCurve.yValues = yValues;

                //Getting the "Gauss coefficients", that is: relying on least squares to calculate the values of the matrix to be solved by Gauss-Jordan
                Coefficients curCoeffs = new Coefficients();
                Coefficients.GaussJordanCoeff curGauss = curCoeffs.getGaussJordanCoeffs(xValues, yValues);

                //Loops iterating through all the "Gauss coefficients" and performing the operations required by the Gauss-Jordan elimination
                for (int i = 0; i < 3; i++)
                {
                    for (int i2 = 0; i2 < 3; i2++)
                    {
                        if (i != i2)
                        {
                            double factor = curGauss.a[i, i] == 0.0 ? 0.0 : -1.0 * curGauss.a[i2, i] / curGauss.a[i, i];

                            for (int i3 = 0; i3 < 3; i3++)
                            {
                                curGauss.a[i2, i3] = factor * curGauss.a[i, i3] + curGauss.a[i2, i3];
                            }
                            curGauss.b[i2] = factor * curGauss.b[i] + curGauss.b[i2];
                        }
                    }
                }

                //A,B,C resulting coefficients of the fit. Example: result = A + B*x + C*x^2
                curCurve.coeffs.A = curGauss.a[0, 0] == 0.0 ? 0.0 : curGauss.b[0] / curGauss.a[0, 0];
                curCurve.coeffs.B = curGauss.a[1, 1] == 0.0 ? 0.0 : curGauss.b[1] / curGauss.a[1, 1];
                curCurve.coeffs.C = curGauss.a[2, 2] == 0.0 ? 0.0 : curGauss.b[2] / curGauss.a[2, 2];

            }
            catch
            {
                curCurve = null; //In case of dealing with too big numbers
            }

            return curCurve;
        }
Exemple #6
0
        //This function forms also part of the redundant-variable-removal process: the removal of the given variable (or group of variables) has been confirmed to be fine and thus
        //this function will update the corresponding ValidCombination variable
        private ValidCombination validCombWithIgnoredItems(ValidCombination curValidComb, List<int> itemsToIgnore, List<Input> inputs, CombValues yVals, Config curConfig, bool isMulti)
        {
            //At least one of the variables in the original combination is redundant and thus the corresponding ValidCombination variable has to be re-calculated
            for (int i = curValidComb.dependentVars.items.Count - 1; i >= 0; i--)
            {
                if (itemsToIgnore.Contains(i)) curValidComb.dependentVars.items.RemoveAt(i);
            }

            if (curValidComb.dependentVars.items.Count < 1)
            {
                curValidComb = null;
            }
            else
            {
                CombValues xVals = Common.getCombinationListVals(curValidComb.dependentVars, inputs);
                curValidComb = createValidComb(curValidComb.dependentVars, inputs, xVals, yVals, curConfig, !isMulti); //Rechecking for redundant variables only after single removals to avoid potential infinite loops
            }

            return curValidComb;
        }
Exemple #7
0
        //Looking at the weights variable to determine whether there are single variables (e.g., var1 + var2) which should better be removed
        private ValidCombination removeSingleRedundant(ValidCombination curValidComb, List<Input> inputs, CombValues yVals, Config curConfig)
        {
            //Addition of the weights of all the variables in each row. This is a simplistic way to determine whether one of the variables
            //forming the given combination is much more relevant than all the other ones
            List<double> allWeights = new List<double>();
            for (int i = 0; i < curValidComb.dependentVars.items.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;
                allWeights.Add(curValidComb.calcVals.Average(x => x.weights[i2]));
            }

            double curMaxWeight = curConfig.limitVals.tooRelevantWeight;
            bool goAhead = allWeights.FirstOrDefault(x => x >= curConfig.limitVals.tooRelevantWeight) >= curConfig.limitVals.tooRelevantWeight;
            goAhead = goAhead ? goAhead : allWeights.FirstOrDefault(x => x <= curConfig.limitVals.maxErrorToIgnoreVar) <= curConfig.limitVals.maxErrorToIgnoreVar;
            if (!goAhead && curValidComb.dependentVars.items.Count > 2)
            {
                curMaxWeight = curConfig.limitVals.tooRelevantWeight2;
                goAhead = allWeights.FirstOrDefault(x => x >= curConfig.limitVals.tooRelevantWeight2) >= curConfig.limitVals.tooRelevantWeight2;
            }

            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 = curValidComb.dependentVars.items.Count - 1; i >= 0; i--)
                {
                    if (allWeights[i] < curMaxWeight)
                    {
                        bool canBeRemoved = (i == curValidComb.dependentVars.items.Count - 1 || curValidComb.dependentVars.items[i].operation != Operation.Multiplication);
                        canBeRemoved = canBeRemoved ? (i == 0 || curValidComb.dependentVars.items[i - 1].operation != Operation.Multiplication) :  false;
                        if (canBeRemoved)
                        {
                            //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)
                            Combination tempDependent = new Combination();
                            tempDependent.items = new List<CombinationItem>(curValidComb.dependentVars.items);
                            tempDependent.items.RemoveAt(i);

                            if (ignoreItem(tempDependent, curValidComb, inputs, yVals, curConfig))
                            {
                                itemsToIgnore.Add(i);
                            }
                        }
                    }
                }

                if (itemsToIgnore.Count > 0)
                {
                    curValidComb = validCombWithIgnoredItems(curValidComb, itemsToIgnore, inputs, yVals, curConfig, false);
                }
            }

            return curValidComb;
        }
Exemple #8
0
        //Method determining whether all the variables forming the corresponding combinations are actually required
        private ValidCombination removeRedundantVars(ValidCombination curValidComb, List<Input> inputs, CombValues yVals, Config curConfig)
        {
            if (curValidComb.dependentVars.items.Count > 1)
            {
                if (curValidComb.calcVals.FirstOrDefault(x => x.weights2.Count > 0) != null)
                {
                    //Removal of redundant groups of variables (i.e., products of 2 or more variables)
                    curValidComb = removeMultiRedundant(curValidComb, inputs, yVals, curConfig);
                }
                if(curValidComb != null) curValidComb = removeSingleRedundant(curValidComb, inputs, yVals, curConfig);
            }

            return curValidComb;
        }
Exemple #9
0
        //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;
        }
Exemple #10
0
        //After a new ValidCombination has been created (and thus the preliminary thresholds have been met), further analysis are required to determine whether it is actually right
        private ValidCombination modifyFit(ValidCombination curValidComb, List<Input> inputs, CombValues yVals, Config curConfig)
        {
            if (fitIsConstant(curValidComb, curConfig))
            {
                //y = A represents accurately the current fit; no further information needs to be accounted for
                if (curValidComb.averError >= curConfig.limitVals.maxErrorConstant)
                {
                    //Having a too big error for a constant fit might indicate an "understanding error". Example: 10001, 9999, 10000... modelled with  y = 10000
                    curValidComb = null;
                }
                else
                {
                    curValidComb.dependentVars = new Combination();
                    curValidComb.coeffs.B = 0;
                    curValidComb.coeffs.C = 0;
                }
            }
            else
            {
                //The current fit is certainly not constant, but some of the variables might not be required. Example: y = x1 + 0.00000000000001 * x2
                curValidComb = removeRedundantVars(curValidComb, inputs, yVals, curConfig);
            }

            return curValidComb;
        }
Exemple #11
0
        //This function is part of the redundant-variable-removal process: after the given variable (or group of variables) has been (temporarily) removed, this
        //function checks whether the resulting combination is still valid or not (and thus the removal process can go further)
        private bool ignoreItem(Combination tempDependent, ValidCombination curValidComb, List<Input> inputs, CombValues yVals, Config curConfig)
        {
            bool ignoreIt = false;

            CombValues xVals = Common.getCombinationListVals(tempDependent, inputs);
            ValidCombination tempValid = createValidComb(tempDependent, inputs, xVals, yVals, curConfig, false);
            if (tempValid != null)
            {
                ignoreIt = tempValid.averError < curValidComb.averError || (tempValid.averError <= curConfig.limitVals.maxErrorToIgnoreVar && curValidComb.averError <= curConfig.limitVals.maxErrorToIgnoreVar);
                ignoreIt = ignoreIt ? ignoreIt : Common.valsAreEquivalent(tempValid.averError, curValidComb.averError, curConfig.limitVals.similarity.medium);
            }

            return ignoreIt;
        }
Exemple #12
0
        //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 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;
        }