/// <summary> /// Generates all valid binary combinations of all binary configurations options in the given model /// </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) { List <List <BinaryOption> > configurations = new List <List <BinaryOption> >(); 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); ConstraintSolverSolution soln = S.Solve(); while (soln.HasFoundSolution) { List <BinaryOption> config = new List <BinaryOption>(); foreach (CspTerm cT in variables) { if (soln.GetIntegerValue(cT) == 1) { config.Add(termToElem[cT]); } } //THese should always be new configurations // if(!Configuration.containsBinaryConfiguration(configurations, config)) configurations.Add(config); soln.GetNext(); } return(configurations); }
/// <summary> /// The method aims at finding a configuration which is similar to the given configuration, but does not contain the optionToBeRemoved. If further options need to be removed from the given configuration, they are outputed in removedElements. /// Idea: Encode this as a CSP problem. We aim at finding a configuration that maximizes a goal. Each option of the given configuration gets a large value assigned. All other options of the variability model gets a negative value assigned. /// We will further create a boolean constraint that forbids selecting the optionToBeRemoved. Now, we find an optimal valid configuration. /// </summary> /// <param name="optionToBeRemoved">The binary configuration option that must not be part of the new configuration.</param> /// <param name="originalConfig">The configuration for which we want to find a similar one.</param> /// <param name="removedElements">If further options need to be removed from the given configuration to build a valid configuration, they are outputed in this list.</param> /// <param name="vm">The variability model containing all options and their constraints.</param> /// <returns>A configuration that is valid, similar to the original configuration and does not contain the optionToBeRemoved. Null if not configuration could be found.</returns> public List <BinaryOption> generateConfigWithoutOption(BinaryOption optionToBeRemoved, List <BinaryOption> originalConfig, out List <BinaryOption> removedElements, 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); removedElements = new List <BinaryOption>(); //Forbid the selection of this configuration option CspTerm optionToRemove = elemToTerm[optionToBeRemoved]; S.AddConstraints(S.Implies(S.True, S.Not(optionToRemove))); //Defining Goals CspTerm[] finalGoals = new CspTerm[variables.Count]; int r = 0; foreach (var term in variables) { if (originalConfig.Contains(termToElem[term])) { finalGoals[r] = term * -1000; //Since we minimize, we put a large negative value of an option that is within the original configuration to increase chances that the option gets selected again } else { finalGoals[r] = variables[r] * 10000;//Positive number will lead to a small chance that an option gets selected when it is not in the original configuration } r++; } S.TryAddMinimizationGoals(S.Sum(finalGoals)); ConstraintSolverSolution soln = S.Solve(); List <BinaryOption> tempConfig = new List <BinaryOption>(); if (soln.HasFoundSolution && soln.Quality == ConstraintSolverSolution.SolutionQuality.Optimal) { tempConfig.Clear(); foreach (CspTerm cT in variables) { if (soln.GetIntegerValue(cT) == 1) { tempConfig.Add(termToElem[cT]); } } //Adding the options that have been removed from the original configuration foreach (var opt in originalConfig) { if (!tempConfig.Contains(opt)) { removedElements.Add(opt); } } return(tempConfig); } return(null); }
/// <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="exact">Checks also the number of selected options such that it returns only true if exactly the given configuration is valid /// (e.g., if we need to select more features to get a valid config, it returns false if exact is set to true). /// <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 exact) { 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 (exact) { 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++; } } //Needs testing TODO if (count != config.Count && exact == true) { return(false); } return(true); } else { return(false); } }
private List <List <BinaryOption> > generateTilSize(int i1, int size, int timeout, VariabilityModel vm) { var foundSolutions = new List <List <BinaryOption> >(); 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); CspTerm t = S.ExactlyMofN(i1, variables.ToArray()); S.AddConstraints(new CspTerm[] { t }); var csp = new ConstraintSolverParams { TimeLimitMilliSec = timeout * 1000, }; ConstraintSolverSolution soln = S.Solve(csp); int counter = 0; while (soln.HasFoundSolution) { List <BinaryOption> tempConfig = ( from cT in variables where soln.GetIntegerValue(cT) == 1 select termToElem[cT]).ToList(); if (tempConfig.Contains(null)) { tempConfig.Remove(null); } foundSolutions.Add(tempConfig); counter++; if (counter == size) { break; } soln.GetNext(); } //Console.WriteLine(i1 + "\t" + foundSolutions.Count); return(foundSolutions); }
/* public List<List<string>> generateDimacsPseudoRandom(string[] lines,int features, int randomsize, BackgroundWorker worker) * { * var cts = new CancellationTokenSource(); * var erglist = new List<List<string>>(); * * var tasks = new Task[features]; * var mylock = new object(); * * for (var i = 0; i < features; i++) * { * var i1 = i; * tasks[i] = Task.Factory.StartNew(() => * { * Console.WriteLine("Starting: " + i1); * var sw = new Stopwatch(); * sw.Start(); * var result = generateDimacsSize(lines, i1, randomsize); * sw.Stop(); * Console.WriteLine("Done: " + i1 + "\tDuration: " + sw.ElapsedMilliseconds + "\tResults: " + result.Count); * return result; * * }, cts.Token).ContinueWith(task => * { * lock (mylock) * { * * erglist.AddRange(task.Result); * * Console.WriteLine("Added results: " + i1 + "\tResults now: " + erglist.Count); * counter++; * //worker.ReportProgress((int)(counter * 100.0f / (double)features), erglist.Count); * } * }); * * if (Task.WaitAny(new[] { tasks[i] }, TimeSpan.FromMilliseconds(60 * 1000)) < 0) * { * cts.Cancel(); * } * } * * Task.WaitAll(tasks); * * return erglist; * } */ /// <summary> /// Simulates a simple method to get valid configurations of binary options of a variability model. The randomness is simulated by the modulu value. /// We take only the modulu'th configuration into the result set based on the CSP solvers output. If modulu is larger than the number of valid variants, the result set is empty. /// </summary> /// <param name="vm">The variability model containing the binary options and their constraints.</param> /// <param name="treshold">Maximum number of configurations</param> /// <param name="modulu">Each configuration that is % modulu == 0 is taken to the result set. Can be less than the maximal (i.e. threshold) specified number of configurations.</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> > generateRandomVariants(VariabilityModel vm, int treshold, int modulu) { 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); List <List <BinaryOption> > erglist = new List <List <BinaryOption> >(); ConstraintSolverSolution soln = S.Solve(); int mod = 0; while (soln.HasFoundSolution) { mod++; if (mod % modulu != 0) { soln.GetNext(); continue; } List <BinaryOption> tempConfig = new List <BinaryOption>(); foreach (CspTerm cT in variables) { if (soln.GetIntegerValue(cT) == 1) { tempConfig.Add(termToElem[cT]); } } if (tempConfig.Contains(null)) { tempConfig.Remove(null); } erglist.Add(tempConfig); if (erglist.Count == treshold) { break; } soln.GetNext(); } return(erglist); }
public bool checkDimacsSAT(List <string> tempConfig, string[] lines) { var exact = false; List <CspTerm> variables = new List <CspTerm>(); Dictionary <string, CspTerm> elemToTerm = new Dictionary <string, CspTerm>(); Dictionary <CspTerm, string> termToElem = new Dictionary <CspTerm, string>(); var sys = CSPsolver.getDimacsCSystem(out variables, out elemToTerm, out termToElem, lines); foreach (var k in elemToTerm.Keys) { if (tempConfig.Contains(k)) { sys.Implies(sys.True, elemToTerm[k]); } } var sol = sys.Solve(); return(sol.HasFoundSolution); }
/// <summary> /// Based on a given (partial) configuration and a variability, we aim at finding all optimally maximal or minimal (in terms of selected binary options) configurations. /// </summary> /// <param name="config">The (partial) configuration which needs to be expaned to be valid.</param> /// <param name="vm">Variability model containing all options and their constraints.</param> /// <param name="minimize">If true, we search for the smallest (in terms of selected options) valid configuration. If false, we search for the largest one.</param> /// <param name="unwantedOptions">Binary options that we do not want to become part of the configuration. Might be part if there is no other valid configuration without them</param> /// <returns>A list of configurations that satisfies the VM and the goal (or null if there is none).</returns> public List <List <BinaryOption> > maximizeConfig(List <BinaryOption> config, VariabilityModel vm, bool minimize, List <BinaryOption> unwantedOptions) { 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 if (config != null) { foreach (BinaryOption binOpt in config) { CspTerm term = elemToTerm[binOpt]; S.AddConstraints(S.Implies(S.True, term)); } } //Defining Goals CspTerm[] finalGoals = new CspTerm[variables.Count]; for (int r = 0; r < variables.Count; r++) { if (minimize == true) { BinaryOption binOpt = termToElem[variables[r]]; if (unwantedOptions != null && (unwantedOptions.Contains(binOpt) && !config.Contains(binOpt))) { finalGoals[r] = variables[r] * 10000; } else { // Element is part of an altnerative Group ... we want to select always the same option of the group, so we give different weights to the member of the group //Functionality deactivated... todo needs further handling /*if (binOpt.getAlternatives().Count != 0) * { * finalGoals[r] = variables[r] * (binOpt.getID() * 10); * } * else * {*/ finalGoals[r] = variables[r] * 1; //} // wenn in einer alternative, dann bekommt es einen wert nach seiner reihenfolge // id mal 10 } } else { finalGoals[r] = variables[r] * -1; // dynamic cost map } } S.TryAddMinimizationGoals(S.Sum(finalGoals)); ConstraintSolverSolution soln = S.Solve(); List <string> erg2 = new List <string>(); List <BinaryOption> tempConfig = new List <BinaryOption>(); List <List <BinaryOption> > resultConfigs = new List <List <BinaryOption> >(); while (soln.HasFoundSolution && soln.Quality == ConstraintSolverSolution.SolutionQuality.Optimal) { tempConfig.Clear(); foreach (CspTerm cT in variables) { if (soln.GetIntegerValue(cT) == 1) { tempConfig.Add(termToElem[cT]); } } if (minimize && tempConfig != null) { resultConfigs.Add(tempConfig); break; } if (!Configuration.containsBinaryConfiguration(resultConfigs, tempConfig)) { resultConfigs.Add(tempConfig); } soln.GetNext(); } return(resultConfigs); }
/// <summary> /// Based on a given (partial) configuration and a variability, we aim at finding the smallest (or largest if minimize == false) valid configuration that has all options. /// </summary> /// <param name="config">The (partial) configuration which needs to be expaned to be valid.</param> /// <param name="vm">Variability model containing all options and their constraints</param> /// <param name="minimize">If true, we search for the smallest (in terms of selected options) valid configuration. If false, we search for the largest one.</param> /// <param name="unWantedOptions">Binary options that we do not want to become part of the configuration. Might be part if there is no other valid configuration without them.</param> /// <returns>The valid configuration (or null if there is none) that satisfies the VM and the goal.</returns> public List <BinaryOption> minimizeConfig(List <BinaryOption> config, VariabilityModel vm, bool minimize, List <BinaryOption> unWantedFeatures) { 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 binOpt in config) { CspTerm term = elemToTerm[binOpt]; S.AddConstraints(S.Implies(S.True, term)); } //Defining Goals CspTerm[] finalGoals = new CspTerm[variables.Count]; for (int r = 0; r < variables.Count; r++) { if (minimize == true) { if (unWantedFeatures != null && (unWantedFeatures.Contains(termToElem[variables[r]]) && !config.Contains(termToElem[variables[r]]))) { finalGoals[r] = variables[r] * 100; } else { finalGoals[r] = variables[r] * 1; } } else { finalGoals[r] = variables[r] * -1; // dynamic cost map } } S.TryAddMinimizationGoals(S.Sum(finalGoals)); ConstraintSolverSolution soln = S.Solve(); List <string> erg2 = new List <string>(); List <BinaryOption> tempConfig = new List <BinaryOption>(); while (soln.HasFoundSolution) { tempConfig.Clear(); foreach (CspTerm cT in variables) { if (soln.GetIntegerValue(cT) == 1) { tempConfig.Add(termToElem[cT]); } } if (minimize && tempConfig != null) { break; } soln.GetNext(); } return(tempConfig); }
public List <List <BinaryOption> > generateRandomVariantsUntilSeconds(VariabilityModel vm, int seconds, int treshold, int modulu) { List <List <BinaryOption> > erglist = new List <List <BinaryOption> >(); var cts = new CancellationTokenSource(); var task = Task.Factory.StartNew(() => { #region task 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); ConstraintSolverSolution soln = S.Solve(); int mod = 0; while (soln.HasFoundSolution) { if (cts.IsCancellationRequested) { return(erglist); } mod++; if (mod % modulu != 0) { soln.GetNext(); continue; } List <BinaryOption> tempConfig = new List <BinaryOption>(); foreach (CspTerm cT in variables) { if (soln.GetIntegerValue(cT) == 1) { tempConfig.Add(termToElem[cT]); } } if (tempConfig.Contains(null)) { tempConfig.Remove(null); } erglist.Add(tempConfig); if (erglist.Count == treshold) { break; } soln.GetNext(); } return(erglist); #endregion }, cts.Token); if (Task.WaitAny(new[] { task }, TimeSpan.FromMilliseconds(seconds * 1000)) < 0) { Console.WriteLine("configsize: " + erglist.Count); cts.Cancel(); return(erglist); } return(erglist); }