private IVariable MakeLongMultiplication(IMilpManager baseMilpManager, Domain domain, IVariable zero, IVariable second,
                                                 IVariable first)
        {
            var result = zero;

            var secondDigits = second.CompositeOperation(CompositeOperationType.UnsignedMagnitudeDecomposition).ToArray();

            for (int index = 0, power = 1; index < secondDigits.Length; ++index, power = power * 2)
            {
                result = result.Operation(OperationType.Addition,
                                          MultipleByBinaryDigit(baseMilpManager, first, secondDigits[index])
                                          .ChangeDomain(domain)
                                          .Operation(OperationType.Multiplication, baseMilpManager.FromConstant(power))
                                          );
            }
            return(result);
        }
        private static IVariable CalculatePower(IVariable number, IVariable power, IMilpManager milpManager, IVariable isEdgeCase)
        {
            var digits = (int)Math.Ceiling(Math.Log(milpManager.IntegerWidth, 2.0));

            var infinity      = milpManager.FromConstant(milpManager.MaximumIntegerValue);
            var currentPower  = milpManager.Operation(OperationType.Minimum, number, isEdgeCase.Operation(OperationType.BinaryNegation).Operation(OperationType.Multiplication, infinity));
            var decomposition = power.CompositeOperation(CompositeOperationType.UnsignedMagnitudeDecomposition).Take(digits).ToArray();
            var one           = milpManager.FromConstant(1);
            var result        = one;

            for (int i = 0; i < digits; ++i)
            {
                if (i > 0)
                {
                    var isAnyNonzeroDigitLater = milpManager.Operation(OperationType.Disjunction, decomposition.Skip(i).ToArray());
                    var numberToMultiply       = milpManager.Operation(OperationType.Minimum, currentPower, isAnyNonzeroDigitLater.Operation(OperationType.Multiplication, infinity));
                    currentPower = numberToMultiply.Operation(OperationType.Multiplication, numberToMultiply);
                }

                result = result.Operation(OperationType.Multiplication, one.Operation(OperationType.Maximum, currentPower.Operation(OperationType.Multiplication, decomposition[i])));
            }

            return(result);
        }
        private static IVariable CalculatePower(IVariable number, IVariable power, IMilpManager milpManager, IVariable isEdgeCase)
        {
            var digits = (int)Math.Ceiling(Math.Log(milpManager.IntegerWidth, 2.0));

            var infinity = milpManager.FromConstant(milpManager.MaximumIntegerValue);
            var currentPower = milpManager.Operation(OperationType.Minimum, number, isEdgeCase.Operation(OperationType.BinaryNegation).Operation(OperationType.Multiplication, infinity));
            var decomposition = power.CompositeOperation(CompositeOperationType.UnsignedMagnitudeDecomposition).Take(digits).ToArray();
            var one = milpManager.FromConstant(1);
            var result = one;

            for (int i = 0; i < digits; ++i)
            {
                if (i > 0)
                {
                    var isAnyNonzeroDigitLater = milpManager.Operation(OperationType.Disjunction, decomposition.Skip(i).ToArray());
                    var numberToMultiply = milpManager.Operation(OperationType.Minimum, currentPower, isAnyNonzeroDigitLater.Operation(OperationType.Multiplication, infinity));
                    currentPower = numberToMultiply.Operation(OperationType.Multiplication, numberToMultiply);
                }

                result = result.Operation(OperationType.Multiplication, one.Operation(OperationType.Maximum, currentPower.Operation(OperationType.Multiplication, decomposition[i])));
            }

            return result;
        }
        private IVariable MakeLongMultiplication(IMilpManager baseMilpManager, Domain domain, IVariable zero, IVariable second,
            IVariable first)
        {
            var result = zero;

            var secondDigits = second.CompositeOperation(CompositeOperationType.UnsignedMagnitudeDecomposition).ToArray();
            for (int index = 0, power = 1; index < secondDigits.Length; ++index, power = power*2)
            {
                result = result.Operation(OperationType.Addition,
                    MultipleByBinaryDigit(baseMilpManager, first, secondDigits[index])
                        .ChangeDomain(domain)
                        .Operation(OperationType.Multiplication, baseMilpManager.FromConstant(power))
                    );
            }
            return result;
        }