/// <summary>
        /// This algorithm calls for each binary option in the variability model the CSP solver to generate a valid, minimal configuration containing that option.
        /// </summary>
        /// <param name="vm">The variability model for which the feature-wise configurations should be generated.</param>
        /// <returns>A list of configurations, in which each configuration is a list of binary options that represent the SELECTED options.</returns>
        public List<List<BinaryOption>> generateFeatureWiseConfigsCSP(VariabilityModel vm)
        {
            this.configurations.Clear();
            Solver.VariantGenerator generator = new Solver.VariantGenerator(null);
            foreach (var opt in vm.BinaryOptions)
            {
                if (opt == vm.Root)
                    continue;
                List<BinaryOption> temp = new List<BinaryOption>();
                temp.Add(opt);
                temp = generator.minimizeConfig(temp, vm, true, null);
                if (temp != null && Configuration.containsBinaryConfiguration(this.configurations, temp) == false)
                    this.configurations.Add(temp);

                //Now finding a configuration without the current option, but with all other options to be able to compute a delta
                List<BinaryOption> withoutOpt = new List<BinaryOption>();
                BinaryOption[] tempArray = temp.ToArray();
                withoutOpt = tempArray.ToList<BinaryOption>();
                withoutOpt.Remove(opt);
                List<BinaryOption> excluded = new List<BinaryOption>();
                excluded.Add(opt);
                withoutOpt = generator.minimizeConfig(withoutOpt, vm, true, excluded);
                if (withoutOpt != null && Configuration.containsBinaryConfiguration(this.configurations, withoutOpt) == false)
                    this.configurations.Add(withoutOpt);
            }

            return this.configurations;
        }
        /// <summary>
        /// This method returns a list of all configurations stored in a given file. All options of the configurations have to be defined in the variability model.
        ///
        /// The file should be structured as follows:
        ///
        /// <![CDATA[ <results> ]]>
        /// <![CDATA[   <row> ]]>
        /// <![CDATA[       <data column="Configuration"> ]]>
        /// <![CDATA[           binaryOption1, binaryOption3,... ]]>
        /// <![CDATA[       </data> ]]>
        /// <![CDATA[       <data column="Variable Features"> ]]>
        /// <![CDATA[           numOption1;64,numOption2;4 ]]>
        /// <![CDATA[       </data> ]]>
        /// <![CDATA[       <data column="Performance"> ]]>
        /// <![CDATA[           21.178 ]]>
        /// <![CDATA[       </data> ]]>
        /// <![CDATA[       <data column="Footprint"> ]]>
        /// <![CDATA[           1679 ]]>
        /// <![CDATA[       </data> ]]>
        /// <![CDATA[   </row> ]]>
        /// <![CDATA[   <row> ]]>
        /// <![CDATA[       <data column="Configuration"> ]]>
        /// <![CDATA[   .... ]]>
        /// <![CDATA[ <results> ]]>
        ///
        ///
        /// </summary>
        /// <param name="dat">Object representing the configuration file.</param>
        /// <param name="model">Variability model of the configurations.</param>
        /// <returns></returns>
        public static List <Configuration> readConfigurations(string file, VariabilityModel model)
        {
            XmlDocument dat = new System.Xml.XmlDocument();

            dat.Load(file);
            return(readConfigurations(dat, model));
        }
        /// <summary>
        /// Checks whether the boolean selection is valid w.r.t. the variability model. Does not check for numeric options' correctness.
        /// </summary>
        /// <param name="config">The list of binary options that are SELECTED (only selected options must occur in the list).</param>
        /// <param name="vm">The variability model that represents the context of the configuration.</param>
        /// <param name="vm">Whether the given list of options represents only a partial configuration. This means that options not in config might be additionally select to obtain a valid configuration.</param>
        /// <returns>True if it is a valid selection w.r.t. the VM, false otherwise</returns>
        public bool checkConfigurationSAT(List<BinaryOption> config, VariabilityModel vm, bool partialConfiguration)
        {
            List<CspTerm> variables = new List<CspTerm>();
            Dictionary<BinaryOption, CspTerm> elemToTerm = new Dictionary<BinaryOption, CspTerm>();
            Dictionary<CspTerm, BinaryOption> termToElem = new Dictionary<CspTerm, BinaryOption>();
            ConstraintSystem S = CSPsolver.getConstraintSystem(out variables, out elemToTerm, out termToElem, vm);

            //Feature Selection
            foreach (BinaryOption binayOpt in elemToTerm.Keys)
            {
                CspTerm term = elemToTerm[binayOpt];
                if (config.Contains(binayOpt))
                {
                    S.AddConstraints(S.Implies(S.True, term));
                }
                else if (!partialConfiguration)
                {
                    S.AddConstraints(S.Implies(S.True, S.Not(term)));
                }
            }

            ConstraintSolverSolution sol = S.Solve();
            if (sol.HasFoundSolution)
            {
                return true;
            }
            else
                return false;
        }
Esempio n. 4
0
        /// <summary>
        /// Creates a new mixed constraint between boolean and numeric options and literals.
        /// </summary>
        /// <param name="unparsedExpr">The expression of the constraint as string.</param>
        /// <param name="varMod">The variability model the constraint applies to.</param>
        /// <param name="requirement">String indicating if the constraints evaluates to
        ///                           to false if not all options are present.</param>
        /// <param name="exprKind">Value indicating if the the expression will be negated.</param>
        public MixedConstraint(String unparsedExpr, VariabilityModel varMod, string requirement, string exprKind = "pos")
            : base(unparsedExpr, varMod)
        {
            if (requirement.Trim().ToLower().Equals(REQUIRE_ALL))
            {
                this.requirement = REQUIRE_ALL;
            }
            else if (requirement.Trim().ToLower().Equals(REQUIRE_NONE))
            {
                this.requirement = REQUIRE_NONE;
            }
            else
            {
                throw new ArgumentException(String.Format("The tag {0} for mixed requirements is not valid.", requirement));
            }

            if (exprKind.Trim().ToLower().Equals(NEGATIVE))
            {
                this.negativeOrPositiveExpr = NEGATIVE;
            }
            else if (exprKind.Trim().ToLower().Equals(POSITIVE))
            {
                this.negativeOrPositiveExpr = POSITIVE;
            }
            else
            {
                throw new ArgumentException(String.Format("The expression kind {0} is not valid. Expression can either be neg or pos.", exprKind));
            }
        }
        /// <summary>
        /// Creates a new mixed constraint between boolean and numeric options and literals.
        /// </summary>
        /// <param name="unparsedExpr">The expression of the constraint as string.</param>
        /// <param name="varMod">The variability model the constraint applies to.</param>
        /// <param name="requirement">String indicating if the constraints evaluates to
        ///                           to false if not all options are present.</param>
        /// <param name="exprKind">Value indicating if the the expression will be negated.</param>
        public MixedConstraint(String unparsedExpr, VariabilityModel varMod, string requirement, string exprKind = "pos")
            : base(unparsedExpr, varMod)
        {
            if (requirement.Trim().ToLower().Equals(REQUIRE_ALL))
            {
                this.requirement = REQUIRE_ALL;
            }
            else if (requirement.Trim().ToLower().Equals(REQUIRE_NONE))
            {
                this.requirement = REQUIRE_NONE;
            }
            else
            {
                throw new ArgumentException(String.Format("The tag {0} for mixed requirements is not valid.", requirement));
            }

            if (exprKind.Trim().ToLower().Equals(NEGATIVE))
            {
                this.negativeOrPositiveExpr = NEGATIVE;
            }
            else if (exprKind.Trim().ToLower().Equals(POSITIVE))
            {
                this.negativeOrPositiveExpr = POSITIVE;
            }
            else
            {
                throw new ArgumentException(String.Format("The expression kind {0} is not valid. Expression can either be neg or pos.", exprKind));
            }

            String[] parts = base.ToString().Split(new string[] { ">", "<", "=", "<=", ">=" }, StringSplitOptions.None);
            leftHandSide  = new InfluenceFunction(parts[0], varMod);
            rightHandSide = new InfluenceFunction(parts[parts.Length - 1], varMod);
            var           = varMod;
        }
Esempio n. 6
0
        private VariabilityModel extractFeatureModelFromExpression(String expression)
        {
            VariabilityModel varModel = new VariabilityModel("TEMP");

            string[] parts = expression.Split(new char[] { '+', '*', '[', ']' });

            double value = 0.0;

            for (int i = 0; i < parts.Length; i++)
            {
                string part = parts[i].Trim();
                if (part.Length > 0)
                {
                    if (!Double.TryParse(part, out value))
                    {
                        if (varModel.getNumericOption(part) == null)
                        {
                            NumericOption option = new NumericOption(varModel, part);
                            varModel.addConfigurationOption(option);
                        }
                    }
                }
            }
            return(varModel);
        }
Esempio n. 7
0
        /// <summary>
        /// Creates a binary option based on the information stored in the xml node. The binary option is assigned to the variability model.
        /// </summary>
        /// <param name="node">Node of the xml file holding the information of the binary option.</param>
        /// <param name="vm">The variabilit model the binary option is assigned to. </param>
        /// <returns>A binary option of the variabilit model with the information stored in the xml node.</returns>
        public static BinaryOption loadFromXML(XmlElement node, VariabilityModel vm)
        {
            BinaryOption option = new BinaryOption(vm, "temp");

            option.loadFromXML(node);
            return(option);
        }
        /// <summary>
        /// Creates a new NonBooleanConstraint for a expression. The expression have to consist binary and numeric options and operators such as "+,*,>=,<=,>,<, and =" only. 
        /// Where all binary and numeric options have to be defined in the variability model. 
        /// </summary>
        /// <param name="unparsedExpression"></param>
        /// <param name="varModel"></param>
        public NonBooleanConstraint(String unparsedExpression, VariabilityModel varModel)
        {
            if (unparsedExpression.Contains(">="))
            {
                comparator = ">=";
            }
            else if (unparsedExpression.Contains("<="))
            {
                comparator = "<=";
            }
            else if (unparsedExpression.Contains("="))
            {
                comparator = "=";
            }
            else if (unparsedExpression.Contains(">"))
            {
                comparator = ">";
            }
            else if (unparsedExpression.Contains("<"))
            {
                comparator = "<";
            }

            String[] parts = unparsedExpression.Split(comparator.ToCharArray());
            leftHandSide = new InfluenceFunction(parts[0], varModel);
            rightHandSide = new InfluenceFunction(parts[parts.Length-1], varModel);
        }
Esempio n. 9
0
        /// <summary>
        /// Creates a numeric option based on the information of the given XML Node (calls base function)
        /// </summary>
        /// <param name="numOptNode">The XML Element containing the information</param>
        /// <param name="variabilityModel">The variability model to which the option belongs to</param>
        /// <returns>The newly created option</returns>
        internal static ConfigurationOption loadFromXML(XmlElement numOptNode, VariabilityModel variabilityModel)
        {
            NumericOption numOpt = new NumericOption(variabilityModel, "temp");

            numOpt.loadFromXML(numOptNode);
            return(numOpt);
        }
