/// <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);
        }
Esempio n. 2
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);
        }
 private void replicateOption(BinaryOption original, BinaryOption replication)
 {
     replication.Optional     = original.Optional;
     replication.OutputString = original.OutputString;
     replication.Postfix      = original.Postfix;
     replication.Prefix       = original.Prefix;
 }
        /// <summary>
        /// Creastes a new variability model with a given name that consists only of a binary root option.
        /// </summary>
        /// <param name="name">The name of the variability model.</param>

        public VariabilityModel(String name)
        {
            this.name = name;
            if (root == null)
            {
                root = new BinaryOption(this, "root");
            }
            this.BinaryOptions.Add(root);
        }
 private void loadBinaryOptions(XmlElement xmlNode)
 {
     foreach (XmlElement binOptNode in xmlNode.ChildNodes)
     {
         if (!addConfigurationOption(BinaryOption.loadFromXML(binOptNode, this)))
         {
             GlobalState.logError.logLine("Could not add option to the variability model. Possible reasons: invalid name, option already exists.");
         }
     }
 }
Esempio n. 6
0
        private BinaryOption getOrCreateDisabled()
        {
            if (this.abstractDisabled == null)
            {
                abstractDisabled = new BinaryOption(base.vm, "Disabled" + this.Name);
                abstractDisabled.IsStrictlyAbstract = true;
            }

            return(abstractDisabled);
        }
Esempio n. 7
0
        private BinaryOption getOrCreateEnabled()
        {
            if (this.abstractEnabled == null)
            {
                abstractEnabled = new BinaryOption(base.vm, "Enabled" + this.Name);
                abstractEnabled.IsStrictlyAbstract = true;
                abstractEnabled.Optional           = true;
                abstractEnabled.Parent             = vm.Root;
                base.vm.AbrstactOptions.Add(abstractEnabled);
            }

            return(abstractEnabled);
        }
Esempio n. 8
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. 9
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);
        }
Esempio n. 10
0
 /// <summary>
 /// Set optional value of the configuration option.
 /// </summary>
 /// <param name="optional">Boolean that indicates the optionality of this option.</param>
 /// <param name="flag">The flag that indicates that this option was deselected.
 /// Only required when setting the option to optional.</param>
 public void setOptional(bool optional, int flag = -1)
 {
     this.Optional = optional;
     if (optional)
     {
         this.OptionalFlag = flag;
         getOrCreateEnabled();
         getOrCreateDisabled();
     }
     else
     {
         base.vm.AbrstactOptions.Remove(abstractEnabled);
         this.abstractEnabled  = null;
         this.abstractDisabled = null;
     }
 }
Esempio n. 11
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);
        }
 private void setParent(BinaryOption current, BinaryOption previous, int currentDepth, int prevDepth)
 {
     if (currentDepth - 1 == prevDepth)
     {
         current.ParentName = previous.Name;
         current.Parent     = previous;
     }
     else
     {
         BinaryOption tempParent = previous;
         while (prevDepth > currentDepth - 1)
         {
             tempParent = (BinaryOption)tempParent.Parent;
             prevDepth--;
         }
         current.ParentName = tempParent.Name;
         current.Parent     = tempParent;
     }
 }
Esempio n. 13
0
        internal bool containsParent(InfluenceFunction featureToAdd)
        {
            foreach (BinaryOption binOpt in featureToAdd.participatingBoolOptions)
            {
                if (this.participatingBoolOptions.Contains(binOpt))
                {
                    return(true);
                }
                BinaryOption parent = (BinaryOption)binOpt.Parent;
                while (parent != null && parent != varModel.Root)
                {
                    if (this.participatingBoolOptions.Contains(parent))
                    {
                        return(true);
                    }
                    parent = (BinaryOption)parent.Parent;
                }
            }

            return(false);
        }
        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);
        }
        /// <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);
        }
Esempio n. 16
0
        /// <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     containsOptionalNumeric = model.NumericOptions.Any(opt => opt.Optional);
            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);

                                // Check if optional and set the appropriate flags.
                                if (containsOptionalNumeric && option.Optional)
                                {
                                    var          opt = (NumericOption)option;
                                    BinaryOption abstractEnabledOpt  = opt.abstractEnabledConfigurationOption();
                                    BinaryOption abstractDisabledOpt = opt.abstractDisabledConfigurationOption();
                                    if (opt.OptionalFlag == value)
                                    {
                                        binOptions.Add(abstractEnabledOpt, BinaryOption.BinaryValue.Deselected);
                                        binOptions.Add(abstractDisabledOpt, BinaryOption.BinaryValue.Selected);
                                    }
                                    else
                                    {
                                        binOptions.Add(abstractEnabledOpt, BinaryOption.BinaryValue.Selected);
                                        binOptions.Add(abstractDisabledOpt, BinaryOption.BinaryValue.Deselected);
                                    }
                                }
                            }
                        }
                        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);
        }
