/// <summary> /// Build one or more arcs from the ternary constraint expression. /// </summary> /// <remarks> /// There will be more than one arc because binarization of the expression requires introducing an /// encapsulated variable between the two variables involved in the expression. /// </remarks> /// <param name="expressionConstraintNode">Expression constraint abstract syntax tree.</param> /// <returns>One or more arcs.</returns> private IReadOnlyCollection <Arc> BuildTernaryExpression(ConstraintExpressionNode expressionConstraintNode) { var arcAccumulator = new List <Arc>(); if (!expressionConstraintNode.InnerExpression.RightExpression.IsLiteral) { var left = CreateNodeFrom(expressionConstraintNode.InnerExpression.LeftExpression); var right = CreateNodeFrom(expressionConstraintNode.InnerExpression.RightExpression); var encapsulatedVariable = new EncapsulatedVariable("U"); var encapsulatedVariableNode = new EncapsulatedVariableNode(encapsulatedVariable); var arc1 = new Arc(left, encapsulatedVariableNode, new EncapsulatedVariableConnector(left, encapsulatedVariableNode, new EncapsulatedSelector(1))); arcAccumulator.Add(arc1); var arc2 = new Arc(right, encapsulatedVariableNode, new EncapsulatedVariableConnector(encapsulatedVariableNode, right, new EncapsulatedSelector(2))); arcAccumulator.Add(arc2); var ternaryConstraintExpression = new TernaryConstraintExpression(expressionConstraintNode, encapsulatedVariableNode, arc1, arc2); var encapsulatedVariableDomainValue = ComputeEncapsulatedDomain(ternaryConstraintExpression); encapsulatedVariable.DomainValue = encapsulatedVariableDomainValue; var expressionSolution = new TernaryConstraintExpressionSolution(ternaryConstraintExpression, encapsulatedVariableDomainValue); _modelSolverMap.AddTernaryExpressionSolution(expressionSolution); } else { var left = CreateNodeFrom(expressionConstraintNode.InnerExpression.LeftExpression); var encapsulatedVariable = new EncapsulatedVariable("U"); var encapsulatedVariableNode = new EncapsulatedVariableNode(encapsulatedVariable); var arc1 = new Arc(left, encapsulatedVariableNode, new EncapsulatedVariableConnector(left, encapsulatedVariableNode, new EncapsulatedSelector(1))); arcAccumulator.Add(arc1); var ternaryConstraintExpression = new TernaryConstraintExpression(expressionConstraintNode, encapsulatedVariableNode, arc1, arc1); var encapsulatedVariableDomainValue = ComputeEncapsulatedDomain(ternaryConstraintExpression); encapsulatedVariable.DomainValue = encapsulatedVariableDomainValue; var expressionSolution = new TernaryConstraintExpressionSolution(ternaryConstraintExpression, encapsulatedVariableDomainValue); _modelSolverMap.AddTernaryExpressionSolution(expressionSolution); } return(new ReadOnlyCollection <Arc>(arcAccumulator)); }
private EncapsulatedVariableDomainValue ComputeEncapsulatedDomain(TernaryConstraintExpression ternaryConstraintExpression) { var encapsulatedVariableCalculator = new EncapsulatedVariablePermutationCalculator(_modelSolverMap, _valueMapper); return(encapsulatedVariableCalculator.Compute(ternaryConstraintExpression)); }
internal EncapsulatedVariableDomainValue Compute(TernaryConstraintExpression ternaryConstraint) { var valueSetAccumulator = new List <ValueSet>(); var leftSource = ternaryConstraint.GetLeftSource(); var leftPossibleValues = leftSource.PossibleValues; var expression = ternaryConstraint.ExpressionNode; IReadOnlyCollection <int> rightPossibleValues; if (!expression.InnerExpression.RightExpression.IsLiteral) { var rightSource = ternaryConstraint.GetRightSource(); rightPossibleValues = new ReadOnlyCollection <int>(rightSource.PossibleValues.ToList()); } else { var lhsVariable = _modelSolverMap.GetModelVariableByName(leftSource.VariableName); var range = _valueMapper.GetDomainValueFor(lhsVariable); var modelValue = expression.InnerExpression.RightExpression.GetLiteral(); var solverValue = range.MapTo(modelValue); rightPossibleValues = new ReadOnlyCollection <int>(new List <int> { solverValue }); } foreach (var leftPossibleValue in leftPossibleValues) { foreach (var rightPossibleValue in rightPossibleValues) { switch (ternaryConstraint.ExpressionNode.InnerExpression.Operator) { case OperatorType.Equals: if (leftPossibleValue == rightPossibleValue) { if (!expression.InnerExpression.RightExpression.IsLiteral) { var rightSource = ternaryConstraint.GetRightSource(); var valueSet = new ValueSet(new[] { new Value(_modelSolverMap.GetSolverVariableByName(leftSource.VariableName), leftPossibleValue), new Value(_modelSolverMap.GetSolverVariableByName(rightSource.VariableName), rightPossibleValue) }); valueSetAccumulator.Add(valueSet); } else { var valueSet = new ValueSet(new[] { new Value(_modelSolverMap.GetSolverVariableByName(leftSource.VariableName), leftPossibleValue) }); valueSetAccumulator.Add(valueSet); } } break; case OperatorType.NotEqual: if (leftPossibleValue != rightPossibleValue) { if (!expression.InnerExpression.RightExpression.IsLiteral) { var rightSource = ternaryConstraint.GetRightSource(); var valueSet = new ValueSet(new[] { new Value(_modelSolverMap.GetSolverVariableByName(leftSource.VariableName), leftPossibleValue), new Value(_modelSolverMap.GetSolverVariableByName(rightSource.VariableName), rightPossibleValue) }); valueSetAccumulator.Add(valueSet); } else { var valueSet = new ValueSet(new[] { new Value(_modelSolverMap.GetSolverVariableByName(leftSource.VariableName), leftPossibleValue) }); valueSetAccumulator.Add(valueSet); } } break; default: throw new NotImplementedException(); } } } return(new EncapsulatedVariableDomainValue(ternaryConstraint.EncapsulatedVariable, valueSetAccumulator)); }