Esempio n. 10
0
        /// <summary>
        /// Creates a new NonBooleanConstraint for a expression. The expression have to consist binary and numeric options and operators such as +, *, &lt;=, &lt;, &gt;=, &gt;, and = only.
        /// Where all binary and numeric options have to be defined in the variability model.
        /// </summary>
        /// <param name="unparsedExpression"></param>
        /// <param name="varModel"></param>
        public NonBooleanConstraint(String unparsedExpression, VariabilityModel varModel)
        {
            if (unparsedExpression.Contains(">="))
            {
                comparator = ">=";
            }
            else if (unparsedExpression.Contains("<="))
            {
                comparator = "<=";
            }
            else if (unparsedExpression.Contains("="))
            {
                comparator = "=";
            }
            else if (unparsedExpression.Contains(">"))
            {
                comparator = ">";
            }
            else if (unparsedExpression.Contains("<"))
            {
                comparator = "<";
            }

            String[] parts = unparsedExpression.Split(comparator.ToCharArray());
            leftHandSide  = new InfluenceFunction(parts[0], varModel);
            rightHandSide = new InfluenceFunction(parts[parts.Length - 1], varModel);
        }
 /// <summary>
 /// This method returns a list of all configurations stored in a given file. All options of the configurations have to be defined in the variability model.
 ///
 /// If the file is a xml file, it should be structured as follows:
 ///
 /// <![CDATA[ <results> ]]>
 /// <![CDATA[   <row> ]]>
 /// <![CDATA[       <data column="Configuration"> ]]>
 /// <![CDATA[           binaryOption1, binaryOption3,... ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Variable Features"> ]]>
 /// <![CDATA[           numOption1;64,numOption2;4 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Performance"> ]]>
 /// <![CDATA[           21.178 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Footprint"> ]]>
 /// <![CDATA[           1679 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[   </row> ]]>
 /// <![CDATA[   <row> ]]>
 /// <![CDATA[       <data column="Configuration"> ]]>
 /// <![CDATA[   .... ]]>
 /// <![CDATA[ <results> ]]>
 ///
 ///
 /// If the file is a csv file, two different formats are supported.
 ///
 /// For the first on, the file should have a header:
 ///
 /// binaryOption1;numOption1;binaryOption2;numOption2;Performance;Footprint
 /// true;64;false;4;21.178;1679
 ///
 /// Note: If a binary option is selected in a configuration, the value can either be "true" or "1".
 ///
 /// In the second format, no header is needed and only binary options are supported. Additionally, the measurements have to consider only one non-functional property.
 ///
 /// </summary>
 /// <param name="file">Full qualified file name.</param>
 /// <param name="model">Variability model of the configurations.</param>
 /// <returns></returns>
 public static List <Configuration> readConfigurations(string file, VariabilityModel model)
 {
     if (file.EndsWith(".xml"))
     {
         XmlDocument dat = new System.Xml.XmlDocument();
         try
         {
             dat.Load(file);
         }
         catch (FileNotFoundException)
         {
             GlobalState.logError.logLine("Configuration file \"" + file + "\" coud not be found."
                                          + " Could not read configurations.");
             return(null);
         }
         catch (XmlException xmlExc)
         {
             GlobalState.logError.logLine("Configuration file \"" + file + "\" has invalid xml format."
                                          + " Could not read configurations. Additional information:" + xmlExc.Message);
             return(null);
         }
         return(readConfigurations(dat, model));
     }
     else
     {
         return(readCSV(file, model));
     }
 }
        /// <summary>
        /// Generates configurations based on the feature-wise heuristic: The method utilizes the structure of the variability model by first determining the set of options that are always selected.
        /// In each iteration, it starts from this set of options (partial configuration) and adds a single option to this partial configurations. 
        /// It then checks whether configuration is valid and if not calls a CSP solver to make this configuration valid with as few selected options as possible.
        /// </summary>
        /// <param name="vm">The variability model for which the feature-wise configurations should be generated.</param>
        /// <returns>A list of configurations, in which each configuration is a list of binary options that represent the SELECTED options.</returns>
        public List<List<BinaryOption>> generateFeatureWiseConfigurations(VariabilityModel vm)
        {
            configurations.Clear();
            List<BinaryOption> optionalFirstLevelElements = new List<BinaryOption>();
            List<BinaryOption> binOptions = vm.BinaryOptions;

            //First: Add options that are present in all configurations
            List<BinaryOption> firstLevelMandatoryFeatures = new List<BinaryOption>();
            foreach (BinaryOption binOpt in binOptions)
            {
                if (binOpt.Parent == null || binOpt.Parent == vm.Root)
                {
                    if (!binOpt.Optional)
                    {
                        if (!binOpt.hasAlternatives())
                        {
                            firstLevelMandatoryFeatures.Add(binOpt);
                            //Todo: Recursive down search
                            /*List<BinaryOption> tmpList = (List<BinaryOption>)vm.getMandatoryChildsRecursive(binOpt);
                            if (tmpList != null && tmpList.Count > 0)
                                firstLevelMandatoryFeatures.AddRange(tmpList);*/
                        }
                    }
                    else
                        optionalFirstLevelElements.Add(binOpt);
                }
            }
            Solver.CheckConfigSAT checkSAT = new Solver.CheckConfigSAT(null);
            Solver.VariantGenerator generator = new Solver.VariantGenerator(null);
            //Generating new configurations: one per option
            if (checkSAT.checkConfigurationSAT(firstLevelMandatoryFeatures, vm, false))
                this.configurations.Add(firstLevelMandatoryFeatures);
            foreach (BinaryOption e in binOptions)
            {
                BinaryOption[] temp = new BinaryOption[firstLevelMandatoryFeatures.Count];
                firstLevelMandatoryFeatures.CopyTo(temp);
                List<BinaryOption> tme = temp.ToList<BinaryOption>();
                if (!tme.Contains(e))
                {
                    tme.Add(e);
                    if (checkSAT.checkConfigurationSAT(tme, vm, false))
                    {
                        if (!this.configurations.Contains(tme))
                            this.configurations.Add(tme);
                    }
                    else
                    {
                        tme = generator.minimizeConfig(tme, vm, true, null);
                        if (tme != null && Configuration.containsBinaryConfiguration(this.configurations, tme) == false)
                            this.configurations.Add(tme);
                    }
                }
                else
                    continue;
            }

            return this.configurations;
        }
        //Two formats are possible: with header and 0,1s for binary selection or no header and giving the names of config options per per line (this excludex numeric options)
        private static List <Configuration> readCSV(string file, VariabilityModel model)
        {
            StreamReader sr;

            try
            {
                sr = new StreamReader(file);
            }
            catch (ArgumentException)
            {
                GlobalState.logError.logLine("Loading a configuration file with empty filename \"\" is not possible." +
                                             " The \"all\" command requires an argument.");
                return(null);
            }
            catch (FileNotFoundException)
            {
                GlobalState.logError.logLine("Configuration file \"" + file + "\" does not exist." +
                                             " Could not read the configuration file.");
                return(null);
            }

            String line1, line2;

            if (!sr.EndOfStream)
            {
                line1 = sr.ReadLine();
            }
            else
            {
                return(null);
            }
            if (!sr.EndOfStream)
            {
                line2 = sr.ReadLine();
            }
            else
            {
                return(null);
            }
            sr.Close();
            var l1 = line1.Split(';');
            var l2 = line2.Split(';');

            if (l1.Length < 2 || l2.Length < 2)
            {
                return(null);
            }
            int d = 0;

            if (int.TryParse(l2[0], out d))
            {
                return(readConfigurations_Header_CSV(file, model));
            }
            else
            {
                return(readCSVBinaryOptFormat(file, model));
            }
        }
Esempio n. 14
0
 /// <summary>
 /// Clears the global state. This mehtod should be used after performing all experiments of one case study.
 /// </summary>
 public static void clear()
 {
     varModel        = null;
     currentNFP      = null;
     allMeasurements = new ResultDB();
     evaluationSet   = new ResultDB();
     nfProperties    = new Dictionary <string, NFProperty>();
     optionOrder     = new List <ConfigurationOption>();
 }
Esempio n. 15
0
 /// <summary>
 /// Clears the global state. This mehtod should be used after performing all experiments of one case study.
 /// </summary>
 public static void clear()
 {
     varModel        = null;
     currentNFP      = null;
     allMeasurements = new ResultDB();
     evalutionSet    = new ResultDB();
     infModel        = null;
     nfProperties    = new Dictionary <string, NFProperty>();
 }
Esempio n. 16
0
        /// <summary>
        /// Generates a configuration for each pair of configuration options. Exceptions: parent-child-relationships, impliciation-relationships
        /// </summary>
        /// <param name="vm">The variability model containing the binary options for which we want to generate the pair-wise configurations.</param>
        /// <returns>A list of configurations in which each configuration is represented by a list of SELECTED binary options</returns>
        public List<List<BinaryOption>> generatePairWiseVariants(VariabilityModel vm)
        {
            //List<String> activeLearning = new List<string>(new string[] { "ls", "inl", "cf", "dcr", "saa", "ive", "wlur", "lir", "vp", "saacyc" });
            this.configurations.Clear();
            List<BinaryOption> measuredElements = new List<BinaryOption>();
            foreach (BinaryOption current in vm.BinaryOptions)
            {
                //if (!activeLearning.Contains(current.Name))
                //    continue;
                measuredElements.Add(current);
                foreach (BinaryOption pair in vm.BinaryOptions)
                {
                    //if (!activeLearning.Contains(pair.Name))
                    //    continue;
                    //Check parent-child relationship
                    if (pair.isAncestor(current) || current.isAncestor(pair) || pair == current)
                        continue;

                    //Check if one option implies the presence of the other option
                    bool impliedOption = false;
                    foreach (var implied in pair.Implied_Options)
                    {
                        if (implied.Count == 1 && implied[0] == current)
                        {
                            impliedOption = true;
                            break;
                        }
                    }
                    if (impliedOption)
                        continue;
                    //vice versa
                    foreach (var implied in current.Implied_Options)
                    {
                        if (implied.Count == 1 && implied[0] == pair)
                        {
                            impliedOption = true;
                            break;
                        }
                    }
                    if (impliedOption)
                        continue;

                    if (pair != current && !measuredElements.Contains(pair))
                    {
                        List<BinaryOption> tempConfig = new List<BinaryOption>();
                        tempConfig.Add(current);
                        tempConfig.Add(pair);
                        tempConfig = generator.minimizeConfig(tempConfig, vm, true, null);

                        if (tempConfig.Count > 0 && !Configuration.containsBinaryConfiguration(configurations,tempConfig))
                            configurations.Add(tempConfig);
                    }
                }
            }
            return this.configurations;
        }
