2011-08-17 64 views
1

我正在使用布爾條件表達式的匹配系統的一小部分工作。C中的條件表達式代數#

這些條件表達式被約束爲單個變量和單個運算符(具有包含之間的邊界情況)。

我感興趣的是:

  • 等於 「=」
  • 比 「>」
  • 大大於等於要 「> =」
  • 小於 「<」
  • 小於或等於「< =」
  • 包含在「> = AND中< =」

我有一個要求比較兩個條件表達式和評價:

1)是否有可能值的重疊?

「X> 1000」與「X> 999」重疊嗎?是。

2)如果存在重疊,則返回該重疊:

的 「X> 1000」 與 「X> 999」 是重疊 「X> 1000」

3)是一個條件表達式受另一個約束?

「X < 999」受「X < 1000」的約束; 「X < 1001」不受限「X < 1000」


我所做的到目前爲止是建立所有可能組合的真值表並返回結果,但我想知道是否有一個更簡單的方法來計算這些?

任何理論/參考資料/ C#庫在那裏?

+1

我首先搜索「解決線性不等式的系統」或類似的問題。 – Ani

回答

3

我還沒有聽說過任何的,但如果你所代表的約束間隔,你可以很容易地沒有他們:

X> 1000變爲(1000,double.Infinity)
X == 1000變爲[ 1000,1000]

這樣,你只需要一個類

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. 
} 

有了這個代碼,你可以回答的問題:

1)搭接:a.Intersect(b).isEmpty()

2)交叉:a.Intersect(b)

3)約束:a.Intersect(b).Equals(a)


編輯:
正如@CodeInChaos建議,你應該考慮用小數代替double。請注意,decimal不具有無限值,因此應該使用decimal.MaxValue和decimal.MinValue。

+0

我會考慮在這裏使用'Decimal'。這種方式從文本解析的限制可以精確表示。 – CodesInChaos

+1

@CodeInChaos:好吧,在這種情況下,我會去尋找一個通用的數字類型。 – Vlad

+0

不知道你的意思是弗拉德。在這種情況下,您不能輕鬆使用通用參數,因爲重載的操作符缺失。可以使用動態類型/運行時代碼生成來解決這個問題,但這很醜且很慢。 – CodesInChaos

0

我已經寫了一些示例代碼快。希望它是有道理的:

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; 
    } 
}