/// <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));
        }
Example #3
0
        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));
        }