Esempio n. 17
0
 /// <summary>
 /// Sets this configuration option as parent for all binary option
 /// in a model, that have this option as parent.
 /// </summary>
 /// <param name="vm">The model that will be used to update the children.</param>
 public void updateChildren(VariabilityModel vm)
 {
     foreach (ConfigurationOption option in vm.BinaryOptions)
     {
         if (option.parentName != null && option.parentName.Equals(this.name))
         {
             option.Parent = this;
         }
     }
 }
 /// <summary>
 /// Clears the global state. This mehtod should be used after performing all experiments of one case study. 
 /// </summary>
 public static void clear()
 {
     varModel = null;
     currentNFP = null;
     allMeasurements = new ResultDB();
     evalutionSet = new ResultDB();
     infModel = null;
     nfProperties = new Dictionary<string,NFProperty>();
     optionOrder = new List<ConfigurationOption>();
 }
Esempio n. 19
0
 /// <summary>
 /// Creates a new configuration option of the given name for the variability model.
 /// </summary>
 /// <param name="vm">The variability model, the option is defined for.</param>
 /// <param name="name">The name of the configuration option.</param>
 public ConfigurationOption(VariabilityModel vm, String name)
 {
     this.vm = vm;
     if (!name.All(Char.IsLetter))
     {
         this.name = removeInvalidCharsFromName(name);
     }
     else
     {
         this.name = name;
     }
 }
        /// <summary>
        /// Read a Feature model in SXFM format and create a new VaribilityModel that
        /// equals the Feature model.
        /// </summary>
        /// <param name="path">The path of the SXFM Feature model.</param>
        /// <returns>VaribilityModel object that equals the SXFM Feature model.</returns>
        public static VariabilityModel loadFromSXFM(string path)
        {
            VariabilityModel model = new VariabilityModel("to_change");

            if (model.loadSXFM(path))
            {
                return(model);
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// Static method that reads an xml file and constructs a variability model using the stored information
        /// </summary>
        /// <param name="path">Path to the XML File</param>
        /// <returns>The instantiated variability model or null if there is no variability model at the path or if the model could not be parsed.</returns>
        public static VariabilityModel loadFromXML(String path)
        {
            VariabilityModel vm = new VariabilityModel("temp");

            if (vm.loadXML(path))
            {
                return(vm);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 22
0
 /// <summary>
 /// This method returns a list of all configurations stored in a given file. All options of the configurations have to be defined in the variability model.
 ///
 /// If the file is a xml file, it should be structured as follows:
 ///
 /// <![CDATA[ <results> ]]>
 /// <![CDATA[   <row> ]]>
 /// <![CDATA[       <data column="Configuration"> ]]>
 /// <![CDATA[           binaryOption1, binaryOption3,... ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Variable Features"> ]]>
 /// <![CDATA[           numOption1;64,numOption2;4 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Performance"> ]]>
 /// <![CDATA[           21.178 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Footprint"> ]]>
 /// <![CDATA[           1679 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[   </row> ]]>
 /// <![CDATA[   <row> ]]>
 /// <![CDATA[       <data column="Configuration"> ]]>
 /// <![CDATA[   .... ]]>
 /// <![CDATA[ <results> ]]>
 ///
 ///
 /// If the file is a csv file, two different formats are supported.
 ///
 /// For the first on, the file should have a header:
 ///
 /// binaryOption1;numOption1;binaryOption2;numOption2;Performance;Footprint
 /// true;64;false;4;21.178;1679
 ///
 /// Note: If a binary option is selected in a configuration, the value can either be "true" or "1".
 ///
 /// In the second format, no header is needed and only binary options are supported. Additionally, the measurements have to consider only one non-functional property.
 ///
 /// </summary>
 /// <param name="file">Full qualified file name.</param>
 /// <param name="model">Variability model of the configurations.</param>
 /// <returns></returns>
 public static List <Configuration> readConfigurations(string file, VariabilityModel model)
 {
     if (file.EndsWith(".xml"))
     {
         XmlDocument dat = new System.Xml.XmlDocument();
         dat.Load(file);
         return(readConfigurations(dat, model));
     }
     else
     {
         return(readCSV(file, model));
     }
 }
Esempio n. 23
0
        private bool tokenIsAFeatureOrNumber(string token, VariabilityModel varModel)
        {
            token = token.Trim();

            double value = 0.0;

            if (Double.TryParse(token, out value))
            {
                return(true);
            }

            if (varModel != null)
            {
                NumericOption numOption = varModel.getNumericOption(token);
                if (numOption != null)
                {
                    if (!participatingNumOptions.Contains(numOption))
                    {
                        this.participatingNumOptions.Add(numOption);
                    }
                    numberOfParticipatingFeatures++;
                    return(true);
                }

                BinaryOption binOption = varModel.getBinaryOption(token);

                if (token.StartsWith("Enabled") || token.StartsWith("Disabled"))
                {
                    binOption = getAbstractOption(token, varModel);
                }

                if (binOption != null)
                {
                    if (!participatingBoolOptions.Contains(binOption))
                    {
                        this.participatingBoolOptions.Add(binOption);
                    }
                    numberOfParticipatingFeatures++;
                    return(true);
                }
            }
            else
            {
                if (token.Equals(this.numOption.Name))
                {
                    return(true);
                }
            }
            return(false);
        }
Esempio n. 24
0
        private static double getValueOfToken(Configuration config, string token, VariabilityModel fm)
        {
            token = token.Trim();

            double value = 0.0;

            if (Double.TryParse(token, out value))
            {
                return(value);
            }

            NumericOption numOpt = fm.getNumericOption(token);

            if (numOpt != null)
            {
                return(config.NumericOptions[numOpt]);
            }
            BinaryOption binOpt = fm.getBinaryOption(token);

            if (token.StartsWith("Enabled") || token.StartsWith("Disabled"))
            {
                binOpt = getAbstractOption(token, fm);
            }

            if (binOpt != null)
            {
                if (token.Equals("base") || token.Equals("root"))
                {
                    return(1.0);
                }

                if (config.BinaryOptions.Keys.Contains(binOpt) && config.BinaryOptions[binOpt] == BinaryOption.BinaryValue.Selected)
                {
                    return(1.0);
                }
                else
                {
                    foreach (BinaryOption option in config.BinaryOptions.Keys)
                    {
                        // option has to be selected in the configuration
                        if (option.Name == binOpt.Name && config.BinaryOptions[option] == BinaryOption.BinaryValue.Selected)
                        {
                            return(1.0);
                        }
                    }
                }
            }
            return(0.0);
        }
        /// <summary>
        /// This method searches for a corresponding methods in the dynamically loadeda assemblies and calls it if found. It prefers due to performance reasons the Microsoft Solver Foundation implementation.
        /// </summary>
        /// <param name="vm">The variability model containing the binary options and their constraints.</param>
        /// <returns>Returns a list of configurations, in which a configuration is a list of SELECTED binary options (deselected options are not present)</returns>
        public List<List<BinaryOption>> generateAllVariantsFast(VariabilityModel vm)
        {
            foreach (Lazy<IVariantGenerator, ISolverType> solver in solvers)
            {
                if (solver.Metadata.SolverType.Equals("MSSolverFoundation")) return solver.Value.generateAllVariantsFast(vm);
            }

            //If not MS Solver, take any solver. Should be changed when supporting more than 2 solvers here
            foreach (Lazy<IVariantGenerator, ISolverType> solver in solvers)
            {
                return solver.Value.generateAllVariantsFast(vm);
            }

            return null;
        }
Esempio n. 26
0
        private static double getValueOfToken(Configuration config, string token, VariabilityModel fm)
        {
            token = token.Trim();

            double value = 0.0;

            if (Double.TryParse(token, out value))
            {
                return(value);
            }

            NumericOption numOpt = fm.getNumericOption(token);

            if (numOpt != null)
            {
                return(config.NumericOptions[numOpt]);
            }
            BinaryOption binOpt = fm.getBinaryOption(token);

            if (binOpt != null)
            {
                if (token.Equals("base"))
                {
                    return(1.0);
                }

                if (config.BinaryOptions.Keys.Contains(binOpt) && config.BinaryOptions[binOpt] == BinaryOption.BinaryValue.Selected)
                {
                    return(1.0);
                }
                else
                {
                    foreach (BinaryOption option in config.BinaryOptions.Keys)
                    {
                        if (option.Name == binOpt.Name)
                        {
                            return(1.0);
                        }
                    }
                }
            }
            return(0.0);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="vm"></param>
        /// <returns></returns>
        public List<List<BinaryOption>> generateNegativeFWAllCombinations(VariabilityModel vm)
        {
            this.configurations.Clear();
            List<List<BinaryOption>> maxConfigs = new List<List<BinaryOption>>();

            maxConfigs = getMaxConfigurations(vm, true);
            configurations.AddRange(maxConfigs);

            //Compute negative feature-wise for all maximum configurations
            foreach (List<BinaryOption> config in maxConfigs)
            {
                bool abort = false;
                List<BinaryOption> currentConfig = new List<BinaryOption>();
                foreach (BinaryOption e in config)
                    currentConfig.Add(e);

                List<BinaryOption> removedElements = new List<BinaryOption>();

                while (abort == false)
                {
                    abort = true;
                    BinaryOption currentElementUnderConsdiration = null;
                    foreach (BinaryOption e in currentConfig)
                    {
                        currentElementUnderConsdiration = e;
                        //Constructing new Configuration without the current element
                        List<BinaryOption> configToMeasure = new List<BinaryOption>();
                        configToMeasure = generator.generateConfigWithoutOption(e, currentConfig, out removedElements, vm);

                        if (configToMeasure == null)
                        {
                            abort = true;
                            continue;
                        }
                        else if(!Configuration.containsBinaryConfiguration(configurations,configToMeasure))
                            configurations.Add(configToMeasure);

                    }
                }
            }
            return this.configurations;
        }
Esempio n. 28
0
        //Two formats are possible: with header and 0,1s for binary selection or no header and giving the names of config options per per line (this excludex numeric options)
        private static List <Configuration> readCSV(string file, VariabilityModel model)
        {
            StreamReader sr = new StreamReader(file);
            String       line1, line2;

            if (!sr.EndOfStream)
            {
                line1 = sr.ReadLine();
            }
            else
            {
                return(null);
            }
            if (!sr.EndOfStream)
            {
                line2 = sr.ReadLine();
            }
            else
            {
                return(null);
            }
            sr.Close();
            var l1 = line1.Split(';');
            var l2 = line2.Split(';');

            if (l1.Length < 2 || l2.Length < 2)
            {
                return(null);
            }
            int d = 0;

            if (int.TryParse(l2[0], out d))
            {
                return(readConfigurations_Header_CSV(file, model));
            }
            else
            {
                return(readCSVBinaryOptFormat(file, model));
            }
        }
        /// <summary>
        /// Checks whether the boolean selection of a configuration is valid w.r.t. the variability model. Does not check for numeric options' correctness.
        /// </summary>
        /// <param name="c">The configuration that needs to be checked.</param>
        /// <param name="vm">The variability model that represents the context of the configuration.</param>
        /// <returns>True if it is a valid selection w.r.t. the VM, false otherwise</returns>
        public bool checkConfigurationSAT(Configuration c, VariabilityModel vm)
        {
            List<CspTerm> variables = new List<CspTerm>();
            Dictionary<BinaryOption, CspTerm> elemToTerm = new Dictionary<BinaryOption, CspTerm>();
            Dictionary<CspTerm, BinaryOption> termToElem = new Dictionary<CspTerm, BinaryOption>();
            ConstraintSystem S = CSPsolver.getConstraintSystem(out variables, out elemToTerm, out termToElem, vm);

            //Feature Selection
            foreach (BinaryOption binayOpt in elemToTerm.Keys)
            {
                CspTerm term = elemToTerm[binayOpt];
                if (c.getBinaryOptions(BinaryOption.BinaryValue.Selected).Contains(binayOpt))
                {
                    S.AddConstraints(S.Implies(S.True, term));
                }
                else
                {
                    S.AddConstraints(S.Implies(S.True, S.Not(term)));
                }
            }

            ConstraintSolverSolution sol = S.Solve();
            if (sol.HasFoundSolution)
            {
                int count = 0;
                foreach (CspTerm cT in variables)
                {
                    if (sol.GetIntegerValue(cT) == 1)
                        count++;
                }
                //-1??? Needs testing TODO
                if (count - 1 != c.getBinaryOptions(BinaryOption.BinaryValue.Selected).Count)
                {
                    return false;
                }
                return true;
            }
            else
                return false;
        }
Esempio n. 30
0
        private static BinaryOption getAbstractOption(String token, VariabilityModel vm)
        {
            NumericOption numOpt;

            if (token.StartsWith("Enabled"))
            {
                numOpt = vm.getNumericOption(token.Substring(7));
                if (numOpt != null)
                {
                    return(numOpt.abstractEnabledConfigurationOption());
                }
            }
            else
            {
                numOpt = vm.getNumericOption(token.Substring(8));
                if (numOpt != null)
                {
                    return(numOpt.abstractDisabledConfigurationOption());
                }
            }
            return(null);
        }
        private static List <Configuration> readCSVBinaryOptFormat(string file, VariabilityModel model)
        {
            List <Configuration> result = new List <Configuration>();
            StreamReader         sr     = new StreamReader(file);

            while (!sr.EndOfStream)
            {
                var line = sr.ReadLine().Split(';');
                List <BinaryOption> temp = new List <BinaryOption>();
                for (int i = 0; i < line.Length - 1; i++)
                {
                    BinaryOption b = model.getBinaryOption(line[i]);
                    temp.Add(b);
                }
                double value = Double.Parse(line[line.Length - 1].Replace(',', '.'), System.Globalization.CultureInfo.InvariantCulture);
                var    c     = new Configuration(temp);
                c.setMeasuredValue(GlobalState.currentNFP, value);
                result.Add(c);
            }
            sr.Close();
            return(result);
        }
        //get one variant per feature multiplied with alternative combinations; the variant tries to maximize the number of selected features, but without the feature in question
        /// <summary>
        /// 
        /// </summary>
        /// <param name="vm"></param>
        /// <returns></returns>
        public List<List<BinaryOption>> generateNegativeFW(VariabilityModel vm)
        {
            this.configurations.Clear();
            List<List<BinaryOption>> maxConfigs = new List<List<BinaryOption>>();

            maxConfigs = getMaxConfigurations(vm, false);
            configurations.AddRange(maxConfigs);
            //Idea try to vary only the first maximum configuration by removing only a single feature
            //If a feature is not present in this maximum configuration, find a maximum configuration in which it is present and then remove the feature
            //Challenges: alternative features or mandatory features cannot be removed
            foreach (BinaryOption binOpt in vm.BinaryOptions)
            {
                if (binOpt.Optional == false || binOpt.hasAlternatives())
                    continue;

                foreach (List<BinaryOption> config in maxConfigs)
                {
                    if (!config.Contains(binOpt))
                        continue;
                    List<BinaryOption> removedElements = null;
                    //Get a configuration without the feature based on the maximum configuration: config
                    List<BinaryOption> configToMeasure = generator.generateConfigWithoutOption(binOpt, config, out removedElements, vm);

                    if (configToMeasure == null)
                    {//This didn't work, let us try to use another maximum configuration
                        continue;
                    }
                    else
                    {
                        if (!Configuration.containsBinaryConfiguration(configurations,configToMeasure))
                            configurations.Add(configToMeasure);
                        break;
                    }

                }
            }
            return this.configurations;
        }
        /// <summary>
        /// Creates a configuration based on a hash representation of that configuration.
        /// </summary>
        /// <param name="hashString">The String which from which we can infer the configuration</param>
        /// <param name="vm">The variability model that is required for identifying options in the hash string to instantiate actual configuration options.</param>
        /// <returns>A configuration that maps to the given hash string.</returns>
        internal static Configuration createFromHashString(string hashString, VariabilityModel vm)
        {
            Dictionary <NumericOption, double> numOptions = new Dictionary <NumericOption, double>();
            List <BinaryOption> binaryFeatures            = new List <BinaryOption>();
            Configuration       c;

            String[] optionList = hashString.Split(new String[] { "%;%" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (String option in optionList)
            {
                if (Char.IsDigit(option[option.Length - 1]))//If last char is a digit, then it must be a numeric option
                {
                    //Now remove the digit from the name
                    int  index = option.Length - 1;
                    Char last  = option[index];

                    while (Char.IsDigit(last) || last == ',' || last == '.' || last == '-')
                    {
                        index--;
                        last = option[index];
                    }
                    Double        optionsValue = Math.Round(Double.Parse(option.Substring(index + 1).Replace(',', '.')), 1);
                    NumericOption no           = vm.getNumericOption(option.Substring(0, index + 1));
                    if (no == null)
                    {
                        continue;
                    }
                    numOptions.Add(no, optionsValue);
                }
                else
                {
                    BinaryOption binOpt = vm.getBinaryOption(option);
                    binaryFeatures.Add(binOpt);
                }
            }
            c = new Configuration(binaryFeatures, numOptions);
            return(c);
        }
        /// <summary>
        /// This method reads all configurations specified in the .csv file. In this mehtod, we assume that the file has a header. 
        /// </summary>
        /// <param name="file"></param>
        /// <param name="model">The variabiliy model for the configurations.</param>
        /// <returns>A list of all configurations </returns>
        public static List<Configuration> readConfigurations_Header_CSV(String file, VariabilityModel model)
        {
            List<Configuration> configurations = new List<Configuration>();

            StreamReader sr = new StreamReader(file);

            String[] optionOrder = new String[model.getOptions().Count - 1];
            String[] nfpOrder = null;

            bool isHeader = true;

            while(!sr.EndOfStream)
            {
                String[] tokens = sr.ReadLine().Split(';');

                if (isHeader)
                {
                    nfpOrder = new String[tokens.Length - optionOrder.Length];
                    for (int i = 0; i < tokens.Length; i++)
                    {
                        String token = tokens[i];
                        if (i < optionOrder.Length)
                        {
                            optionOrder[i] = token;
                        }
                        else
                        {
                            nfpOrder[i - optionOrder.Length] = token;
                            if (!GlobalState.nfProperties.ContainsKey(token))
                            {
                                GlobalState.nfProperties.Add(token, new NFProperty(token));
                            }
                        }
                    }
                    isHeader = false;
                }
                else
                {
                    Dictionary<BinaryOption, BinaryOption.BinaryValue> binOptions = new Dictionary<BinaryOption, BinaryOption.BinaryValue>();
                    Dictionary<NumericOption, double> numOptions = new Dictionary<NumericOption, double>();
                    Dictionary<NFProperty, double> properties = new Dictionary<NFProperty, double>();

                    for (int i = 0; i < tokens.Length; i++)
                    {
                        String token = tokens[i];
                        if (i < optionOrder.Length)
                        {
                            ConfigurationOption option = model.getOption(optionOrder[i]);
                            if (option.GetType() == typeof(BinaryOption))
                            {
                                if (token.Equals("true") || token.Equals("1"))
                                    binOptions.Add((BinaryOption)option, BinaryOption.BinaryValue.Selected);
                                else
                                    binOptions.Add((BinaryOption)option, BinaryOption.BinaryValue.Deselected);
                            }
                            else
                            {
                                double value = Convert.ToDouble(token);
                                numOptions.Add((NumericOption)option, value);
                            }
                        }
                        else
                        {
                            NFProperty nfp = GlobalState.nfProperties[nfpOrder[i - optionOrder.Length]];
                            double value = Convert.ToDouble(token);
                            properties.Add(nfp, value);

                            double currentMaxMeasuredValue;
                            if (GlobalState.allMeasurements.maxMeasuredValue.TryGetValue(nfp, out currentMaxMeasuredValue))
                            {
                                if (Math.Abs(value) > Math.Abs(currentMaxMeasuredValue))
                                {
                                    GlobalState.allMeasurements.maxMeasuredValue[nfp] = value;
                                }
                            }
                            else
                            {
                                GlobalState.allMeasurements.maxMeasuredValue.Add(nfp, value);
                            }

                        }

                    }

                    Configuration config = new Configuration(binOptions, numOptions, properties);
                    configurations.Add(config);
                }
            }
            sr.Close();
            return configurations;
        }
        /// <summary>
        /// This method returns a list of all configurations stored in a given file. All options of the configurations have to be defined in the variability model. 
        /// </summary>
        /// <param name="dat">Object representing the configuration file.</param>
        /// <param name="model">Variability model of the configurations.</param>
        /// <returns>Returns a list of configurations that were defined in the XML document. Can be an empty list.</returns>
        public static List<Configuration> readConfigurations(XmlDocument dat, VariabilityModel model)
        {
            XmlElement currentElemt = dat.DocumentElement;

            // Retrieve the decimal delimiter and the separator sign if included
            if (currentElemt.HasAttribute(decimalDelimiterTag) && currentElemt.HasAttribute(separatorTag))
            {
                // I assume that the decimal delimiter as well as the separator are only one symbol
                ConfigurationReader.decimalDelimiter = currentElemt.GetAttribute(decimalDelimiterTag)[0];
                ConfigurationReader.separator = currentElemt.GetAttribute(separatorTag)[0];

                if (currentElemt.GetAttribute(decimalDelimiterTag).Length > 1 || currentElemt.GetAttribute(separatorTag).Length > 1)
                {
                    GlobalState.logError.log("The decimal delimiter and the separator must consist of only one symbol.");
                }
                if (ConfigurationReader.decimalDelimiter == ConfigurationReader.separator)
                {
                    GlobalState.logError.log("The decimal delimiter symbol and the separator symbol must be different.");
                }
            }
            else if (currentElemt.HasAttribute(decimalDelimiterTag))
            {
                ConfigurationReader.decimalDelimiter = currentElemt.GetAttribute(decimalDelimiterTag)[0];
                if (currentElemt.GetAttribute(decimalDelimiterTag).Length > 1)
                {
                    GlobalState.logError.log("The decimal delimiter must consist of only one symbol.");
                }
            }
            else if (currentElemt.HasAttribute(separatorTag))
            {
                ConfigurationReader.separator = currentElemt.GetAttribute(separatorTag)[0];
                if (currentElemt.GetAttribute(separatorTag).Length > 1)
                {
                    GlobalState.logError.log("The separator symbol must be different.");
                }
            }

            HashSet<Configuration> configurations = new HashSet<Configuration>();

            int numberOfConfigs = currentElemt.ChildNodes.Count;
            int configsWithTooLargeDeviation = 0;
            foreach (XmlNode node in currentElemt.ChildNodes)
            {
                bool readMultipleMeasurements = false;
                if (node.Attributes.Count > 0 && node.Attributes[0].Value.ToLower() == "true")
                {
                    readMultipleMeasurements = true;
                }
                Dictionary<NFProperty, double> propertiesForConfig = new Dictionary<NFProperty, double>(); ;
                bool alternativeFormat = false;
                string binaryString = "";
                string numericString = "";
                string configID = "";
                Dictionary<NFProperty, double> measuredProperty = new Dictionary<NFProperty, double>();
                Configuration c = null;
                bool hasSetConfig = false;
                foreach (XmlNode childNode in node.ChildNodes)
                {
                    if (c == null && hasSetConfig)
                        continue;
                    switch (childNode.Attributes[0].Value)
                    {
                        // TODO we use this to support result files having the old structure
                        case "Configuration":
                            binaryString = childNode.InnerText;
                            break;
                        case "Variable Features":
                            numericString = childNode.InnerText;
                            break;

                        case "BinaryOptions":
                            binaryString = childNode.InnerText;
                            break;
                        case "NumericOptions":
                            numericString = childNode.InnerText;
                            break;
                        case "ConfigID":
                            if (readMultipleMeasurements)
                            {
                                configID = childNode.InnerText.Replace("_", "%;%");
                            }
                            else
                                configID = childNode.InnerText;
                            if (configID.Contains("%;%seek") && configID.Contains("%;%seek0") == false)
                            {
                                hasSetConfig = true;
                                c = null;
                                break;
                            }
                            alternativeFormat = true;
                            c = Configuration.createFromHashString(configID, GlobalState.varModel);
                            hasSetConfig = true;
                            break;
                        case "CompilerOptions":
                            //todo
                            break;
                        case "ConfigFileOptions":
                            //todo
                            break;
                        case "ParameterOptions":
                            //todo
                            break;
                        case "ProgramName":
                            //todo
                            break;
                        case "StartupBegin":
                            //todo
                            break;
                        case "StartupEnd":
                            //todo
                            break;
                        default:
                            NFProperty property = GlobalState.getOrCreateProperty(childNode.Attributes[0].Value);
                            double measuredValue = 0;
                            //-1 means that measurement failed... 3rd values strongly devigates in C.'s measurements, hence we use it only in case we have no other measurements
                            if (readMultipleMeasurements)
                            {
                                //if (property.Name != "run-real")
                                //    continue;
                                String[] m = childNode.InnerText.ToString().Split(separator);
                                double val1 = 0;
                                if (!Double.TryParse(m[0], out val1))
                                    break;
                                if (m.Length > 1)
                                {
                                    List<double> values = new List<double>();
                                    double avg = 0;
                                    foreach (var i in m)
                                    {
                                        double d = Convert.ToDouble(i.Replace(decimalDelimiter, '.'));
                                        if (d != -1)
                                        {
                                            values.Add(d);
                                            avg += d;
                                        }
                                    }
                                    if (values.Count == 0)
                                    {
                                        configsWithTooLargeDeviation++;
                                        c = null;
                                        break;
                                    }
                                    avg = avg / values.Count;
                                    /* foreach (var d in values)
                                        {
                                            if ((d / avg) * 100 > 10)
                                            {
                                                configsWithTooLargeDeviation++;
                                                c = null;
                                                break;
                                            }
                                        }*/
                                    measuredValue = avg;
                                    /*double val2 = Convert.ToDouble(m[1]);
                                        if (val1 == -1)
                                            measuredValue = val2;
                                        else if (val1 == -1 && val2 == -1)
                                            measuredValue = Convert.ToDouble(m[2]);
                                        else if (val2 == -1)
                                            measuredValue = val1;
                                        else
                                            measuredValue = (val1 + val2) / 2;*/
                                }
                                else
                                    measuredValue = val1;
                            }
                            else
                                measuredValue = Convert.ToDouble(childNode.InnerText.ToString().Replace(decimalDelimiter, '.'));

                            // Save the largest measured value.
                            double currentMaxMeasuredValue;
                            if (GlobalState.allMeasurements.maxMeasuredValue.TryGetValue(property, out currentMaxMeasuredValue))
                            {
                                if (Math.Abs(measuredValue) > Math.Abs(currentMaxMeasuredValue))
                                {
                                    GlobalState.allMeasurements.maxMeasuredValue[property] = measuredValue;
                                }
                            }
                            else
                            {
                                GlobalState.allMeasurements.maxMeasuredValue.Add(property, measuredValue);
                            }

                            // Add measured value to the configuration.
                            if (alternativeFormat && c != null)
                            {
                                c.setMeasuredValue(property, measuredValue);
                            }
                            else
                            {
                                measuredProperty.Add(property, measuredValue);
                            }
                            break;
                    }
                }

                if (alternativeFormat && c != null)
                {
                    if (configurations.Contains(c))
                    {
                        GlobalState.logError.logLine("Mutiple definition of one configuration in the configurations file:  " + c.ToString());
                    }
                    else
                    {
                        // if (GlobalState.currentNFP != null && c.nfpValues.Keys.Contains(GlobalState.currentNFP) && c.nfpValues[GlobalState.currentNFP] != -1)
                        configurations.Add(c);
                    }
                cont: { }
                    continue;
                }

                Dictionary<BinaryOption, BinaryOption.BinaryValue> binaryOptions = new Dictionary<BinaryOption, BinaryOption.BinaryValue>();

                string[] binaryOptionNames = binaryString.Split(',');
                foreach (string binaryOptionName in binaryOptionNames)
                {
                    string currOption = binaryOptionName.Trim();
                    if (currOption.Length > 0)
                    {
                        BinaryOption bOpt = null;

                        bOpt = model.getBinaryOption(currOption);

                        if (bOpt == null)
                            GlobalState.logError.logLine("No Binary option found with name: " + currOption);
                        binaryOptions.Add(bOpt, BinaryOption.BinaryValue.Selected);
                    }
                }

                // Add "root" binary option to the configuration
                if (!binaryOptions.ContainsKey(model.Root))
                    binaryOptions.Add(model.Root, BinaryOption.BinaryValue.Selected);

                Dictionary<NumericOption, double> numericOptions = new Dictionary<NumericOption, double>();
                if (!string.IsNullOrEmpty(numericString))
                {
                    string[] numOptionArray = numericString.Trim().Split(',');
                    foreach (string numOption in numOptionArray)
                    {
                        string[] numOptionsKeyValue;
                        if (numOption.Contains(";"))
                            numOptionsKeyValue = numOption.Split(';');
                        else
                            numOptionsKeyValue = numOption.Split(' ');// added for rc-lookahead 40
                        numOptionsKeyValue[0] = numOptionsKeyValue[0].Trim();
                        if (numOptionsKeyValue[0].Length == 0)
                            continue;
                        NumericOption varFeat = model.getNumericOption(numOptionsKeyValue[0]);
                        if (varFeat == null)
                            GlobalState.logError.logLine("No numeric option found with name: " + numOptionsKeyValue[0]);
                        double varFeatValue = Convert.ToDouble(numOptionsKeyValue[1]);

                        numericOptions.Add(varFeat, varFeatValue);
                    }
                }

                Configuration config = new Configuration(binaryOptions, numericOptions, measuredProperty);

                //if(configurations.Contains(config))
                //{
                //    GlobalState.logError.log("Mutiple definition of one configuration in the configurations file:  " + config.ToString());
                //}else
                //{
                configurations.Add(config);
                //}
            }
            GlobalState.logInfo.logLine("Configs with too large deviation: " + configsWithTooLargeDeviation);
            return configurations.ToList();
        }
 /// <summary>
 /// This method returns a list of all configurations stored in a given file. All options of the configurations have to be defined in the variability model.
 /// 
 /// If the file is a xml file, it should be structured as follows:
 /// 
 /// <![CDATA[ <results> ]]>
 /// <![CDATA[   <row> ]]>
 /// <![CDATA[       <data column="Configuration"> ]]>
 /// <![CDATA[           binaryOption1, binaryOption3,... ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Variable Features"> ]]>
 /// <![CDATA[           numOption1;64,numOption2;4 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Performance"> ]]>
 /// <![CDATA[           21.178 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[       <data column="Footprint"> ]]>
 /// <![CDATA[           1679 ]]>
 /// <![CDATA[       </data> ]]>
 /// <![CDATA[   </row> ]]>
 /// <![CDATA[   <row> ]]>
 /// <![CDATA[       <data column="Configuration"> ]]>
 /// <![CDATA[   .... ]]>
 /// <![CDATA[ <results> ]]>
 /// 
 ///
 /// If the file is a csv file, two different formats are supported. 
 /// 
 /// For the first on, the file should have a header: 
 /// 
 /// binaryOption1;numOption1;binaryOption2;numOption2;Performance;Footprint
 /// true;64;false;4;21.178;1679
 /// 
 /// Note: If a binary option is selected in a configuration, the value can either be "true" or "1".  
 /// 
 /// In the second format, no header is needed and only binary options are supported. Additionally, the measurements have to consider only one non-functional property.
 /// 
 /// </summary>
 /// <param name="file">Full qualified file name.</param>
 /// <param name="model">Variability model of the configurations.</param>
 /// <returns></returns>
 public static List<Configuration> readConfigurations(string file, VariabilityModel model)
 {
     if (file.EndsWith(".xml"))
     {
         XmlDocument dat = new System.Xml.XmlDocument();
         dat.Load(file);
         return readConfigurations(dat, model);
     }
     else
     {
         return readCSV(file, model);
     }
 }
        public VariabilityModel createVarModel()
        {
            VariabilityModel varMod = new VariabilityModel("testModel_1");

            // -------------------- BINARY OPTIONS ----------------
            BinaryOption binOp1 = new BinaryOption(varMod, "binOpt1");
            binOp1.Optional = false;
            binOp1.Prefix = "--";
            varMod.addConfigurationOption(binOp1);

            BinaryOption binOp2 = new BinaryOption(varMod, "binOpt2");
            binOp2.Optional = true;
            binOp2.Prefix = "-?";
            binOp2.Postfix = "kg";
            binOp2.Parent = binOp1;
            binOp2.OutputString = "binOpt2";
            varMod.addConfigurationOption(binOp2);

            BinaryOption binOp3 = new BinaryOption(varMod, "binOpt3");
            binOp3.Optional = true;
            binOp3.Prefix = "";
            binOp3.Postfix = "";
            binOp3.Parent = binOp1;
            List<List<ConfigurationOption>> exclude = new List<List<ConfigurationOption>>();
            List<ConfigurationOption> subExclude = new List<ConfigurationOption>();
            subExclude.Add(binOp2);
            exclude.Add(subExclude);
            binOp3.Excluded_Options = exclude;
            varMod.addConfigurationOption(binOp3);

            BinaryOption binOp4 = new BinaryOption(varMod, "binOpt4");
            binOp4.Optional = true;
            binOp4.Prefix = "4_";
            binOp4.Postfix = "_4";
            binOp4.Parent = binOp1;
            List<List<ConfigurationOption>> implied = new List<List<ConfigurationOption>>();
            List<ConfigurationOption> subimplied = new List<ConfigurationOption>();
            subimplied.Add(binOp2);
            implied.Add(subimplied);
            binOp4.Implied_Options = implied;
            varMod.addConfigurationOption(binOp4);

            // -------------------- NUMERIC OPTIONS ----------------

            NumericOption numOpt1 = new NumericOption(varMod, "numOpt1");
            numOpt1.DefaultValue = 0.0;
            numOpt1.Prefix = "num1-";
            numOpt1.Postfix = "--";
            numOpt1.Min_value = 0;
            numOpt1.Max_value = 10;
            numOpt1.StepFunction = new InfluenceFunction("n + 2");
            varMod.addConfigurationOption(numOpt1);

            NumericOption numOpt2 = new NumericOption(varMod, "numOpt2");
            numOpt2.DefaultValue = 0.8;
            numOpt2.Prefix = "";
            numOpt2.Postfix = "";
            numOpt2.Min_value = 0.1;
            numOpt2.Max_value = 5;
            numOpt2.StepFunction = new InfluenceFunction("n * 2");
            varMod.addConfigurationOption(numOpt2);

            return varMod;
        }
        /// <summary>
        /// Checks if the specified expression is compatible with the specified model.
        /// </summary>
        /// <param name="exp">Specified expression. Must not be null.</param>
        /// <param name="model">Specified variability model. Must not be null.</param>
        /// <returns>Returns true if expression and model are compatible else false</returns>
        private bool checkExpressionCompatibility(string exp, VariabilityModel model)
        {
            if (exp == null)
                throw new ArgumentNullException("Parameter exp must not be null!");
            if (model == null)
                throw new ArgumentNullException("Parameter model must not be null!");

            foreach (string prt in exp.Split(' '))
            {
                double d;

                if (!isOperator(prt) && prt != "log10(" && prt != ")"
                    && !double.TryParse(prt, out d)
                    && model.getOption(prt) == null)
                {
                    return false;
                }
            }

            return true;
        }
        private double getValueOfToken(Dictionary<NumericOption,double> config, string token, VariabilityModel varModel)
        {
            token = token.Trim();

            double value = 0.0;

            if (Double.TryParse(token, out value))
            {
                return value;
            }

            if (varModel == null)
            {
                if (token.Equals(this.numOption.Name))
                    return config[this.numOption];
            }
            else
            {
                NumericOption numOpt = varModel.getNumericOption(token);
                if (numOpt != null)
                    return (config[numOpt]);
            }
            return 0.0;
        }
        /// <summary>
        /// Parses the binary options, represented as string, of a configuration.
        /// </summary>
        /// <param name="binaryString">The string representation of the selected binary configuration options.</param>
        /// <param name="binaryOptions">The data strcutre containing the parsed binary options and their values.</param>
        /// <param name="varModel">The variability model the configuration is defined for.</param>
        /// <returns>True if the configuration is valid.</returns>
        private static bool parseBinaryOptionString(string binaryString, out Dictionary <BinaryOption, BinaryOption.BinaryValue> binaryOptions, VariabilityModel varModel)
        {
            bool valid = true;

            Dictionary <BinaryOption, BinaryOption.BinaryValue> _binaryOptions = new Dictionary <BinaryOption, BinaryOption.BinaryValue>();

            string[] binaryOptionNames = binaryString.Split(',');
            foreach (string binaryOptionName in binaryOptionNames)
            {
                string currOption = binaryOptionName.Trim();
                if (currOption.Length > 0)
                {
                    BinaryOption bOpt = null;

                    bOpt = varModel.getBinaryOption(currOption);

                    if (bOpt == null)
                    {
                        GlobalState.logError.logLine("No Binary option found with name: " + currOption);
                        valid = false;
                        break;
                    }
                    _binaryOptions.Add(bOpt, BinaryOption.BinaryValue.Selected);
                }
            }

            binaryOptions = _binaryOptions;

            return(valid);
        }
        /// <summary>
        /// This method reads all configurations specified in the .csv file. In this mehtod, we assume that the file has a header.
        /// </summary>
        /// <param name="file"></param>
        /// <param name="model">The variabiliy model for the configurations.</param>
        /// <returns>A list of all configurations </returns>
        public static List <Configuration> readConfigurations_Header_CSV(String file, VariabilityModel model)
        {
            List <Configuration> configurations = new List <Configuration>();

            StreamReader sr = new StreamReader(file);

            String[] optionOrder = new String[model.getOptions().Count];
            String[] nfpOrder    = null;

            bool isHeader = true;

            while (!sr.EndOfStream)
            {
                String[] tokens = sr.ReadLine().Split(';');

                if (isHeader)
                {
                    nfpOrder = new String[tokens.Length - optionOrder.Length];
                    for (int i = 0; i < tokens.Length; i++)
                    {
                        String token = tokens[i];
                        if (i < optionOrder.Length)
                        {
                            optionOrder[i] = token;
                        }
                        else
                        {
                            nfpOrder[i - optionOrder.Length] = token;
                            if (!GlobalState.nfProperties.ContainsKey(token))
                            {
                                GlobalState.nfProperties.Add(token, new NFProperty(token));
                            }
                        }
                    }
                    isHeader = false;
                }
                else
                {
                    Dictionary <BinaryOption, BinaryOption.BinaryValue> binOptions = new Dictionary <BinaryOption, BinaryOption.BinaryValue>();
                    Dictionary <NumericOption, double> numOptions = new Dictionary <NumericOption, double>();
                    Dictionary <NFProperty, double>    properties = new Dictionary <NFProperty, double>();

                    for (int i = 0; i < tokens.Length; i++)
                    {
                        String token = tokens[i];
                        if (i < optionOrder.Length)
                        {
                            ConfigurationOption option = model.getOption(optionOrder[i]);
                            if (option.GetType() == typeof(BinaryOption))
                            {
                                if (token.Equals("true") || token.Equals("1"))
                                {
                                    binOptions.Add((BinaryOption)option, BinaryOption.BinaryValue.Selected);
                                }
                            }
                            else
                            {
                                double value = Convert.ToDouble(token);
                                numOptions.Add((NumericOption)option, value);
                            }
                        }
                        else
                        {
                            NFProperty nfp   = GlobalState.nfProperties[nfpOrder[i - optionOrder.Length]];
                            double     value = Convert.ToDouble(token);
                            properties.Add(nfp, value);

                            double currentMaxMeasuredValue;
                            if (GlobalState.allMeasurements.maxMeasuredValue.TryGetValue(nfp, out currentMaxMeasuredValue))
                            {
                                if (Math.Abs(value) > Math.Abs(currentMaxMeasuredValue))
                                {
                                    GlobalState.allMeasurements.maxMeasuredValue[nfp] = value;
                                }
                            }
                            else
                            {
                                GlobalState.allMeasurements.maxMeasuredValue.Add(nfp, value);
                            }
                        }
                    }

                    Configuration config = new Configuration(binOptions, numOptions, properties);
                    configurations.Add(config);
                }
            }
            sr.Close();
            return(configurations);
        }
 //Two formats are possible: with header and 0,1s for binary selection or no header and giving the names of config options per per line (this excludex numeric options)
 private static List<Configuration> readCSV(string file, VariabilityModel model)
 {
     StreamReader sr = new StreamReader(file);
     String line1, line2;
     if (!sr.EndOfStream)
         line1 = sr.ReadLine();
     else return null;
     if (!sr.EndOfStream)
         line2 = sr.ReadLine();
     else
         return null;
     sr.Close();
     var l1 = line1.Split(';');
     var l2 = line2.Split(';');
     if (l1.Length < 2 || l2.Length < 2)
         return null;
     int d = 0;
     if (int.TryParse(l2[0], out d))
         return readConfigurations_Header_CSV(file, model);
     else
         return readCSVBinaryOptFormat(file, model);
 }
Esempio n. 43
0
 /// <summary>
 /// Creates a new feature by concartinating two given features with a multiplication.
 /// </summary>
 /// <param name="original">The first feature to concatinate.</param>
 /// <param name="toAdd">The second feature to concatinate.</param>
 /// <param name="vm">The variability model, the two features are defined for.</param>
 public Feature(Feature original, Feature toAdd, VariabilityModel vm)
     : base(original.getPureString() + " * " + toAdd.getPureString(), vm)
 {
     hashCode = initHashCode();
 }
        /// <summary>
        /// Sets all necessary information and initializes all components.
        /// </summary>
        /// <param name="exp">Loaded expression of the function. Must not be null.</param>
        /// <param name="model">Corresponding variability model of the expression.</param>
        private void loadComponents(string exp, VariabilityModel model)
        {
            if (exp == null)
                throw new ArgumentNullException("Parameter exp may not be null!");
            if (model != null && !checkExpressionCompatibility(exp, model))
            {
                MessageBox.Show(ERROR_EXP_MODEL_INCOMPATIBLE);
                return;
            }

            String optExpression = Regex.Replace(exp, @"\r\n?|\n", "");

            // Test if the loaded expression can be used
            try
            {
                new InfluenceFunction(optExpression);
            } catch
            {
                MessageBox.Show(ERROR_INVALID_EXP);
                return;
            }

            if (originalFunction == null)
                initializeOnce();

            modelLoaded = model != null;
            originalFunction = modelLoaded ? new InfluenceFunction(optExpression, model) : new InfluenceFunction(optExpression);
            currentModel = originalFunction.getVariabilityModel();

            adjustedExpressionTree = originalFunction.getExpressionTree();

            calculateOccurances();

            // Update readFunction-textbox
            getMaxAbstractConstant(originalFunction.ToString());
            updateFunctionTextBox(originalFunctionTextBox, sortExpression(originalFunction.ToString()));

            // Activating all components and returning their original state
            ilFunctionPanel.Scene = new ILScene();
            ilFunctionPanel.Refresh();

            initializeComponents();
            updateAdjustedFunction();
        }
        private bool tokenIsAFeatureOrNumber(string token, VariabilityModel varModel)
        {
            token = token.Trim();

            double value = 0.0;

            if (Double.TryParse(token, out value))
            {
                return true;
            }

            if (varModel != null)
            {
                NumericOption numOption = varModel.getNumericOption(token);
                if (numOption != null)
                {
                    if (!participatingNumOptions.Contains(numOption))
                        this.participatingNumOptions.Add(numOption);
                    numberOfParticipatingFeatures++;
                    return true;
                }

                BinaryOption binOption = varModel.getBinaryOption(token);
                if (binOption != null)
                {
                    if (!participatingBoolOptions.Contains(binOption))
                        this.participatingBoolOptions.Add(binOption);
                    numberOfParticipatingFeatures++;
                    return true;
                }
            }
            else
            {
                if(token.Equals(this.numOption.Name))
                    return true;
            }
            return false;
        }
        private static double getValueOfToken(Configuration config, string token, VariabilityModel fm)
        {
            token = token.Trim();

            double value = 0.0;

            if (Double.TryParse(token, out value))
            {
                return value;
            }

            NumericOption numOpt = fm.getNumericOption(token);
            if (numOpt != null)
            {
                return config.NumericOptions[numOpt];
            }
            BinaryOption binOpt = fm.getBinaryOption(token);
            if (binOpt != null)
            {
                if(token.Equals("base"))
                    return 1.0;

                if (config.BinaryOptions.Keys.Contains(binOpt) && config.BinaryOptions[binOpt] == BinaryOption.BinaryValue.Selected)
                    return 1.0;
                else
                {
                    foreach (BinaryOption option in config.BinaryOptions.Keys)
                    {
                        if (option.Name == binOpt.Name )
                        {
                            return 1.0;
                        }
                    }
                }

            }
            return 0.0;
        }
        /// <summary>
        /// This method searches for a corresponding methods in the dynamically loadeda assemblies and calls it if found. It prefers due to performance reasons the Microsoft Solver Foundation implementation.
        /// </summary>
        /// <param name="c">The configuration that needs to be checked.</param>
        /// <param name="vm">The variability model that represents the context of the configuration.</param>
        /// <returns>True if it is a valid selection w.r.t. the VM, false otherwise</returns>
        public bool checkConfigurationSAT(Configuration c, VariabilityModel vm)
        {
            foreach (Lazy<ICheckConfigSAT, ISolverType> solver in solvers)
            {
                if (solver.Metadata.SolverType.Equals("MSSolverFoundation")) return solver.Value.checkConfigurationSAT(c, vm);
            }

            //If not MS Solver, take any solver. Should be changed when supporting more than 2 solvers here
            foreach (Lazy<ICheckConfigSAT, ISolverType> solver in solvers)
            {
                return solver.Value.checkConfigurationSAT(c, vm);
            }

            return false;
        }
 /// <summary>
 /// Creates an influence function based on the expression. The variability model is used to identify binary and numeric
 /// configuration options. 
 /// </summary>
 /// <param name="expression">A function consisting of numbers, operators and configuration-option names.</param>
 /// <param name="varModel">The variability model of the configuration options.</param>
 public InfluenceFunction(string expression, VariabilityModel varModel)
 {
     this.varModel = varModel;
     parseExpressionToPolnishNotation(expression);
 }
        private static List<Configuration> readCSVBinaryOptFormat(string file, VariabilityModel model)
        {
            List<Configuration> result = new List<Configuration>();
            StreamReader sr = new StreamReader(file);
            while (!sr.EndOfStream)
            {
                var line = sr.ReadLine().Split(';');
                List<BinaryOption> temp = new List<BinaryOption>();
                for (int i = 0; i < line.Length - 1; i++)
                {
                    BinaryOption b = model.getBinaryOption(line[i]);
                    temp.Add(b);
                }
                double value = Double.Parse(line[line.Length - 1].Replace(',', '.'));
                var c = new Configuration(temp);
                c.setMeasuredValue(GlobalState.currentNFP, value);
                result.Add(c);

            }
            sr.Close();
            return result;
        }
        /// <summary>
        /// This method returns a list of all configurations stored in a given file. All options of the configurations have to be defined in the variability model.
        /// </summary>
        /// <param name="dat">Object representing the configuration file.</param>
        /// <param name="varModel">Variability model of the configurations.</param>
        /// <returns>Returns a list of configurations that were defined in the XML document. Can be an empty list.</returns>
        public static List <Configuration> readConfigurations(XmlDocument dat, VariabilityModel varModel)
        {
            XmlElement currentElemt = dat.DocumentElement;


            parseHeaderOfDocument(currentElemt);

            HashSet <Configuration> configurations = new HashSet <Configuration>();
            int configsWithTooLargeDeviation       = 0;

            foreach (XmlNode nodeOfOneConfiguration in currentElemt.ChildNodes)
            {
                bool readMultipleMeasurements = false;
                if (nodeOfOneConfiguration.Attributes.Count > 0 && nodeOfOneConfiguration.Attributes[0].Value.ToLower() == "true")
                {
                    readMultipleMeasurements = true;
                }
                Dictionary <NFProperty, double> propertiesForConfig = new Dictionary <NFProperty, double>();;
                bool   alternativeFormat = false;
                string binaryString      = "";
                string numericString     = "";
                string configID          = "";
                Dictionary <NFProperty, double> measuredProperty = new Dictionary <NFProperty, double>();
                Configuration c            = null;
                bool          hasSetConfig = false;
                foreach (XmlNode childNode in nodeOfOneConfiguration.ChildNodes)
                {
                    if (c == null && hasSetConfig)
                    {
                        continue;
                    }
                    switch (childNode.Attributes[0].Value)
                    {
                    // TODO we use this to support result files having the old structure
                    case "BinaryOptions":
                    case "Configuration":
                        binaryString = childNode.InnerText;
                        break;

                    case "NumericOptions":
                    case "Variable Features":
                        numericString = childNode.InnerText;
                        break;

                    case "ConfigID":
                        if (readMultipleMeasurements)
                        {
                            configID = childNode.InnerText.Replace("_", "%;%");
                        }
                        else
                        {
                            configID = childNode.InnerText;
                        }
                        if (configID.Contains("%;%seek") && configID.Contains("%;%seek0") == false)
                        {
                            hasSetConfig = true;
                            c            = null;
                            break;
                        }
                        alternativeFormat = true;
                        c            = Configuration.createFromHashString(configID, GlobalState.varModel);
                        hasSetConfig = true;
                        break;

                    default:
                        NFProperty property      = GlobalState.getOrCreateProperty(childNode.Attributes[0].Value);
                        double     measuredValue = 0;
                        //-1 means that measurement failed... 3rd values strongly devigates in C.'s measurements, hence we use it only in case we have no other measurements
                        if (readMultipleMeasurements)
                        {
                            //if (property.Name != "run-real")
                            //    continue;
                            String[] m    = childNode.InnerText.ToString().Split(separator);
                            double   val1 = 0;
                            if (!Double.TryParse(m[0], out val1))
                            {
                                break;
                            }
                            if (m.Length > 1)
                            {
                                List <double> values = new List <double>();
                                double        avg    = 0;
                                foreach (var i in m)
                                {
                                    double d = double.Parse(i.Replace(decimalDelimiter, '.'), System.Globalization.CultureInfo.InvariantCulture);
                                    if (d != -1)
                                    {
                                        values.Add(d);
                                        avg += d;
                                    }
                                }
                                if (values.Count == 0)
                                {
                                    configsWithTooLargeDeviation++;
                                    c = null;
                                    break;
                                }
                                avg = avg / values.Count;

                                /* foreach (var d in values)
                                 *  {
                                 *      if ((d / avg) * 100 > 10)
                                 *      {
                                 *          configsWithTooLargeDeviation++;
                                 *          c = null;
                                 *          break;
                                 *      }
                                 *  }*/
                                measuredValue = avg;

                                /*double val2 = Convert.ToDouble(m[1]);
                                 *  if (val1 == -1)
                                 *      measuredValue = val2;
                                 *  else if (val1 == -1 && val2 == -1)
                                 *      measuredValue = Convert.ToDouble(m[2]);
                                 *  else if (val2 == -1)
                                 *      measuredValue = val1;
                                 *  else
                                 *      measuredValue = (val1 + val2) / 2;*/
                            }
                            else
                            {
                                measuredValue = val1;
                            }
                        }
                        else
                        {
                            measuredValue = double.Parse(childNode.InnerText.ToString().Replace(decimalDelimiter, '.'), System.Globalization.CultureInfo.InvariantCulture);
                        }
                        // TODO how to handle configurations with negative nfps?
                        if (measuredValue < 0)
                        {
                            goto nextConfig;
                        }

                        // Save the largest measured value.
                        double currentMaxMeasuredValue;
                        if (GlobalState.allMeasurements.maxMeasuredValue.TryGetValue(property, out currentMaxMeasuredValue))
                        {
                            if (Math.Abs(measuredValue) > Math.Abs(currentMaxMeasuredValue))
                            {
                                GlobalState.allMeasurements.maxMeasuredValue[property] = measuredValue;
                            }
                        }
                        else
                        {
                            GlobalState.allMeasurements.maxMeasuredValue.Add(property, measuredValue);
                        }

                        // Add measured value to the configuration.
                        if (alternativeFormat && c != null)
                        {
                            c.setMeasuredValue(property, measuredValue);
                        }
                        else
                        {
                            measuredProperty.Add(property, measuredValue);
                        }
                        break;
                    }
                }

                if (alternativeFormat && c != null)
                {
                    if (configurations.Contains(c))
                    {
                        GlobalState.logError.logLine("Mutiple definition of one configuration in the configurations file:  " + c.ToString());
                    }
                    else
                    {
                        // if (GlobalState.currentNFP != null && c.nfpValues.Keys.Contains(GlobalState.currentNFP) && c.nfpValues[GlobalState.currentNFP] != -1)
                        configurations.Add(c);
                    }
                    continue;
                }

                // indicates if this configuration is valid in the current feature model
                bool valid = true;

                // parse the binary options string
                Dictionary <BinaryOption, BinaryOption.BinaryValue> binaryOptions = new Dictionary <BinaryOption, BinaryOption.BinaryValue>();
                valid &= parseBinaryOptionString(binaryString, out binaryOptions, varModel);

                // parse the numeric options string
                Dictionary <NumericOption, double> numericOptions = new Dictionary <NumericOption, double>();
                valid &= parseNumericOptionString(numericString, out numericOptions, varModel);

                // Add "root" binary option to the configuration
                if (!binaryOptions.ContainsKey(varModel.Root))
                {
                    binaryOptions.Add(varModel.Root, BinaryOption.BinaryValue.Selected);
                }


                if (valid)
                {
                    Configuration config = new Configuration(binaryOptions, numericOptions, measuredProperty);
                    configurations.Add(config);
                }
                else
                {
                    GlobalState.logError.logLine("Invalid configuration:" + binaryString + numericString);
                }
                nextConfig : { }
            }

            GlobalState.logInfo.logLine("Configs with too large deviation: " + configsWithTooLargeDeviation);
            return(configurations.ToList());
        }
Esempio n. 51
0
 /// <summary>
 /// Creates a new feature based on the given expression.
 /// </summary>
 /// <param name="expression">The string represenation of the feature.</param>
 /// <param name="vm">The variability model the expression is defined for.</param>
 public Feature(String expression, VariabilityModel vm) : base(expression, vm)
 {
     hashCode = initHashCode();
 }
        private VariabilityModel extractFeatureModelFromExpression(String expression)
        {
            VariabilityModel varModel = new VariabilityModel("TEMP");

            string[] parts = expression.Split(new char[] { '+', '*', '[', ']' });

            double value = 0.0;
            for (int i = 0; i < parts.Length;i++)
            {
                string part = parts[i].Trim();
                if (part.Length > 0)
                {
                    if (!Double.TryParse(part, out value))
                    {
                        if (varModel.getNumericOption(part) == null)
                        {
                            NumericOption option = new NumericOption(varModel, part);
                            varModel.addConfigurationOption(option);
                        }
                    }
                }
            }
            return varModel;
        }
        /// <summary>
        /// Parses the numeric options, represented as string, of a configuration.
        /// </summary>
        /// <param name="numericString">The string representation of the numeric configuration options.</param>
        /// <param name="numericOptions">The data strcutre containing the parsed numeric options and their values.</param>
        /// <param name="varModel">The variability model the configuration is defined for.</param>
        /// <returns>True if the configuration is valid</returns>
        private static bool parseNumericOptionString(string numericString, out Dictionary <NumericOption, double> numericOptions, VariabilityModel varModel)
        {
            bool valid = true;

            Dictionary <NumericOption, double> _numericOptions = new Dictionary <NumericOption, double>();

            if (!string.IsNullOrEmpty(numericString))
            {
                string[] numOptionArray = numericString.Trim().Split(',');
                foreach (string numOption in numOptionArray)
                {
                    if (!valid)
                    {
                        break;
                    }

                    string[] numOptionsKeyValue;
                    if (numOption.Contains(";"))
                    {
                        numOptionsKeyValue = numOption.Split(';');
                    }
                    else
                    {
                        numOptionsKeyValue = numOption.Split(' ');// added for rc-lookahead 40
                    }
                    numOptionsKeyValue[0] = numOptionsKeyValue[0].Trim();
                    if (numOptionsKeyValue[0].Length == 0)
                    {
                        continue;
                    }
                    NumericOption varFeat = varModel.getNumericOption(numOptionsKeyValue[0]);
                    if (varFeat == null)
                    {
                        GlobalState.logError.logLine("No numeric option found with name: " + numOptionsKeyValue[0]);
                        valid = false;
                    }
                    else
                    {
                        double varFeatValue = Convert.ToDouble(numOptionsKeyValue[1]);
                        _numericOptions.Add(varFeat, varFeatValue);
                    }
                }
            }

            numericOptions = _numericOptions;

            return(valid);
        }
 /// <summary>
 /// Creates a numeric option based on the information of the given XML Node (calls base function)
 /// </summary>
 /// <param name="numOptNode">The XML Element containing the information</param>
 /// <param name="variabilityModel">The variability model to which the option belongs to</param>
 /// <returns>The newly created option</returns>
 internal static ConfigurationOption loadFromXML(XmlElement numOptNode, VariabilityModel variabilityModel)
 {
     NumericOption numOpt = new NumericOption(variabilityModel, "temp");
     numOpt.loadFromXML(numOptNode);
     return numOpt;
 }
        /// <summary>
        /// Generates a constraint system based on a variability model. The constraint system can be used to check for satisfiability of configurations as well as optimization.
        /// </summary>
        /// <param name="variables">Empty input, outputs a list of CSP terms that correspond to the configuration options of the variability model</param>
        /// <param name="optionToTerm">A map to get for a given configuration option the corresponding CSP term of the constraint system</param>
        /// <param name="termToOption">A map that gives for a given CSP term the corresponding configuration option of the variability model</param>
        /// <param name="vm">The variability model for which we generate a constraint system</param>
        /// <returns>The generated constraint system consisting of logical terms representing configuration options as well as their boolean constraints.</returns>
        internal static ConstraintSystem getConstraintSystem(out List<CspTerm> variables, out Dictionary<BinaryOption, CspTerm> optionToTerm, out Dictionary<CspTerm, BinaryOption> termToOption, VariabilityModel vm)
        {
            //Reusing seems to not work correctely. The problem: configurations are realized as additional constraints for the system.
            //however, when checking for the next config, the old config's constraints remain in the solver such that we have a wrong result.
            /*
            if (csystem != null && variables_global != null && optionToTerm_global != null && termToOption_global != null && vm != null)
            {//For optimization purpose
                if (vm.BinaryOptions.Count == vm_global.BinaryOptions.Count && vm.Name.Equals(vm_global.Name))
                {
                    variables = variables_global;
                    optionToTerm = optionToTerm_global;
                    termToOption = termToOption_global;
                    return csystem;
                }
            }*/

            ConstraintSystem S = ConstraintSystem.CreateSolver();

            optionToTerm = new Dictionary<BinaryOption, CspTerm>();
            termToOption = new Dictionary<CspTerm, BinaryOption>();
            variables = new List<CspTerm>();
            foreach (BinaryOption binOpt in vm.BinaryOptions)
            {
                CspDomain domain = S.DefaultBoolean;
                CspTerm temp = S.CreateVariable(domain, binOpt);
                optionToTerm.Add(binOpt, temp);
                termToOption.Add(temp, binOpt);
                variables.Add(temp);
            }

            List<List<ConfigurationOption>> alreadyHandledAlternativeOptions = new List<List<ConfigurationOption>>();

            //Constraints of a single configuration option
            foreach (BinaryOption current in vm.BinaryOptions)
            {
                CspTerm cT = optionToTerm[current];
                if (current.Parent == null || current.Parent == vm.Root)
                {
                    if (current.Optional == false && current.Excluded_Options.Count == 0)
                        S.AddConstraints(S.Implies(S.True, cT));
                    else
                        S.AddConstraints(S.Implies(cT, optionToTerm[vm.Root]));
                }

                if (current.Parent != null && current.Parent != vm.Root)
                {
                    CspTerm parent = optionToTerm[(BinaryOption)current.Parent];
                    S.AddConstraints(S.Implies(cT, parent));
                    if (current.Optional == false && current.Excluded_Options.Count == 0)
                        S.AddConstraints(S.Implies(parent, cT));//mandatory child relationship
                }

                //Alternative or other exclusion constraints
                if (current.Excluded_Options.Count > 0)
                {
                    List<ConfigurationOption> alternativeOptions = current.collectAlternativeOptions();
                    if (alternativeOptions.Count > 0)
                    {
                        //Check whether we handled this group of alternatives already
                        foreach (var alternativeGroup in alreadyHandledAlternativeOptions)
                            foreach (var alternative in alternativeGroup)
                                if (current == alternative)
                                    goto handledAlternative;

                        //It is not allowed that an alternative group has no parent element
                        CspTerm parent = null;
                        if (current.Parent == null)
                            parent = S.True;
                        else
                            parent = optionToTerm[(BinaryOption)current.Parent];

                        CspTerm[] terms = new CspTerm[alternativeOptions.Count + 1];
                        terms[0] = cT;
                        int i = 1;
                        foreach (BinaryOption altEle in alternativeOptions)
                        {
                            CspTerm temp = optionToTerm[altEle];
                            terms[i] = temp;
                            i++;
                        }
                        S.AddConstraints(S.Implies(parent, S.ExactlyMofN(1, terms)));
                        alreadyHandledAlternativeOptions.Add(alternativeOptions);
                        handledAlternative: { }
                    }

                    //Excluded option(s) as cross-tree constraint(s)
                    List<List<ConfigurationOption>> nonAlternative = current.getNonAlternativeExlcudedOptions();
                    if(nonAlternative.Count > 0) {
                        foreach(var excludedOption in nonAlternative){
                            CspTerm[] orTerm = new CspTerm[excludedOption.Count];
                            int i = 0;
                            foreach (var opt in excludedOption)
                            {
                                CspTerm target = optionToTerm[(BinaryOption)opt];
                                orTerm[i] = target;
                                i++;
                            }
                            S.AddConstraints(S.Implies(cT, S.Not(S.Or(orTerm))));
                        }
                    }
                }
                //Handle implies
                if (current.Implied_Options.Count > 0)
                {
                    foreach (List<ConfigurationOption> impliedOr in current.Implied_Options)
                    {
                        CspTerm[] orTerms = new CspTerm[impliedOr.Count];
                        //Possible error: if a binary option impies a numeric option
                        for (int i = 0; i < impliedOr.Count; i++)
                            orTerms[i] = optionToTerm[(BinaryOption)impliedOr.ElementAt(i)];
                        S.AddConstraints(S.Implies(optionToTerm[current], S.Or(orTerms)));
                    }
                }
            }

            //Handle global cross-tree constraints involving multiple options at a time
            // the constraints should be in conjunctive normal form
            foreach (string constraint in vm.BooleanConstraints)
            {
                bool and = false;
                string[] terms;
                if (constraint.Contains("&"))
                {
                    and = true;
                    terms = constraint.Split('&');
                }
                else
                    terms = constraint.Split('|');

                CspTerm[] cspTerms = new CspTerm[terms.Count()];
                int i = 0;
                foreach (string t in terms)
                {
                    string optName = t.Trim();
                    if (optName.StartsWith("-") || optName.StartsWith("!"))
                    {
                        optName = optName.Substring(1);
                        BinaryOption binOpt = vm.getBinaryOption(optName);
                        CspTerm cspElem = optionToTerm[binOpt];
                        CspTerm notCspElem = S.Not(cspElem);
                        cspTerms[i] = notCspElem;
                    }
                    else
                    {
                        BinaryOption binOpt = vm.getBinaryOption(optName);
                        CspTerm cspElem = optionToTerm[binOpt];
                        cspTerms[i] = cspElem;
                    }
                    i++;
                }
                if (and)
                    S.AddConstraints(S.And(cspTerms));
                else
                    S.AddConstraints(S.Or(cspTerms));
            }
            csystem = S;
            optionToTerm_global = optionToTerm;
            vm_global = vm;
            termToOption_global = termToOption;
            variables_global = variables;
            return S;
        }
 public void saveVarModel(VariabilityModel varMod)
 {
     varMod.saveXML(@"D:\SPLConquerorGitHub\\SPLConqueror\ExampleFiles\foo.xml");
 }
Esempio n. 57
0
 /// <summary>
 /// Constructor to create a new numeric option. All values are set to zero (calls basic constructor)
 /// </summary>
 /// <param name="vm">The variability model to which the option belongs to</param>
 /// <param name="name">Name of that option</param>
 public NumericOption(VariabilityModel vm, String name)
     : base(vm, name)
 {
     this.Optional = false;
 }
 /// <summary>
 /// Constructor to create a new numeric option. All values are set to zero (calls basic constructor)
 /// </summary>
 /// <param name="vm">The variability model to which the option belongs to</param>
 /// <param name="name">Name of that option</param>
 public NumericOption(VariabilityModel vm, String name)
     : base(vm, name)
 {
 }
 /// <summary>
 /// Static method that reads an xml file and constructs a variability model using the stored information
 /// </summary>
 /// <param name="path">Path to the XML File</param>
 /// <returns>The instantiated variability model or null if there is no variability model at the path or if the model could not be parsed.</returns>
 public static VariabilityModel loadFromXML(String path)
 {
     VariabilityModel vm = new VariabilityModel("temp");
     if (vm.loadXML(path))
         return vm;
     else
         return null;
 }
 /// <summary>
 /// Creates an influence function based on the expression. All token wich are neither number nor operators are considered to be 
 /// numeric configuration options. 
 /// </summary>
 /// <param name="expression">A function consisting of numbers, operators and configuration-option names.</param>
 public InfluenceFunction(String expression)
 {
     this.varModel = extractFeatureModelFromExpression(createWellFormedExpression(expression));
     parseExpressionToPolnishNotation(expression);
 }