开发者

Conditional expression algebra in C#

I am working on a small part of a matching system that uses boolean conditional expressions.

These conditional expressions are contrained to a single variable and a single operator (with an edge case of an Inclusive Between).

I am interested in:

  • Equal To "="
  • Greater than ">"
  • Greater Than Or Equal To ">="
  • Less Than "<"
  • Less Than Or Equal To "<="
  • Inclusive Between ">= AND <="

I have a requirement to compare two conditional expressions and evaluate:

1) Is there an overlap of possible values?

Does "X > 1000" overlap with "X > 999"? Yes.

2) If there is an overlap, return the overlap:

The overlap of "X > 1000" with "X > 999" is "X > 1000"

3) Is a conditional expression constrained by another?

"X < 999" is constrained by "X < 1000" ; "X &l开发者_如何学Ct; 1001" is not constrained by "X < 1000"


What I have done so far is build up a truth table of all possible combinations and return the results, but I was wondering if there was an easier way to calculate these?

Any Theory / Reference material / C# libraries out there?


I haven't heard of any, but you can easily do without them if you represent the constraints as intervals:

x > 1000 becomes (1000, double.Infinity)
x == 1000 becomes [1000, 1000]

etc.

This way you need only one class

class Constraint
{
    double Lower; bool isLowerStrict;
    double Upper; bool isUpperStrict;
    bool isIn(double d)
    { 
        return (isLowerStrict ? Lower < d : Lower <= d) &&
               (isUpperStrict ? Upper > d : Upper >= d);
    }

    Constraint intersect(Constraint other)
    {
        Constraint result = new Constraint();
        if (Lower > other.Lower)
        {
            result.Lower = Lower;
            result.isLowerStrict = isLowerStrict;
        }
        else if (Lower < other.Lower)
        {
            result.Lower = other.Lower;
            result.isLowerStrict = other.isLowerStrict;
        }
        else
        {
            result.Lower = Lower;
            result.IsLowerStrict = isLowerStrict || other.isLowerStrict;
        }
        // the same for upper
        return result;
    }

    public bool isEmpty()
    {
        if (Lower > Upper) return true;
        if (Lower == Upper && (isLowerStrict || isUpperStrict)) return true;
        return false;
    }
    public bool Equals(Constraint other)
    {
        if (isEmpty()) return other.isEmpty();
        return (Lower == other.Lower) && (Upper = other.Upper) &&
               (isLowerStrict == other.IsLowerStrict) &&
               (isUpperStrict == other.isUpperStrict);
    }

    // construction:
    static Constraint GreaterThan(double d)
    {
        return new Constraint()
        {
            Lower = d,
            isLowerStrict = true,
            Upper = double.PositiveInfinity,
            isUpperStrict = false
        };
    }
    static Constraint IsEqualTo(double d)
    {
        return new Constraint()
        {
            Lower = d,
            isLowerStrict = false,
            Upper = d,
            isUpperStrict = false
        };
    }
    // etc.
}

With this code, you can answer the questions:

1) overlap: a.Intersect(b).isEmpty()

2) intersect: a.Intersect(b)

3) constrain: a.Intersect(b).Equals(a)


EDIT:
As @CodeInChaos suggests, you should consider replacing double with decimal. Mind that decimal lacks infinite values, so you should use decimal.MaxValue and decimal.MinValue instead.


I had written some sample code fast. Hope it makes sense:

enum SygnType
{
    More, Less, Equal
}
public class Representation
{
    public SignType sign;
    public int value;
}
public class Range
{
    public bool infinityNegative;
    public bool infinityPositive;
    public int minValue;
    public int maxValue;
    public Range(List<Representation> values)
    {
        infinityNegative=true;
        infinityPositive=true;
        foreach(var value in values)
        {
            if (value.sign==SignType.More)
            {
                infinityNegative=false;
                if (value>minValue)
                    minValue=value;
            }
            else if (value.sign==SignType.Less)
            {
                infinityPositive=false;
                if (value<maxValue)
                    maxValue=value;
            }
            else if (value.sign==SignType.Equal)
            {
                infinityPositive=infinityNegative=false;
                minValue=maxValue=value;
                break;
            }
        }
    }
    public bool Overlaps(Range checkRange)
    {
        if (checkRange.infinityPositive)
            return CompareUpperLevelValue(checkRange); //this method should compare upper value overlapping
        else if (checkRange.infinityNegative)
            return CompareLowerLevelValue(checkRange); //this method should compare lower value overlapping
        else
            return CompareInterval(checkRange); //this method should compare interval
    }
    public bool CompareUpperLevelValue(Range checkRange)
    {
        if (checkRange.maxValue<maxValue)
            return true;
        else 
            return false
    }
    public bool CompareLowerLevelValue(Range checkRange)
    {
        if (checkRange.minValue>minValue)
            return true;
        else 
            return false
    }
    public bool CompareInterval(Range checkRange)
    {
        if ((checkRange.minValue>minValue)&&(checkRange.maxValue<maxValue))
            return true;
        else
            return false;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