Esempio n. 17
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.
        /// </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;

            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(',');
                            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);
                                    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(',', '.'));
                        }
                        if (alternativeFormat && c != null)
                        {
                            c.setMeasuredValue(property, measuredValue);
                        }
                        else
                        {
                            measuredProperty.Add(property, measuredValue);
                        }
                        break;
                    }
                }

                if (alternativeFormat && c != null)
                {
                    if (configurations.Contains(c))
                    {
                        GlobalState.logError.log("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.log("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.log("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.log("Configs with too large deviation: " + configsWithTooLargeDeviation);
            return(configurations.ToList());
        }
        private void parseFeaturesSXFM(string[] features)
        {
            int                 previousDepth  = 0;
            BinaryOption        previousOption = null;
            string              cardinality    = null;
            List <BinaryOption> optionsInGroup = null;

            foreach (string feature in features)
            {
                int      currentDepth = getDepth(feature);
                string[] information  = splitWhiteSpaces(feature);

                if (feature.Contains(":r"))
                {
                    this.root.Name         = "root";
                    this.root.OutputString = information[1];
                    previousOption         = this.root;
                }
                else if (feature.Contains(":m"))
                {
                    BinaryOption mandatory = new BinaryOption(this, information[2]);
                    mandatory.Optional     = false;
                    mandatory.OutputString = information[1];
                    this.binaryOptions.Add(mandatory);

                    setParent(mandatory, previousOption, currentDepth, previousDepth);

                    previousOption = mandatory;
                }
                else if (feature.Contains(":o"))
                {
                    BinaryOption optional = new BinaryOption(this, information[2]);
                    optional.Optional     = true;
                    optional.OutputString = information[1];
                    this.binaryOptions.Add(optional);

                    setParent(optional, previousOption, currentDepth, previousDepth);

                    previousOption = optional;
                }
                else if (feature.Contains(":g"))
                {
                    if (optionsInGroup != null && optionsInGroup.Count > 0)
                    {
                        resolveGroup(optionsInGroup, cardinality);
                    }

                    optionsInGroup = null;
                    BinaryOption groupParent = new BinaryOption(this, information[2]);
                    groupParent.Optional     = false;
                    groupParent.OutputString = information[1];
                    this.binaryOptions.Add(groupParent);

                    cardinality = information[3];

                    setParent(groupParent, previousOption, currentDepth, previousDepth);

                    previousOption = groupParent;
                }
                else if (feature.Contains(":"))
                {
                    if (optionsInGroup == null)
                    {
                        optionsInGroup = new List <BinaryOption>();
                    }

                    BinaryOption mandatory = new BinaryOption(this, information[2]);
                    mandatory.Optional     = false;
                    mandatory.OutputString = information[1];
                    this.binaryOptions.Add(mandatory);

                    setParent(mandatory, previousOption, currentDepth, previousDepth);

                    optionsInGroup.Add(mandatory);
                    previousOption = mandatory;
                }

                previousDepth = currentDepth;
            }
            if (optionsInGroup != null && optionsInGroup.Count > 0)
            {
                resolveGroup(optionsInGroup, cardinality);
            }
        }
        /// <summary>
        /// Produce a reduced version of the variability model, containing only binary options
        /// and at least the considered options. Is a considered option, all parent option will be inlcuded.
        /// Constraints between options(alternative groups, implication etc), will be included if enough options
        /// are present to (e.g. both options for implications or at least 2 options in alternative groups).
        /// </summary>
        /// <param name="consideredOptions">The options that will be in the reduced model.</param>
        /// <returns>A reduced version of the model containing the considered options.</returns>
        public VariabilityModel reduce(List <BinaryOption> consideredOptions)
        {
            VariabilityModel reduced = new VariabilityModel(this.name);

            foreach (BinaryOption binOpt in consideredOptions)
            {
                BinaryOption child = new BinaryOption(reduced, binOpt.Name);
                replicateOption(binOpt, child);
                reduced.addConfigurationOption(child);
                BinaryOption parent       = (BinaryOption)binOpt.Parent;
                bool         parentExists = false;
                while ((parent != null && parent != this.root) && !parentExists)
                {
                    BinaryOption newParent = reduced.getBinaryOption(parent.Name);
                    if (newParent == null)
                    {
                        newParent = new BinaryOption(reduced, parent.Name);
                        replicateOption(parent, newParent);
                        reduced.addConfigurationOption(newParent);
                    }
                    else
                    {
                        parentExists = true;
                    }
                    child.Parent = newParent;
                    child        = newParent;
                    parent       = (BinaryOption)parent.Parent;
                }

                if (child.Parent == null)
                {
                    child.Parent = reduced.root;
                }
            }

            foreach (BinaryOption opt in consideredOptions)
            {
                List <List <ConfigurationOption> > impliedOptionsRepl = new List <List <ConfigurationOption> >();
                foreach (List <ConfigurationOption> implied in opt.Implied_Options)
                {
                    List <ConfigurationOption> implRepl = new List <ConfigurationOption>();

                    foreach (ConfigurationOption impliedOption in implied)
                    {
                        if (reduced.getOption(impliedOption.Name) != null)
                        {
                            implRepl.Add(reduced.getOption(impliedOption.Name));
                        }
                    }
                    impliedOptionsRepl.Add(implRepl);
                }

                reduced.getBinaryOption(opt.Name).Implied_Options = impliedOptionsRepl;

                List <List <ConfigurationOption> > excludedOptionsRepl = new List <List <ConfigurationOption> >();
                foreach (List <ConfigurationOption> excluded in opt.Excluded_Options)
                {
                    List <ConfigurationOption> exclRepl = new List <ConfigurationOption>();

                    foreach (ConfigurationOption excludedOption in excluded)
                    {
                        if (reduced.getOption(excludedOption.Name) != null)
                        {
                            exclRepl.Add(reduced.getOption(excludedOption.Name));
                        }
                    }
                    excludedOptionsRepl.Add(exclRepl);
                }

                reduced.getBinaryOption(opt.Name).Excluded_Options = excludedOptionsRepl;
            }

            return(reduced);
        }