/// <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> /// 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."); } } }
private BinaryOption getOrCreateDisabled() { if (this.abstractDisabled == null) { abstractDisabled = new BinaryOption(base.vm, "Disabled" + this.Name); abstractDisabled.IsStrictlyAbstract = true; } return(abstractDisabled); }
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); }
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); }
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> /// 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; } }
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; } }
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); }
/// <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); }
/// <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); }