private bool ReviseArcs(ConstraintNetwork constraintNetwork) { var domainChanged = false; foreach (var arc in constraintNetwork.GetArcs()) { /* * Arcs with ternary or unary expressions are pre-computed with one * or more solution sets produced for the variables involved in the expression. */ if (arc.IsPreComputed) { continue; } var connector = arc.Connector as ConstraintExpressionConnector; Debug.Assert(connector != null); var constraint = connector.Constraint; if (!constraint.Node.InnerExpression.LeftExpression.IsLiteral) { // Revise the left variable domain domainChanged |= ReviseLeft(arc.Left as VariableNode, arc.Right as VariableNode, constraint); } if (!constraint.Node.InnerExpression.RightExpression.IsLiteral) { // Revise the right variable domain domainChanged |= ReviseRight(arc.Left as VariableNode, arc.Right as VariableNode, constraint); } } return(domainChanged); }
/// <summary> /// Build a constraint network from the model. /// </summary> /// <param name="model">Constraint model.</param> /// <returns>Constraint network.</returns> internal ConstraintNetwork Build(ModelModel model) { MapVariables(model); MapValues(model); ConvertBuckets(model); _constraintNetwork = new ConstraintNetwork(); PopulateConstraintNetwork(model); CreateVariables(model); return(_constraintNetwork); }
/// <summary> /// Extract a snapshot from the constraint network. /// </summary> /// <param name="constraintNetwork">Constraint network.</param> /// <param name="solutionSnapshot">Solution snapshot.</param> /// <returns>True if a snapshot was extracted, False if the snapshot could not be extracted.</returns> internal bool ExtractFrom(ConstraintNetwork constraintNetwork, out SolutionSnapshot solutionSnapshot) { _constraintNetwork = constraintNetwork; var solverVariables = constraintNetwork.GetSolverVariables(); var assignment = new SnapshotLabelAssignment(solverVariables); _variables = new List <VariableBase>(constraintNetwork.GetVariables()); var status = Backtrack(0, assignment, constraintNetwork); solutionSnapshot = status ? ConvertSnapshotFrom(assignment, constraintNetwork) : SolutionSnapshot.Empty; return(status); }
/// <summary> /// Remove values found during the ternary pre-calculation phase that are now /// inconsistent with values discovered during the regular revising of /// domains of the binary constraints. /// </summary> /// <param name="constraintNetwork">Constraint network.</param> private void RemoveTernaryValuesInconsistentWithBinaryConstraints(ConstraintNetwork constraintNetwork) { var constraintExpressionSolutions = _modelSolverMap.GetTernaryConstraintExpressionSolutions(); foreach (var constraintExpressionSolution in constraintExpressionSolutions) { var leftVariable = constraintExpressionSolution.Expression.LeftArc.Left.Content as SolverVariable; Debug.Assert(leftVariable != null); var leftVariableDomain = leftVariable.Domain; var leftVariableIndex = 1; // Left variable is always in first index RemoveTernaryValuesInconsistentWithBinaryConstraint(constraintExpressionSolution, leftVariableIndex, leftVariableDomain); var rightVariable = constraintExpressionSolution.Expression.RightArc.Left.Content as SolverVariable; Debug.Assert(rightVariable != null); var rightVariableDomain = rightVariable.Domain; var rightVariableIndex = 2; // Right variable is always in second index RemoveTernaryValuesInconsistentWithBinaryConstraint(constraintExpressionSolution, rightVariableIndex, rightVariableDomain); } }
/// <summary> /// Get all value sets for the variable. /// </summary> /// <param name="variable">Variable</param> /// <param name="assignment">All value assignments.</param> /// <param name="constraintNetwork">Constraint network.</param> /// <returns>All value sets for the variable.</returns> private IEnumerable <ValueSet> OrderDomainValues(VariableBase variable, SnapshotLabelAssignment assignment, ConstraintNetwork constraintNetwork) { switch (variable) { case SolverVariable solverVariable: return(solverVariable.GetCandidates()); case EncapsulatedVariable encapsulatedVariable: return(encapsulatedVariable.GetCandidates()); default: throw new NotImplementedException(); } }
/// <summary> /// Backtrack through a variable's value sets until one is found that is arc consistent. /// </summary> /// <param name="currentVariableIndex">Current variable index.</param> /// <param name="snapshotAssignment">Current snapshot of value sets.</param> /// <param name="constraintNetwork">Constraint network.</param> /// <returns>True if a value is found to be consistent, False if a value is not found.</returns> private bool Backtrack(int currentVariableIndex, SnapshotLabelAssignment snapshotAssignment, ConstraintNetwork constraintNetwork) { // Label assignment has been successful... if (snapshotAssignment.IsComplete() && AllVariablesTested(currentVariableIndex)) { return(true); } // The unassigned variable may be a regular variable or an encapsulated variable var currentVariable = SelectUnassignedVariable(currentVariableIndex, constraintNetwork, snapshotAssignment); foreach (var value in OrderDomainValues(currentVariable, snapshotAssignment, constraintNetwork)) { if (IsConsistent(value, snapshotAssignment)) { snapshotAssignment.AssignTo(value); // Is this the final variable? if (AllVariablesTested(currentVariableIndex)) { return(true); } if (Backtrack(currentVariableIndex + 1, snapshotAssignment, constraintNetwork)) { return(true); } } snapshotAssignment.Remove(value); } return(false); }
private IEnumerable <BucketLabelModel> ExtractBucketLabelsFrom(SnapshotLabelAssignment assignment, ConstraintNetwork constraintNetwork) { var bucketLabelAccumulator = new List <BucketLabelModel>(); foreach (var bucketVariableMap in _modelSolverMap.GetBucketVariables()) { bucketLabelAccumulator.Add(ExtractBucketLabelFrom(assignment, bucketVariableMap)); } return(bucketLabelAccumulator); }
private IEnumerable <AggregateVariableLabelModel> ExtractAggregateLabelsFrom(SnapshotLabelAssignment assignment, ConstraintNetwork constraintNetwork) { var aggregatorLabelAccumulator = new List <AggregateVariableLabelModel>(); foreach (var aggregateSolverVariable in constraintNetwork.GetAggregateVariables()) { var internalAccumulator = new List <ValueModel>(); var aggregateVariableModel = _modelSolverMap.GetModelAggregateVariableByName(aggregateSolverVariable.Name); foreach (var variable in aggregateSolverVariable.Variables) { var solverVariable = _modelSolverMap.GetSolverVariableByName(variable.Name); var labelAssignment = assignment.GetAssignmentFor(solverVariable); var variableSolverValue = labelAssignment.Value; var variableModel = _modelSolverMap.GetInternalModelAggregateVariableByName(variable.Name); var variableModelValue = ConvertSolverValueToModel((SingletonVariableModel)variableModel, variableSolverValue); internalAccumulator.Add(new ValueModel(variableModelValue)); } var label = new AggregateVariableLabelModel(aggregateVariableModel, internalAccumulator); aggregatorLabelAccumulator.Add(label); } return(aggregatorLabelAccumulator); }
private IEnumerable <SingletonVariableLabelModel> ExtractSingletonLabelsFrom(SnapshotLabelAssignment assignment, ConstraintNetwork constraintNetwork) { var labelAccumulator = new List <SingletonVariableLabelModel>(); foreach (var variable in constraintNetwork.GetSingletonVariables()) { var solverVariable = _modelSolverMap.GetSolverSingletonVariableByName(variable.Name); var labelAssignment = assignment.GetAssignmentFor(solverVariable); var variableSolverValue = labelAssignment.Value; var variableModel = _modelSolverMap.GetModelSingletonVariableByName(variable.Name); var variableModelValue = ConvertSolverValueToModel(variableModel, variableSolverValue); var label = new SingletonVariableLabelModel(variableModel, new ValueModel(variableModelValue)); labelAccumulator.Add(label); } return(labelAccumulator); }
private SolutionSnapshot ConvertSnapshotFrom(SnapshotLabelAssignment assignment, ConstraintNetwork constraintNetwork) { return(new SolutionSnapshot(ExtractSingletonLabelsFrom(assignment, constraintNetwork), ExtractAggregateLabelsFrom(assignment, constraintNetwork), ExtractBucketLabelsFrom(assignment, constraintNetwork))); }
private VariableBase SelectUnassignedVariable(int currentVariableIndex, ConstraintNetwork constraintNetwork, SnapshotLabelAssignment assignment) { Debug.Assert(currentVariableIndex < _variables.Count, "Backtracking must never attempt to go over the end of the variables."); return(_variables[currentVariableIndex]); }