假设符号是整数

时间:2018-01-04 18:12:11

标签: sympy

我正在使用SymPy来创建一个Kakuro求解器,但我无法强制执行符号需要整数。到目前为止,我得到了一个看起来像这样的不等式:

((1 <= x) & (x < 3/2)) | ((3/2 < x) & (x < 2))

符号x应该等于1,因此表达式是正确的,因为1是唯一可能的整数。

如何强制x为整数?

我知道SymPy中有可用的丢番图求解器,但这些似乎只能处理方程,而不是不等式。我尝试使用以下方法创建符号:

x = Symbol('x', integer=True)

但没有运气。

1 个答案:

答案 0 :(得分:0)

似乎没有内置方式,但我编写了一个函数来简化你提到的那种关系,假设我们使用整数。

有八个重写规则:例如,x <= number替换为x <= floor(number)x < number替换为x <= ceiling(number) - 1等。

应用这些规则后,表达式的任何剩余And部分都会受到reduce_inequalities的约束。示例:

expr = ((1 <= x) & (x < 3 / 2)) | ((3 / 2 < x) & (x < 2))
simplify_integer_relation(expr)   # returns Eq(x, 1)

警告:重写规则假设我们不会在表达式中执行任何类似x/2的操作,从而创建未知的小数。假设涉及未知的所有内容都是整数。

代码:

def simplify_integer_relation(expr):
    rewrite_rules = {
        GreaterThan: {
            "lhs": lambda z: floor(z),
            "rhs": lambda z: ceiling(z),
            "rel": GreaterThan,
        },
        LessThan: {
            "lhs": lambda z: ceiling(z),
            "rhs": lambda z: floor(z),
            "rel": LessThan,
        },
        StrictGreaterThan: {
            "lhs": lambda z: ceiling(z) - 1,
            "rhs": lambda z: floor(z) + 1,
            "rel": GreaterThan,
        },
        StrictLessThan: {
            "lhs": lambda z: floor(z) + 1,
            "rhs": lambda z: ceiling(z) - 1,
            "rel": LessThan,
        },
    }

    for rel in rewrite_rules:
        rule = rewrite_rules[rel]
        for atom in expr.atoms(rel):
            if atom.lhs.is_number:
                new_atom = rule["rel"](rule["lhs"](atom.lhs), atom.rhs)
                expr = expr.subs(atom, new_atom)
            elif atom.rhs.is_number:
                new_atom = rule["rel"](atom.lhs, rule["rhs"](atom.rhs))
                expr = expr.subs(atom, new_atom)

    for system in expr.atoms(And):
        expr = expr.subs(system, reduce_inequalities(system.args))

    return expr