I am working on a project using PuLP and I am trying to create a terminal prompt to allow users to input their data and then my Python program will change the input to code readable by PuLP. To do this I must allow users to input:
2*a + 3*b <= c
and my code will eval() this code as well as creating variables a, b and c such
a = LpVariable("a",None,None,LpContinuous)
b = LpVariable("b",None,None,LpContinuous)
c = LpVariable("c",None,None,LpContinuous)
any ideas? I've tried using exec() but it does not seem to like this much.
at the moment I'm getting the input via:
print "Please enter your constraints 1 at a time and enter '#' when done:"
control = True
while (control):
entry = raw_input('-->')
entryS = ""
entryS += entry
so the string 2*a+3*B <= c is stored as entryS
Using eval() might not be such a good idea, but if you insist (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()
Result:
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
The LpVariable class is obviously a mockup. Also, the LpTransformer class should produce something that's usable by pulp. Just change the visit_* methods accordingly.
Numbers are all ints, which you might not want. You should probably add floats and/or convert all numbers to decimal.Decimal.
Instead of using eval() I'd probably write a real parser, maybe with pyparsing, or, my favorite for stuff like that, Parcon.
Put
entryS = ""
before the while loop.
Related
I am trying to write a function that returns the variables contained in a class of type Rule. I need to iterate through it and get all variables and store them in a set.
class Rule:
# head is a function
# body is a *list* of functions
def __init__(self, head, body):
self.head = head
self.body = body
def __str__(self):
return str(self.head) + ' :- ' + str(self.body)
def __eq__(self, other):
if not isinstance(other, Rule):
return NotImplemented
return self.head == other.head and self.body == other.body
def __hash__(self):
return hash(self.head) + hash(self.body)
class RuleBody:
def __init__(self, terms):
assert isinstance(terms, list)
self.terms = terms
def separator(self):
return ','
def __str__(self):
return '(' + (self.separator() + ' ').join(
list(map(str, self.terms))) + ')'
def __eq__(self, other):
if not isinstance(other, RuleBody):
return NotImplemented
return self.terms == other.terms
def __hash__(self):
return hash(self.terms)
My function is the following:
def variables_of_clause (self, c : Rule) -> set :
returnSet = set()
l = getattr(c, 'body')
for o in l:
returnSet.add(o)
Testing function
# The variables in a Prolog rule p (X, Y, a) :- q (a, b, a) is [X; Y]
def test_variables_of_clause (self):
c = Rule (Function ("p", [Variable("X"), Variable("Y"), Atom("a")]),
RuleBody ([Function ("q", [Atom("a"), Atom("b"), Atom("a")])]))
#assert
(self.variables_of_clause(c) == set([Variable("X"), Variable("Y")]))
I keep getting an error that says: TypeError: 'RuleBody' is not iterable.
RuleBody.terms is a list, not RuleBody, you can iterate over RuleBody.terms instead, however, you can make your RuleBody class iterable (by basically making it return RuleBody.terms's elements), using the __iter__ method:
class RuleBody:
... # everything
...
def __iter__(self):
return iter(self.terms)
class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class2 = Cat(class1.number * 0.5)
class1.number_update()
print(class1.number)
print(class2.number)
Current output: 2, 0.5
I want: 2, 1
I really simplified it, so I hope you will understand
Thank you for help
You are running class1.number_update() after you define the class2 variable, so the class1 variable has a value of 1 when you define class2, and after you define class2, class1 becomes into 2. To fix this, just switch around those two lines:
class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class1.number_update()
class2 = Cat(class1.number * 0.5)
print(class1.number)
print(class2.number)
You could return the number in number_update():
class Dog(object):
def __init__(self, number):
self.number = number
def number_update(self):
self.number += 1
return self.number
class Cat(object):
def __init__(self, number):
self.number = number
class1 = Dog(1)
class2 = Cat(class1.number_update() * .5)
print(class1.number)
print(class2.number)
Output:
2
1.0
As suggested in the comments, to do this exactly as you want, you'll have to write your own expression and number classes, such as this:
class Op:
def __init__(self, op):
self.op = op
def __call__(self, a, b):
if self.op == "*":
return a * b
if self.op == "/":
return a / b
if self.op == "-":
return a - b
if self.op == "+":
return a + b
raise TypeError(f"Unknown op {repr(self.op)}")
def __repr__(self):
return self.op
mul = Op("*")
div = Op("/")
add = Op("+")
sub = Op("-")
class Expr:
def __init__(self, a, b, op):
self.op = op
self.a = a
self.b = b
def eval(self):
return self.op(self.a.eval(), self.b.eval())
def __repr__(self):
return f"({self.a} {self.op} {self.b})"
def __mul__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, mul)
def __div__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, div)
def __add__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, add)
def __sub__(self, other):
if isinstance(other, (int, float)):
b = Number(other)
else:
b = other
a = self
return Expr(a, b, sub)
def __rmul__(self, other):
return self.__class__.__mul__(other, self)
def __rdiv__(self, other):
return self.__class__.__div__(other, self)
def __rsub__(self, other):
return self.__class__.__sub__(other, self)
def __radd__(self, other):
return self.__class__.__add__(other, self)
class Number(Expr):
def __init__(self, value):
self._value = value
def get(self):
return self._value
def set(self, new):
self._value = new
def increment(self):
self._value += 1
def eval(self):
return self._value
def __repr__(self):
return str(self._value)
class Dog:
def __init__(self, number):
self.number = Number(number)
def number_update(self):
self.number.increment()
class Cat:
def __init__(self, number):
self._number = number
#property
def number(self):
return self._number.eval()
#number.setter
def number(self, new):
if isinstance(new, (int, float)):
new = Number(new)
self._number = new
cls1 = Dog(1)
cls2 = Cat(cls1.number * 0.5)
cls1.number_update()
print(cls1.number)
print(cls2.number)
Here, we get the expected output of
2
1.0
Lets go through the lines of your main function and trace the values of Dog and Cat
class1 = Dog(1) # Dog=1; Cat=undefined
class2 = Cat(class1.number * 0.5) # Dog=1; Cat=1*0.5=0.5
class1.number_update() # Dog=2; Cat=0.5
print(class1.number) # >>>"2"
print(class2.number) # >>>"0.5"
Your class doesn't have a reference to Dog's number member, it just references the Cat class property.
EDIT: It doesn't copy, it creates a reference directly to the object.
We have some variable, or other instance: a='?'.
We have such input:
f = a(3112).bas(443).ssad(34)
When we type
print(f)
Output should be:
3112a-443bas-34ssad
I've tried some ways to solve this and have found information about chaining, but I still have the problem. I can't return class name to the brginning of the string.
This, what I have:
class A():
def __getattribute__(self, item):
print (str(item))
return super(A, self).__getattribute__(item)
def __init__(self, x):
self.x = x
print (str(x))
def b(self, item):
print (str(item))
return self
def c(self, item):
print (str(item))
return self
def d(self, item):
print (str(item))
return self
A(100).b(200).c(300).d(400)
My output:
100
b
200
c
300
d
400
But I couldn't concatenate it in one string.
Dynamic way
class A(object):
def __init__(self, integer):
self._strings = ['{}a'.format(integer)]
def __getattr__(self, attrname, *args):
def wrapper(*args, **kwargs):
self._strings.append('{}{}'.format(args[0], attrname))
return self
return wrapper
def __str__(self):
return '-'.join(self._strings)
print(A(100).bas(200).ssad(300))
Output
100a-200bas-300ssad
But also
print(A(100).egg(200).bacon(300).SPAM(1000))
Output
100a-200egg-300bacon-1000SPAM
Static way
class A(object):
def __init__(self, integer):
self._strings = ['{}a'.format(integer)]
def bas(self, integer):
self._strings.append('{}bas'.format(integer))
return self
def ssad(self, integer):
self._strings.append('{}ssad'.format(integer))
return self
def __str__(self):
return '-'.join(self._strings)
print(A(100).b(200).c(300))
Output
100a-200bas-300ssad
More about __str__
You can override the __str__ method to define your specific output:
class A():
def __init__(self, a, b="", c="", d=""):
self._a = a
self._b = b
self._c = c
self._d = d
def __str__(self):
return '{}a-{}b-{}c-{}d'.format( self.a, self.b, self.c, self.d )
def b(self, item):
self._b = item
return self
def c(self, item):
self._c = item
return self
def d(self, item):
self._d = item
return self
f = A(100).b(200).c(300).d(400)
print(f) # 100a-200b-300c-400d
Here I tried it in another way , ie, If you want to take the function name instead of manually giving it you can use inspect in python. Try this code :
import inspect
class A():
l = []
def __init__(self, x):
self.x = x
print (str(x))
self.l.append(str(x) + "a")
def b(self, item):
print (str(item))
self.l.append(str(item) + inspect.stack()[0][3])
return self
def c(self, item):
print (str(item))
self.l.append(str(item) + inspect.stack()[0][3])
return self
def d(self, item):
print (str(item))
self.l.append(str(item) + inspect.stack()[0][3])
return self
print("-".join(A(100).b(200).c(300).d(400).l))
The o/p is like :
'100a-200b-300c-400d'
I want to write a program that accepts as input a number p and produces as output a type-constructor for a number that obeys integer arithmetic modulo p.
So far I have
def IntegersModP(p):
N = type('IntegersMod%d' % p, (), {})
def __init__(self, x): self.val = x % p
def __add__(a, b): return N(a.val + b.val)
... (more functions) ...
attrs = {'__init__': __init__, '__add__': __add__, ... }
for name, f in attrs.items():
setattr(N, name, f)
return N
This works fine, but I'd like to know what the Pythonic way to do this is, which I understand would use metaclasses.
Like this:
def IntegerModP(p): # class factory function
class IntegerModP(object):
def __init__(self, x):
self.val = x % p
def __add__(a, b):
return IntegerModP(a.val + b.val)
def __str__(self):
return str(self.val)
def __repr__(self):
return '{}({})'.format(self.__class__.__name__, self.val)
IntegerModP.__name__ = 'IntegerMod%s' % p # rename created class
return IntegerModP
IntegerMod4 = IntegerModP(4)
i = IntegerMod4(3)
j = IntegerMod4(2)
print i + j # 1
print repr(i + j) # IntegerMod4(1)
Metaclasses are for when your class needs to behave differently from a normal class or when you want to alter the behavior of the class statement. Neither of those apply here, so there's really no need to use a metaclass. In fact, you could just have one ModularInteger class with instances that record their value and modulus, but assuming you don't want to do that, it's still easy to do this with an ordinary class statement:
def integers_mod_p(p):
class IntegerModP(object):
def __init__(self, n):
self.n = n % IntegerModP.p
def typecheck(self, other):
try:
if self.p != other.p:
raise TypeError
except AttributeError:
raise TypeError
def __add__(self, other):
self.typecheck(other)
return IntegerModP(self.n + other.n)
def __sub__(self, other):
...
IntegerModP.p = p
IntegerModP.__name__ = 'IntegerMod{}'.format(p)
return IntegerModP
I have a class in which I store data in a list for inheritance reasons. I would like to know, and I have done my share of googling, is there a cleaner way other than creating getter/setter functions and properties to give a alias to the element in this list?
For example...
class Serializable(object):
"""Adds serialization to from binary string"""
def encode(self):
"""Pack into struct"""
return self.encoder.pack(*self)
def decode(self, data_str):
"""Unpack from struct"""
self.data = self.encoder.unpack(data_str)
return self.data
class Ping(Serializable):
encoder = Struct("!16sBBBL")
def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
self.data = [ident, 1, ttl, hops, length]
self.ident = property(self.data[0])
def __getitem__(self, index):
return self.data[index]
#property
def ident(self):
return self.data[0]
#ident.setter
def ident(self, value):
self.data[0] = value
#property
def protocol(self):
return self.data[1]
#protocol.setter
def protocol(self, protocol):
self.data[1]
I would prefer a more compact solution to reference object.ident while maintaining the ability to pack and unpack as above.
If you store your values/properties in a dictionary instead:
def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
self.data = {
'ident': ident,
'protocol': 1,
'ttl': hops,
'length': length,
}
And then override __getattr__ and __setattr__:
def __getattr__(self, attr):
return self.data[attr]
def __setattr__(self, attr, value):
if attr == 'data':
object.__setattr__(self, attr, value)
else:
self.data[attr] = value
Now you can do this:
>>> ping = Ping()
>>> ping.protocol
1
>>> ping.protocol = 2
>>> ping.protocol
2
If self.data absolutely has to be a list, you can do this instead:
class Ping(Serializable):
mapping = ('ident', 'protocol', 'ttl', 'hops', 'length')
encoder = Struct("!16sBBBL")
def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
self.data = [ident, 1, ttl, hops, length]
def __getitem__(self, index):
return self.data[index]
def __getattr__(self, attr):
index = self.mapping.index(attr)
return self.data[index]
def __setattr__(self, attr, value):
if attr == 'data':
object.__setattr__(self, attr, value)
else:
index = self.mapping.index(attr)
self.data[index] = value
def alias_property(key):
return property(
lambda self: getattr(self, key),
lambda self, val: setattr(self, key, val),
lambda self: delattr(self, key))
class A(object):
def __init__(self, prop):
self.prop = prop
prop_alias = alias_property('prop')
If your problem is just shorten the code to access ident, you may just use "property" in the "old style" - that is, you pass to it, as parameters, the getter and setter functions, instead of using it as a decorator.
In this case, the functions are so small, they can be lambda functions, without affecting code readbility.
class Ping(Serializable):
encoder = Struct("!16sBBBL")
def __init__(self, ident=None, ttl=TTL, hops=0, length=0):
if ident is None:
ident = create_id()
self.data = [ident, 1, ttl, hops, length]
# The line bellow looks like garbage -
# it does not even make sense as a call to `property`
# should have a callable as first parameter
# returns an object that is designed to work as a class attribute
# self.ident = property(self.data[0])
# rather:
self.ident = ident
# this will use the property defined bellow
def __getitem__(self, index):
return self.data[index]
ident = property(lambda s: s.data[0], lambda s, v: s.data[0].__setitem__(0, v)
protocol = property(lambda s: s.data[1], lambda s, v: s.data[1].__setitem__(1, v)