0

私は PuLP を使用してプロジェクトに取り組んでおり、ユーザーがデータを入力できるようにするターミナル プロンプトを作成しようとしています。その後、私の Python プログラムは入力を PuLP で読み取り可能なコードに変更します。これを行うには、ユーザーに次の入力を許可する必要があります。

2*a + 3*b <= c

私のコードはこのコードをeval()し、変数a、b、cを作成します

a = LpVariable("a",None,None,LpContinuous)
b = LpVariable("b",None,None,LpContinuous)
c = LpVariable("c",None,None,LpContinuous)

何か案は?exec() を使用してみましたが、あまり気に入らないようです。

現時点では、次の方法で入力を取得しています。

print "Please enter your constraints 1 at a time and enter '#' when done:"
control = True
while (control):
    entry = raw_input('-->')
    entryS = ""
    entryS += entry

したがって、文字列 2*a+3*B <= c は entryS として格納されます

4

2 に答える 2

1

を使用eval()するのはあまり良い考えではないかもしれませんが、主張する場合 (Python 3):

call = lambda f: lambda *args: f(*args)
flip = lambda f: lambda *args: f(*reversed(args))


class Expression:

    def __repr__(self):
        return '{}({})'.format(type(self).__name__, self)


class BinaryExpression(Expression):

    def __init__(self, left, right):
        self.left = promote(left)
        self.right = promote(right)

    def __str__(self):
        return '({} {} {})'.format(self.op, self.left, self.right)


class Variable(Expression):

    def __init__(self, name):
        self.name = name

    def __str__(self):
        return self.name


class Number(Expression):

    def __init__(self, value):
        self.value = int(value)

    def __str__(self):
        return str(self.value)


class Multiplication(BinaryExpression):
    op = '*'


class Addition(BinaryExpression):
    op = '+'


class Smaller(BinaryExpression):
    op = '<'


class Greater(BinaryExpression):
    op = '>'


class SmallerOrEqual(BinaryExpression):
    op = '<='


class GreaterOrEqual(BinaryExpression):
    op = '>='


Expression.__mul__ = call(Multiplication)
Expression.__rmul__ = flip(Multiplication)
Expression.__add__ = call(Addition)
Expression.__radd__ = flip(Addition)
Expression.__lt__ = call(Smaller)
Expression.__gt__ = call(Greater)
Expression.__le__ = call(SmallerOrEqual)
Expression.__ge__ = call(GreaterOrEqual)


def promote(item):
    if isinstance(item, str):
        return Variable(item)
    elif isinstance(item, int):
        return Number(item)
    else:
        return item


class LpVariable:

    def __init__(self, name, x, y, z):
        self.name = name
        self.x = x
        self.y = y
        self.z = z

    def __str__(self):
        return 'LpVariable({}, {}, {}, {})'.format(
            self.name,
            self.x,
            self.y,
            self.z,
        )

    __repr__ = __str__


LpContinuous = 'LpContinuous'


class ExpressionVisitor:

    def visit(self, node):
        return getattr(self, 'visit_' + type(node).__name__)(node)


class LpTransformer(ExpressionVisitor):

    def visit_Variable(self, node):
        return LpVariable(node.name, None, None, LpContinuous)

    def visit_Number(self, node):
        return node.value

    def visit_Multiplication(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_Addition(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_Smaller(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_Greater(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_SmallerOrEqual(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]

    def visit_GreaterOrEqual(self, node):
        return [node.op, self.visit(node.left), self.visit(node.right)]


class Evaluator(ExpressionVisitor):

    def __init__(self, **env):
        self.env = env

    def visit_Variable(self, node):
        return self.env[node.name]

    def visit_Number(self, node):
        return node.value

    def visit_Multiplication(self, node):
        return self.visit(node.left) * self.visit(node.right)

    def visit_Addition(self, node):
        return self.visit(node.left) + self.visit(node.right)

    def visit_Smaller(self, node):
        return self.visit(node.left) < self.visit(node.right)

    def visit_Greater(self, node):
        return self.visit(node.left) > self.visit(node.right)

    def visit_SmallerOrEqual(self, node):
        return self.visit(node.left) <= self.visit(node.right)

    def visit_GreaterOrEqual(self, node):
        return self.visit(node.left) >= self.visit(node.right)


class Namespace(dict):

    def __missing__(self, key):
        value = self[key] = Variable(key)
        return value


def main():
    constraints = '2*a + 3*b <= c'
    namespace = Namespace()
    tree = eval(constraints, {}, namespace)
    print('AST in prefix notation:', tree)
    print()
    print('Namespace:', namespace)
    print()
    print('LP-Transformed tree:')
    import pprint
    pprint.pprint(LpTransformer().visit(tree))
    print()
    print('Evaluated with a=3, b=5, c=10:')
    pprint.pprint(Evaluator(a=3, b=5, c=10).visit(tree))
    print()
    print('Evaluated with a=3, b=5, c=100:')
    pprint.pprint(Evaluator(a=3, b=5, c=100).visit(tree))


if __name__ == '__main__':
    main()

結果:

AST in prefix notation: (<= (+ (* 2 a) (* 3 b)) c)    

Namespace: {'a': Variable(a), 'c': Variable(c), 'b': Variable(b)}

LP-Transformed tree:
['<=',
 ['+',
  ['*', 2, LpVariable(a, None, None, LpContinuous)],
  ['*', 3, LpVariable(b, None, None, LpContinuous)]],
 LpVariable(c, None, None, LpContinuous)]

Evaluated with a=3, b=5, c=10:
False

Evaluated with a=3, b=5, c=100:
True

クラスは明らかにLpVariableモックアップです。また、このLpTransformerクラスは、pulp で使用できるものを生成する必要があります。visit_*それに応じてメソッドを変更するだけです。

数値はすべてints であり、望ましくない場合があります。おそらくfloats を追加するか、すべての数値を に変換する必要がありますdecimal.Decimal

使用する代わりにeval()、おそらく pyparsing を使用して、またはそのようなもので私のお気に入りの Parcon を使用して、実際のパーサーを作成するでしょう。

于 2014-11-17T01:40:17.177 に答える
0

置く

entryS = "" 

while ループの前。

于 2012-12-06T20:43:20.817 に答える