/// <summary> /// Randomly assign values to the propositions, /// propagate through the initialization, /// and initialize the other state information accordingly. /// </summary> private void MakeRandomAssignment() { if (varInitialized == null || varInitialized.Length != Problem.SATVariables.Count) { varInitialized = new bool[Problem.SATVariables.Count]; improvablePropositions = new DynamicUShortSet(Problem.SATVariables.Count); } Array.Clear(falseLiterals, 0, falseLiterals.Length); Array.Clear(trueLiterals, 0, trueLiterals.Length); Array.Clear(varInitialized, 0, varInitialized.Length); totalUtility = 0; improvablePropositions.Clear(); var vars = Problem.SATVariables; // // Set indices to a randomly permuted series of 1 .. Propositions.Length - 1 // This gives us a random order in which to initialize the variables // var indices = new ushort[Propositions.Length - 1]; for (var i = 0; i < indices.Length; i++) { indices[i] = (ushort)(i + 1); } // Fisher-Yates shuffle algorithm (https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) var lastIndex = indices.Length - 1; for (var i = 0; i < indices.Length - 2; i++) { var swapWith = Random.InRange(i, lastIndex); var temp = indices[i]; indices[i] = indices[swapWith]; indices[swapWith] = temp; } foreach (var i in indices) { if (!varInitialized[i]) { var satVar = vars[i]; var truth = satVar.IsPredetermined ? satVar.PredeterminedValue : satVar.RandomInitialState; // Skip the propagation if user specified if (!Problem.PropagateConstraintsDuringInitialization) { Propositions[i] = truth; UpdateUtility(i); } else { PropagateConstraints(i, truth); } } } foreach (var targetClause in Problem.Constraints) { // Make sure we don't change the predetermined propositions targetClause.UnPredeterminedDisjuncts.Clear(); foreach (short lit in targetClause.Disjuncts) { if (!Problem.SATVariables[(ushort)Math.Abs(lit)].IsPredetermined) { targetClause.UnPredeterminedDisjuncts.Add(lit); } } } UnsatisfiedClauses.Clear(); // Initialize trueDisjunctCount[] and unsatisfiedClauses for (ushort i = 0; i < TrueDisjunctCount.Length; i++) { var c = Problem.Constraints[i]; var satisfiedDisjuncts = c.CountDisjuncts(Solution); TrueDisjunctCount[i] = satisfiedDisjuncts; if (!c.IsSatisfied(satisfiedDisjuncts) && c.IsEnabled(Solution)) { if (c.UnPredeterminedDisjuncts.Count == 0) { // It's false, but all the disjuncts are predetermined throw new ContradictionException(Problem, c); } UnsatisfiedClauses.Add(i); } } //CheckUtility(); }
/// <summary> /// Flip the variable at the specified index. /// </summary> /// <param name="pIndex">Index of the variable/proposition to flip</param> private void Flip(ushort pIndex) { var prop = Problem.SATVariables[pIndex]; Debug.Assert(!prop.IsPredetermined, "The prop is predetermined, can't flip it."); var currentlyTrue = Propositions[pIndex]; var utility = prop.Proposition.Utility; // ReSharper disable once CompareOfFloatsByEqualityOperator if (utility != 0) { if (utility < 0 ^ currentlyTrue) { // This flip lowers utility improvablePropositions.Add(pIndex); } else { // This flip increases utility improvablePropositions.Remove(pIndex); } } { if (currentlyTrue) { // Flip true -> false Propositions[pIndex] = false; totalUtility -= Problem.SATVariables[pIndex].Proposition.Utility; // Update the clauses in which this appears as a positive literal foreach (ushort cIndex in prop.PositiveClauses) { // prop appears as a positive literal in clause. // We just made it false, so clause now has fewer satisfied disjuncts. var clause = Problem.Constraints[cIndex]; clause.UpdateTruePositiveAndFalseNegative(this); } // Update the clauses in which this appears as a negative literal foreach (ushort cIndex in prop.NegativeClauses) { // prop appears as a negative literal in clause. // We just made it false, so clause now has more satisfied disjuncts. var clause = Problem.Constraints[cIndex]; clause.UpdateTrueNegativeAndFalsePositive(this); } } else { // Flip false -> true Propositions[pIndex] = true; totalUtility += Problem.SATVariables[pIndex].Proposition.Utility; // Update the clauses in which this appears as a positive literal foreach (ushort cIndex in prop.PositiveClauses) { // prop appears as a positive literal in clause. // We just made it true, so clause now has more satisfied disjuncts. var clause = Problem.Constraints[cIndex]; clause.UpdateTrueNegativeAndFalsePositive(this); } // Update the clauses in which this appears as a negative literal foreach (ushort cIndex in prop.NegativeClauses) { // prop appears as a negative literal in clause. // We just made it true, so clause now has fewer satisfied disjuncts. var clause = Problem.Constraints[cIndex]; clause.UpdateTruePositiveAndFalseNegative(this); } } } //CheckUtility(); }