/// <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 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; }
private void generatePowerSet(VariabilityModel vm, List <BinaryOption> candidates, int t, List <List <BinaryOption> > result, int index) { if (candidates.Count == t) { candidates = generator.minimizeConfig(candidates, vm, true, null); if (candidates.Count != 0) { result.Add(candidates); } return; } for (int i = index; i < GlobalState.varModel.BinaryOptions.Count; i++) { if (candidates.Count < t) { if (!candidates.Contains(GlobalState.varModel.BinaryOptions[i])) { List <BinaryOption> newCand = new List <BinaryOption>(); newCand.AddRange(candidates); newCand.Add(GlobalState.varModel.BinaryOptions[i]); if (newOptionIsValidForCandidate(candidates, GlobalState.varModel.BinaryOptions[i])) { generatePowerSet(vm, newCand, t, result, i + 1); } } } } return; }
public List <List <BinaryOption> > generateFeatureWiseUntilSeconds(VariabilityModel vm, int seconds) { var cts = new CancellationTokenSource(); var task = Task.Factory.StartNew(() => { #region task 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(AppDomain.CurrentDomain.BaseDirectory); //Solver.VariantGenerator generator = new Solver.VariantGenerator(AppDomain.CurrentDomain.BaseDirectory); Solver.VariantGenerator generator = new Solver.VariantGenerator(null); Solver.CheckConfigSAT checkSAT = new Solver.CheckConfigSAT(null); //Generating new configurations: one per option if (checkSAT.checkConfigurationSAT(firstLevelMandatoryFeatures, vm, true)) { this.configurations.Add(firstLevelMandatoryFeatures); } foreach (BinaryOption e in binOptions) { if (cts.IsCancellationRequested) { return(configurations); } 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, true)) { 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; } } Console.WriteLine("Found " + configurations.Count); return(this.configurations); #endregion }, cts.Token); if (Task.WaitAny(new[] { task }, TimeSpan.FromMilliseconds(seconds * 1000)) < 0) { cts.Cancel(); } return(configurations); }
/// <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, true)) { 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, true)) { 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); }
/// <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; }
/// <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) { 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); }