private void AddBinaryConfigurationsToConstraintSystem(VariabilityModel vm, ConstraintSystem s, Configuration configurationToExclude, Dictionary <BinaryOption, CspTerm> elemToTerm) { List <BinaryOption> allBinaryOptions = vm.BinaryOptions; List <CspTerm> positiveTerms = new List <CspTerm>(); List <CspTerm> negativeTerms = new List <CspTerm>(); foreach (BinaryOption binOpt in allBinaryOptions) { if (configurationToExclude.BinaryOptions.ContainsKey(binOpt) && configurationToExclude.BinaryOptions[binOpt] == BinaryOption.BinaryValue.Selected) { positiveTerms.Add(elemToTerm[binOpt]); } else { negativeTerms.Add(elemToTerm[binOpt]); } } if (negativeTerms.Count > 0) { positiveTerms.Add(s.Not(s.And(negativeTerms.ToArray()))); } s.AddConstraints(s.Not(s.And(positiveTerms.ToArray()))); }
static void Main(string[] args) { ConstraintSystem s1 = ConstraintSystem.CreateSolver(); // () and () CspTerm p1 = s1.CreateBoolean("p1"); CspTerm p2 = s1.CreateBoolean("p2"); CspTerm p3 = s1.CreateBoolean("p3"); CspTerm p4 = s1.CreateBoolean("p4"); var x = new CspDomain(); CspTerm test = s1.And(s1.Or(p1, s1.And(s1.Neg(p3)), s1.Neg(p1)), s1.And(p2, s1.Neg(s1.Difference(p1, p2)))); CspTerm tOr12 = s1.Or(s1.Neg(t1), s1.Neg(t2)); CspTerm tOr13 = s1.Or(s1.Neg(t1), s1.Neg(t3)); CspTerm tOr14 = s1.Or(s1.Neg(t1), s1.Neg(t4)); CspTerm tOr23 = s1.Or(s1.Neg(t2), s1.Neg(t3)); CspTerm tOr24 = s1.Or(s1.Neg(t2), s1.Neg(t4)); CspTerm tOr34 = s1.Or(s1.Neg(t3), s1.Neg(t4)); CspTerm tOr = s1.Or(t1, t2, t3, t4); s1.AddConstraints(tOr12); s1.AddConstraints(tOr13); s1.AddConstraints(tOr14); s1.AddConstraints(tOr23); s1.AddConstraints(tOr24); s1.AddConstraints(tOr34); s1.AddConstraints(tOr); ConstraintSolverSolution solution1 = s1.Solve(); if (solution1.HasFoundSolution) { Console.WriteLine("Is Satisfiable"); } else { Console.WriteLine("Not satisfiable"); } Console.ReadKey(); }
public override void AddConstaint() { ConstraintSystem solver = ConstraintSystemSolver.Instance.Solver; CspTerm constraint = null; CspTerm[] inputTerms = new CspTerm[Input.Count]; for (int i = 0; i < Input.Count; i++) { inputTerms[i] = Input[i].CspTerm; } CspTerm outputTerm = Output.CspTerm; Type consType = type; if (IsNotHealthy) { // In case the gate is Broken (Not Healthy) - we don't want to add any constraint!!! return; /* * switch (type) * { * case Type.and: * consType = Type.nand; * break; * case Type.nand: * consType = Type.and; * break; * case Type.or: * consType = Type.nor; * break; * case Type.nor: * consType = Type.or; * break; * case Type.xor: * consType = Type.nxor; * break; * case Type.nxor: * consType = Type.xor; * break; * } */ } lock (ConstraintSystemSolver.Instance.Locker) { //Debug.WriteLine("SAT IN!"); switch (consType) { case Type.and: CspTerm allAndInputs = solver.And(inputTerms); constraint = solver.Equal(allAndInputs, outputTerm); break; case Type.nand: CspTerm allNandInputs = solver.And(inputTerms); constraint = solver.Equal(allNandInputs, solver.Not(outputTerm)); break; case Type.nor: CspTerm allNorInputs = solver.Or(inputTerms); constraint = solver.Equal(allNorInputs, solver.Not(outputTerm)); break; case Type.or: CspTerm allOrInputs = solver.Or(inputTerms); constraint = solver.Equal(allOrInputs, outputTerm); break; case Type.xor: //XOR is also: //http://en.wikipedia.org/wiki/XOR_gate#/media/File:254px_3gate_XOR.jpg CspTerm firstNand = solver.Not(solver.And(inputTerms)); CspTerm firstOr = solver.Or(inputTerms); CspTerm secendAnd = solver.And(firstNand, firstOr); constraint = solver.Equal(secendAnd, outputTerm); break; case Type.nxor: //XOR is also: //http://en.wikipedia.org/wiki/XOR_gate#/media/File:254px_3gate_XOR.jpg CspTerm firstNand2 = solver.Not(solver.And(inputTerms)); CspTerm firstOr2 = solver.Or(inputTerms); CspTerm secendAnd2 = solver.And(firstNand2, firstOr2); constraint = solver.Equal(secendAnd2, solver.Not(outputTerm)); break; } solver.AddConstraints(constraint); //Debug.WriteLine("SAT OUT!"); } }
/// <summary> /// Generates a constraint system based on a variability model. The constraint system can be used to check for satisfiability of configurations as well as optimization. /// </summary> /// <param name="variables">Empty input, outputs a list of CSP terms that correspond to the configuration options of the variability model</param> /// <param name="optionToTerm">A map to get for a given configuration option the corresponding CSP term of the constraint system</param> /// <param name="termToOption">A map that gives for a given CSP term the corresponding configuration option of the variability model</param> /// <param name="vm">The variability model for which we generate a constraint system</param> /// <returns>The generated constraint system consisting of logical terms representing configuration options as well as their boolean constraints.</returns> internal static ConstraintSystem getConstraintSystem(out List <CspTerm> variables, out Dictionary <BinaryOption, CspTerm> optionToTerm, out Dictionary <CspTerm, BinaryOption> termToOption, VariabilityModel vm) { //Reusing seems to not work correctely. The problem: configurations are realized as additional constraints for the system. //however, when checking for the next config, the old config's constraints remain in the solver such that we have a wrong result. /* * if (csystem != null && variables_global != null && optionToTerm_global != null && termToOption_global != null && vm != null) * {//For optimization purpose * if (vm.BinaryOptions.Count == vm_global.BinaryOptions.Count && vm.Name.Equals(vm_global.Name)) * { * variables = variables_global; * optionToTerm = optionToTerm_global; * termToOption = termToOption_global; * return csystem; * } * }*/ ConstraintSystem S = ConstraintSystem.CreateSolver(); optionToTerm = new Dictionary <BinaryOption, CspTerm>(); termToOption = new Dictionary <CspTerm, BinaryOption>(); variables = new List <CspTerm>(); foreach (BinaryOption binOpt in vm.BinaryOptions) { CspDomain domain = S.DefaultBoolean; CspTerm temp = S.CreateVariable(domain, binOpt); optionToTerm.Add(binOpt, temp); termToOption.Add(temp, binOpt); variables.Add(temp); } List <List <ConfigurationOption> > alreadyHandledAlternativeOptions = new List <List <ConfigurationOption> >(); //Constraints of a single configuration option foreach (BinaryOption current in vm.BinaryOptions) { CspTerm cT = optionToTerm[current]; if (current.Parent == null || current.Parent == vm.Root) { if (current.Optional == false && current.Excluded_Options.Count == 0) { S.AddConstraints(S.Implies(S.True, cT)); } else { S.AddConstraints(S.Implies(cT, optionToTerm[vm.Root])); } } if (current.Parent != null && current.Parent != vm.Root) { CspTerm parent = optionToTerm[(BinaryOption)current.Parent]; S.AddConstraints(S.Implies(cT, parent)); if (current.Optional == false && current.Excluded_Options.Count == 0) { S.AddConstraints(S.Implies(parent, cT));//mandatory child relationship } } //Alternative or other exclusion constraints if (current.Excluded_Options.Count > 0) { List <ConfigurationOption> alternativeOptions = current.collectAlternativeOptions(); if (alternativeOptions.Count > 0) { //Check whether we handled this group of alternatives already foreach (var alternativeGroup in alreadyHandledAlternativeOptions) { foreach (var alternative in alternativeGroup) { if (current == alternative) { goto handledAlternative; } } } //It is not allowed that an alternative group has no parent element CspTerm parent = null; if (current.Parent == null) { parent = S.True; } else { parent = optionToTerm[(BinaryOption)current.Parent]; } CspTerm[] terms = new CspTerm[alternativeOptions.Count + 1]; terms[0] = cT; int i = 1; foreach (BinaryOption altEle in alternativeOptions) { CspTerm temp = optionToTerm[altEle]; terms[i] = temp; i++; } S.AddConstraints(S.Implies(parent, S.ExactlyMofN(1, terms))); alreadyHandledAlternativeOptions.Add(alternativeOptions); handledAlternative : { } } //Excluded option(s) as cross-tree constraint(s) List <List <ConfigurationOption> > nonAlternative = current.getNonAlternativeExlcudedOptions(); if (nonAlternative.Count > 0) { foreach (var excludedOption in nonAlternative) { CspTerm[] orTerm = new CspTerm[excludedOption.Count]; int i = 0; foreach (var opt in excludedOption) { CspTerm target = optionToTerm[(BinaryOption)opt]; orTerm[i] = target; i++; } S.AddConstraints(S.Implies(cT, S.Not(S.Or(orTerm)))); } } } //Handle implies if (current.Implied_Options.Count > 0) { foreach (List <ConfigurationOption> impliedOr in current.Implied_Options) { CspTerm[] orTerms = new CspTerm[impliedOr.Count]; //Possible error: if a binary option impies a numeric option for (int i = 0; i < impliedOr.Count; i++) { orTerms[i] = optionToTerm[(BinaryOption)impliedOr.ElementAt(i)]; } S.AddConstraints(S.Implies(optionToTerm[current], S.Or(orTerms))); } } } //Handle global cross-tree constraints involving multiple options at a time // the constraints should be in conjunctive normal form foreach (string constraint in vm.BinaryConstraints) { bool and = false; string[] terms; if (constraint.Contains("&")) { and = true; terms = constraint.Split('&'); } else { terms = constraint.Split('|'); } CspTerm[] cspTerms = new CspTerm[terms.Count()]; int i = 0; foreach (string t in terms) { string optName = t.Trim(); if (optName.StartsWith("-") || optName.StartsWith("!")) { optName = optName.Substring(1); BinaryOption binOpt = vm.getBinaryOption(optName); CspTerm cspElem = optionToTerm[binOpt]; CspTerm notCspElem = S.Not(cspElem); cspTerms[i] = notCspElem; } else { BinaryOption binOpt = vm.getBinaryOption(optName); CspTerm cspElem = optionToTerm[binOpt]; cspTerms[i] = cspElem; } i++; } if (and) { S.AddConstraints(S.And(cspTerms)); } else { S.AddConstraints(S.Or(cspTerms)); } } csystem = S; optionToTerm_global = optionToTerm; vm_global = vm; termToOption_global = termToOption; variables_global = variables; return(S); }
/// <summary> /// Generates a constraint system based on a variability model. The constraint system can be used to check for satisfiability of configurations as well as optimization. /// </summary> /// <param name="variables">Empty input, outputs a list of CSP terms that correspond to the configuration options of the variability model</param> /// <param name="optionToTerm">A map to get for a given configuration option the corresponding CSP term of the constraint system</param> /// <param name="termToOption">A map that gives for a given CSP term the corresponding configuration option of the variability model</param> /// <param name="vm">The variability model for which we generate a constraint system</param> /// <returns>The generated constraint system consisting of logical terms representing configuration options as well as their boolean constraints.</returns> internal static ConstraintSystem GetGeneralConstraintSystem(out Dictionary <CspTerm, bool> variables, out Dictionary <ConfigurationOption, CspTerm> optionToTerm, out Dictionary <CspTerm, ConfigurationOption> termToOption, VariabilityModel vm) { ConstraintSystem S = ConstraintSystem.CreateSolver(); optionToTerm = new Dictionary <ConfigurationOption, CspTerm>(); termToOption = new Dictionary <CspTerm, ConfigurationOption>(); variables = new Dictionary <CspTerm, bool>(); foreach (ConfigurationOption o in vm.getOptions()) { CspDomain binDomain = S.DefaultBoolean; CspTerm temp; if (o is BinaryOption) { temp = S.CreateVariable(binDomain, o); } else { NumericOption numOpt = (NumericOption)o; temp = S.CreateVariable(S.CreateIntegerInterval((int)numOpt.Min_value, (int)numOpt.Max_value), o); } optionToTerm.Add(o, temp); termToOption.Add(temp, o); if (o is NumericOption) { variables.Add(temp, false); } else { variables.Add(temp, true); } } List <List <ConfigurationOption> > alreadyHandledAlternativeOptions = new List <List <ConfigurationOption> >(); //Constraints of a single configuration option foreach (ConfigurationOption current in vm.getOptions()) { CspTerm cT = optionToTerm[current]; if (current.Parent == null || current.Parent == vm.Root) { if ((current is BinaryOption && ((BinaryOption)current).Optional == false && current.Excluded_Options.Count == 0)) { S.AddConstraints(S.Implies(S.True, cT)); } else { S.AddConstraints(S.Implies(cT, optionToTerm[vm.Root])); } } if (current.Parent != null && current.Parent != vm.Root) { CspTerm parent = optionToTerm[(BinaryOption)current.Parent]; S.AddConstraints(S.Implies(cT, parent)); if (current is BinaryOption && ((BinaryOption)current).Optional == false && current.Excluded_Options.Count == 0) { S.AddConstraints(S.Implies(parent, cT));//mandatory child relationship } } // Add numeric integer values if (current is NumericOption) { NumericOption numOpt = (NumericOption)current; List <double> values = numOpt.getAllValues(); List <CspTerm> equals = new List <CspTerm>(); foreach (double d in values) { equals.Add(S.Equal((int)d, cT)); } S.AddConstraints(S.Or(equals.ToArray())); } //Alternative or other exclusion constraints if (current.Excluded_Options.Count > 0 && current is BinaryOption) { BinaryOption binOpt = (BinaryOption)current; List <ConfigurationOption> alternativeOptions = binOpt.collectAlternativeOptions(); if (alternativeOptions.Count > 0) { //Check whether we handled this group of alternatives already foreach (var alternativeGroup in alreadyHandledAlternativeOptions) { foreach (var alternative in alternativeGroup) { if (current == alternative) { goto handledAlternative; } } } //It is not allowed that an alternative group has no parent element CspTerm parent = null; if (current.Parent == null) { parent = S.True; } else { parent = optionToTerm[(BinaryOption)current.Parent]; } CspTerm[] terms = new CspTerm[alternativeOptions.Count + 1]; terms[0] = cT; int i = 1; foreach (BinaryOption altEle in alternativeOptions) { CspTerm temp = optionToTerm[altEle]; terms[i] = temp; i++; } S.AddConstraints(S.Implies(parent, S.ExactlyMofN(1, terms))); alreadyHandledAlternativeOptions.Add(alternativeOptions); handledAlternative : { } } //Excluded option(s) as cross-tree constraint(s) List <List <ConfigurationOption> > nonAlternative = binOpt.getNonAlternativeExlcudedOptions(); if (nonAlternative.Count > 0) { foreach (var excludedOption in nonAlternative) { CspTerm[] orTerm = new CspTerm[excludedOption.Count]; int i = 0; foreach (var opt in excludedOption) { CspTerm target = optionToTerm[(BinaryOption)opt]; orTerm[i] = target; i++; } S.AddConstraints(S.Implies(cT, S.Not(S.Or(orTerm)))); } } } //Handle implies if (current.Implied_Options.Count > 0) { foreach (List <ConfigurationOption> impliedOr in current.Implied_Options) { CspTerm[] orTerms = new CspTerm[impliedOr.Count]; //Possible error: if a binary option impies a numeric option for (int i = 0; i < impliedOr.Count; i++) { orTerms[i] = optionToTerm[(BinaryOption)impliedOr.ElementAt(i)]; } S.AddConstraints(S.Implies(optionToTerm[current], S.Or(orTerms))); } } } //Handle global cross-tree constraints involving multiple options at a time // the constraints should be in conjunctive normal form foreach (string constraint in vm.BinaryConstraints) { bool and = false; string[] terms; if (constraint.Contains("&")) { and = true; terms = constraint.Split('&'); } else { terms = constraint.Split('|'); } CspTerm[] cspTerms = new CspTerm[terms.Count()]; int i = 0; foreach (string t in terms) { string optName = t.Trim(); if (optName.StartsWith("-") || optName.StartsWith("!")) { optName = optName.Substring(1); BinaryOption binOpt = vm.getBinaryOption(optName); CspTerm cspElem = optionToTerm[binOpt]; CspTerm notCspElem = S.Not(cspElem); cspTerms[i] = notCspElem; } else { BinaryOption binOpt = vm.getBinaryOption(optName); CspTerm cspElem = optionToTerm[binOpt]; cspTerms[i] = cspElem; } i++; } if (and) { S.AddConstraints(S.And(cspTerms)); } else { S.AddConstraints(S.Or(cspTerms)); } } return(S); }