2011-08-17 60 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; 
    } 
}