private SolverVariable ExtractVariableFrom(ExpressionNode expressionConstraintNode)
        {
            switch (expressionConstraintNode.InnerExpression)
            {
            case SingletonVariableReferenceNode singletonVariableReference:
                return(_modelSolverMap.GetSolverSingletonVariableByName(singletonVariableReference.VariableName));

            case AggregateVariableReferenceNode aggregateVariableReference:
                return(_modelSolverMap.GetSolverAggregateVariableByName(aggregateVariableReference.VariableName,
                                                                        aggregateVariableReference.SubscriptStatement.Subscript));

            case SingletonVariableReferenceExpressionNode singletonVariableExpression:
                return(_modelSolverMap.GetSolverSingletonVariableByName(singletonVariableExpression.VariableReference.VariableName));

            case AggregateVariableReferenceExpressionNode aggregateVariableExpression:
                return(_modelSolverMap.GetSolverAggregateVariableByName(aggregateVariableExpression.VariableReference.VariableName,
                                                                        aggregateVariableExpression.VariableReference.SubscriptStatement.Subscript));

            case BucketVariableReferenceNode bucketVariableReference:
                return(_modelSolverMap.GetSolverBucketVariableByName(bucketVariableReference.BucketName,
                                                                     bucketVariableReference.SubscriptStatement.Subscript,
                                                                     bucketVariableReference.VariableName));

            default:
                throw new NotImplementedException();
            }
        }
        private void CreateArcFrom(AllDifferentConstraintModel constraint)
        {
            var solverAggregateVariable = _modelSolverMap.GetSolverAggregateVariableByName(constraint.Expression.Text);

            /*
             * Iterate through all variables inside the aggregate and ensure
             * that each variable is not equal to all variables to their
             * right. The not equal operator is commutative so there is no need
             * to express the constraint the other way around.
             */
            for (var i = 0; i < solverAggregateVariable.Variables.Count; i++)
            {
                for (var z = i + 1; z < solverAggregateVariable.Variables.Count; z++)
                {
                    var expressionText = $"${solverAggregateVariable.Name}[{i}] <> ${solverAggregateVariable.Name}[{z}]";
                    var interpreter    = new ConstraintExpressionParser();
                    var parseResult    = interpreter.Parse(expressionText);
                    Debug.Assert(parseResult.IsSuccess);
                    _constraintNetwork.AddArc(_arcBuilder.Build(parseResult.Root));
                }
            }
        }