Beispiel #1
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;
        }
Beispiel #2
0
        //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;
        }
Beispiel #3
0
        //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;
        }
Beispiel #4
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;
        }
Beispiel #5
0
        //When the fit is not constant, the corresponding dependent variable (combination of variables, exponents & operations) has also to be displayed.
        //This is what this method takes care of: displaying the dependent variable by following the expected format
        public List<VarValue> writeVarInRTB(Combination curComb)
        {
            rtbCombinations.AppendText(Environment.NewLine);
            rtbCombinations.AppendText(Environment.NewLine);
            rtbText("Where: ");

            bool noExponents = true;
            int i = -1;
            while (i < curComb.items.Count - 1 && noExponents)
            {
                i = i + 1;
                if (curComb.items[i].exponent != 1.0 && curComb.items[i].exponent > -9999) noExponents = false;
            }

            if (noExponents) rtbCombinations.AppendText(Environment.NewLine); //Additional space to avoid when both lines are too close (= all the variables have 1.0 as exponent)

            rtbCombinations.AppendText(Environment.NewLine);
            rtbText("VAR = ");

            List<VarValue> curVarVals = new List<VarValue>();

            //Loop iterating through all the elements of the given combination and performing the corresponding actions (e.g., updating the text in rtbCombinations or setting as many NumericUpDowns as dependent variables)
            for (i = 0; i < curComb.items.Count; i++)
            {
                rtbSuperIndices(curComb.items[i].exponent, true, curComb.items[i].variable.input.displayedName);
                if (i < curComb.items.Count - 1) rtbOperation(curComb.items[i].operation);

                while (curVarVals.Count - 1 < curComb.items[i].variable.index)
                {
                    curVarVals.Add(new VarValue() { variable = new Variable(), value = 0.0 });
                }
                curVarVals.Insert(curComb.items[i].variable.index, new VarValue() { variable = curComb.items[i].variable, value = curComb.items[i].variable.input.min });

                mainForm.setInputNumUpDown(i, curComb.items[i].variable); //Setting up the corresponding NumericUpDowns and Labels
            }

            return curVarVals;
        }
Beispiel #6
0
        public List<double> realVals; //Y (independent variable) values as read from the input file

        #endregion Fields

        #region Constructors

        public ValidCombination()
        {
            realVals = new List<double>();
            calcVals = new List<RowVal>();
            errors = new List<double>();
            coeffs = new PolCoeffs();
            dependentVars = new Combination();
            independentVar = new Variable();
            assessment = new Assessment();
        }
Beispiel #7
0
        public List<RowVal> values; //List of values associated with the given combination (one value per row) and the distribution of the contribution from each variable (in case of being more than one) to each value

        #endregion Fields

        #region Constructors

        public CombValues()
        {
            combination = new Combination();
            values = new List<RowVal>();
        }
Beispiel #8
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;
        }
Beispiel #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;
        }
Beispiel #10
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;
        }
