Is it possible to parse and evaluate inequalities?

265 Views Asked by At

As per title, is it possible to parse and evaluate inequalities obtaining a true/false result?

As example:

Expression e = Infix.ParseOrThrow("A<B");

It throws:

enter image description here

My current approach:

public static bool CheckInequalitySatisfaction(string inequality, BoxDimensionValues values = null)
{
    try
    {
        if (string.IsNullOrWhiteSpace(inequality))
            throw new ArgumentNullException(nameof(inequality));

        if (inequality.ToLower().Equals("false"))
            return false;

        if (inequality.ToLower().Equals("true"))
            return true;

        var matches = Regex.Match(inequality, "(?<left>.+)(?<operand>==|<=|>=|<|>)(?<right>.+)");

        if (!matches.Success)
            throw new ArgumentException($"The inequality is not valid {inequality}", nameof(inequality));

        var leftExpression = matches.Groups["left"].Value;
        if (!TryEvaluateExpression(leftExpression, values, out int leftValue))
            throw new ArgumentException($"The left expression of the inequality is not valid {leftExpression}", nameof(inequality));

        var rightExpression = matches.Groups["right"].Value;
        if (!TryEvaluateExpression(rightExpression, values, out int rightValue))
            throw new ArgumentException($"The right expression of the inequality is not valid {rightExpression}", nameof(inequality));

        var inequalityOperator = matches.Groups["operand"].Value;

        return inequalityOperator switch
        {
            "==" => leftValue == rightValue,
            "<=" => leftValue <= rightValue,
            ">=" => leftValue >= rightValue,
            "<" => leftValue < rightValue,
            ">" => leftValue > rightValue,
            _ => throw new NotImplementedException($"The operator {inequalityOperator} is not supported for inequalities evaluation"),
        };
    }
    catch (Exception ex)
    {
        ex.Log(MethodBase.GetCurrentMethod());
        throw;
    }
}

1

There are 1 best solutions below

3
On

I spent some time trying to solve this for you, and could not with the current featureset in MathNet. But I did notice that MathNet's Expression object can handle operations like + and - with other Expression objects, so you could write an extension method that converted your inequality into a parsable expression.

Basically, since we know that Infix will parse "A-B" but not "A<B", you could replace the "<" with "-" and then check the expression against 0. Something like this, perhaps:

public static Expression SafeParseLessThan(this string mathExpression)
{
    var splitExpression = mathExpression.Split("<");
    var left = Infix.ParseOrThrow(splitExpression[0]);
    var right = Infix.ParseOrThrow(splitExpression[1]);

    return left - right;
}

With usage:

var newExpression = "A<B".SafeParseLessThan();

var symbols = new Dictionary<string, FloatingPoint>
{
    {"A", 3},
    {"B", 5}
};

var result = Evaluate.Evaluate(symbols, newExpression).RealValue < 0; // true

There will be other things for you to consider, given the types of functions you are parsing. For instance, this quick example I whipped up assumes real values. You will also need to get creative if you need include other non-parsable elements in your expressions such as min and max, perhaps like in "min(A,B) < max(C,D)".

I also noticed you posted another question related to MathNet parsing of min/max functions. You could probably apply this type of strategy to that as well.