2012-12-06 145 views
0

我正在使用PuLP進行項目工作,我試圖創建終端提示符以允許用戶輸入他們的數據,然後我的Python程序將輸入更改爲PuLP可讀的代碼。要做到這一點,我必須允許用戶輸入:允許用戶輸入變量(Python)

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

+1

你現在怎麼從終端獲取輸入? – munk

+0

我首先輸入整個字符串,然後你必須檢查每個「字母」,看看它是一個字符,int oder運算符,然後聲明一個匹配變量。 – Lotzki

+0

@usmcs更新了問題,對不起。 – user1883573

回答

0

字符串將

entryS = "" 
在while循環之前的

+0

用戶將輸入一組PuLP(一個用於python的線性編程包) 一次一個。但是,PuLP需要你單獨聲明變量,所以我想遍歷輸入來嘗試找到變量並將它們放入第二種類型的代碼中。對不起,如果我沒有解釋得很好,我是新來的。所以entryS必須重置爲每個輸入。 – user1883573

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課程應該生產一些紙漿可用的東西。只需相應地更改visit_*方法。

數字都是int s,你可能不想要。您應該添加float和/或將所有數字轉換爲decimal.Decimal

而不是使用eval()我可能會寫一個真正的解析器,也許用pyparsing,或者,我喜歡這樣的東西,Parcon。