Beispiel #11
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;
        }
        //Method called from the main combinatorics loops for multivariate cases above (addMulti). Its whole purpose is reducing the size of the loops.
        //It includes the "more internal loops", the ones creating the corresponding ValidCombination and adding it to the list of all the combinations so far
        private List<ValidCombination> internalLoop(int[] curOpers, int[] curExps, List<ValidCombination> allCombinations, Config curConfig, List<int> indices, List<Input> inputs, Variable indepVar)
        {
            for (int rel = 0; rel < curConfig.operations.Count; rel++)
            {
                if (cancelSim) return allCombinations;

                Combination curCombination = new Combination();
                curOpers[indices.Count - 2] = rel;

                for (int i = 0; i < indices.Count; i++)
                {
                    int genIndex = indices[i];

                    //The cast to decimal type is included in order to avoid problems with the double floating point (e.g., without casting to decimal, 10.55 wouldn't be found)
                    int maxDec = inputs[genIndex].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 = genIndex, input = inputs[genIndex], noDec = maxDec };
                    CombinationItem curItem = new CombinationItem() { variable = curVariable, exponent = curConfig.exponents[curExps[i]], operation = curConfig.operations[curOpers[i]] };
                    curCombination.items.Add(curItem);
                }

                allCombinations = addToAllCombinations(curCombination, inputs, curConfig, allCombinations, indepVar);
            }

            return allCombinations;
        }
        //Accessory method called from the one above to determine whether two combinations are equivalent or not
        private bool dependentAreEquivalent(Combination dependentVars1, Combination dependentVars2)
        {
            bool areEquivalent = true;
            for (int i = 0; i < dependentVars1.items.Count; i++)
            {
                bool found = false;
                for (int i2 = 0; i2 < dependentVars2.items.Count; i2++)
                {
                    if (dependentVars1.items[i].variable.index == dependentVars2.items[i2].variable.index)
                    {
                        if (dependentVars1.items[i].exponent == dependentVars2.items[i2].exponent)
                        {
                            bool goAhead = dependentVars1.items[i].operation == dependentVars2.items[i2].operation;
                            if (!goAhead && i == dependentVars1.items.Count - 1) goAhead = true;
                            if (goAhead)
                            {
                                found = true;
                                break;
                            }
                        }
                    }
                }

                if (!found)
                {
                    areEquivalent = false;
                    break;
                }
            }

            return areEquivalent;
        }
        //Method starting the creation of the corresponding "ValidCombination" and, eventually, storing it in the list including all the ones so far
        private List<ValidCombination> addToAllCombinations(Combination curCombination, List<Input> inputs, Config curConfig, List<ValidCombination> allCombinations, Variable indepVar)
        {
            ValidCombination curValid = newCombination(curCombination, indepVar, inputs, allCombinations, curConfig);
            if (curValid != null)
            {
                if (allCombinations.Count >= curConfig.maxNoCombs)
                {
                    allCombinations = allCombinations.OrderByDescending(x => x.assessment.globalRating).ToList();

                    if (curValid.assessment.globalRating > allCombinations[allCombinations.Count - 1].assessment.globalRating)
                    {
                        allCombinations.RemoveAt(allCombinations.Count - 1);
                    }
                    else
                    {
                        curValid = null;
                    }
                }

                if (curValid != null)
                {
                    if (curValid.dependentVars.items.Count < 1)
                    {
                        if (curValid.coeffs.B != 0.0 || curValid.coeffs.C != 0.0) curValid = null;
                    }
                }
            }

            if(curValid != null) allCombinations.Add(curValid);

            return allCombinations;
        }
        //Method in charge of putting together all the inputs for the given combination (i.e., variables, exponents and operations) and bring together all the remaining factors (e.g., suitability of the fit)
        //to form the associated ValidCombination and add it to the list of valid combinations created so far
        private List<ValidCombination> addCombination(List<Input> inputs, List<int> indices, Config curConfig, List<ValidCombination> allCombinations, Variable indepVar)
        {
            if (indices.Count == 1)
            {
                //Only one variable is accounted for and thus the whole combinatorial process will consist in accounting for the different exponents
                int genIndex = indices[0];

                for (int i = 0; i < curConfig.exponents.Count; i++)
                {
                    if (cancelSim) break;

                    Combination curCombination = new Combination();

                    //The cast to decimal type is included in order to avoid problems from the double floating point (e.g., 10.55)
                    int maxDec = inputs[genIndex].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 = genIndex, input = inputs[genIndex], noDec = maxDec };
                    CombinationItem curItem = new CombinationItem() { variable = curVariable, exponent = curConfig.exponents[i], operation = curConfig.operations[0] };
                    curCombination.items.Add(curItem);

                    allCombinations = addToAllCombinations(curCombination, inputs, curConfig, allCombinations, indepVar);
                }
            }
            else
            {
                //Various variables are accounted for and thus everything (i.e., variables, exponents & operations) have to be brought into picture
                allCombinations = addMulti(inputs, indices, curConfig, allCombinations, indepVar);
            }

            return allCombinations;
        }