Я не слышал о них, но вы легко можете обойтись без них, если представите ограничения в виде интервалов:
x> 1000 становится (1000, double.Infinity)
х == 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)
EDIT:
Как подсказывает @CodeInChaos, вы должны рассмотреть возможность замены double на десятичное. Имейте в виду, что десятичному не хватает бесконечных значений, поэтому вы должны использовать вместо него decimal.MaxValue и decimal.MinValue.