how to pass expression as argument to a function without evaluating it - python-3.x

First, see the relevant user code for running z3-solver. This works fine, and the solver returns some values after evaluating the expression:
# see source at https://github.com/Z3Prover/z3
# the relevant code is at: z3-master/src/api/python/z3/z3.py
# pip install z3-solver
from z3 import *
x = Int('x')
#print(type(x)) # <class 'z3.z3.ArithRef'>
y = Int('y')
s = Solver()
# print(type(s)) # <class 'z3.z3.Solver'>
s.add(x > 10) # this works
s.add(y == x + 2)
print(s)
print(s.check())
print(s.model())
Now, my short attempt at writing an evaluator like z3:
class Int():
def __init__(self,name):
self.name = name
self.value = None
def do_print(self):
print('Rand({})'.format(self.name))
def __str__(self):
return(str(self.value))
class Solver():
def add(self, *argv):
self.args = []
for arg in argv:
self.args.append(arg)
def do_print(self):
print('Constr(',end='')
for arg in self.args:
print(arg)
print(')')
x = Int('x')
s=Solver()
s.add(x > 10) # this does not work - but why is same kind of code in z3 working?
# err: TypeError: '<' not supported between instances of 'Int' and 'int'
x.do_print()
s.do_print()
I am getting an error on the s.add() line. I understand the error, that the object 'x' cannot be compared with an integer. This is happening because the expression in this line is getting evaluated before the s.add() is being called.
But my question is - how is z3-solver bypassing this error? How is it able to pass the args to add() without evaluating it first?
How do I fix the problem in my code, and pass the expression to s.add() without evaluating it first?

Related

Why error: "must be real number, not RestMode"? How can fix it?

I'm using ROS, and writing some codes to do some tasks, and now I'm facing an error: TypeError: must be real number, not RestMode, for more details, I have code here:
#!/usr/bin/env python
#encoding: utf-8
import rospy
from geometry_msgs.msg import Vector3
from sensor_msgs.msg import Imu
from std_msgs.msg import Float64
import numpy as np
import geometry as geo
import transformation as tf
from IK_solver import IK
class RestMode:
def __init__(self, bodyDimensions, legDimensions):
# rospy.Subscriber('spot_keyboard/body_pose',Vector3,self.callback)
self.bodyLength = bodyDimensions[0]
self.bodyWidth = bodyDimensions[1]
self.bodyHeight = bodyDimensions[2]
self.l1 = legDimensions[0]
self.l2 = legDimensions[1]
self.l3 = legDimensions[2]
# rospy.Subscriber('spot_imu/base_link_orientation',Imu, self.get_body_pose)
self.rate = rospy.Rate(10.0) #10Hz
self.rb = IK(bodyDimensions, legDimensions)
angles_cmd = [ 'spot_controller/FL1_joint/command',
'spot_controller/FL2_joint/command',
'spot_controller/FL3_joint/command',
'spot_controller/RL1_joint/command',
'spot_controller/RL2_joint/command',
'spot_controller/RL3_joint/command',
'spot_controller/RR1_joint/command',
'spot_controller/RR2_joint/command',
'spot_controller/RR3_joint/command',
'spot_controller/FL1_joint/command',
'spot_controller/FL2_joint/command',
'spot_controller/FL3_joint/command' ]
self.joint = []
for i in range(12):
self.joint.append(rospy.Publisher(angles_cmd[i], Float64, queue_size=10))
# self.initial_pose()
def initial_pose(self,roll=0,pitch=0,yaw=0,dx=0,dy=0,dz=None):
if dz == None:
dz = self.bodyHeight
order = ['FL','RL','RR','FR']
angles = []
rospy.loginfo("Start Calculate Angles!")
for leg in order:
(q1,q2,q3,ht) = self.rb.calculateAngles(self,roll,pitch,yaw,dx,dy,dz,leg)
angles.append(q1)
angles.append(q2)
angles.append(q3)
rospy.loginfo("Done! Start publish!")
for i in range(12):
self.joint[i].publish(angles[i])
self.rate.sleep()
if __name__ == '__main__':
rospy.init_node('rest_mode', anonymous=True)
body = [0.1908, 0.080, 0.15]
legs = [0.04, 0.1, 0.094333]
rest = RestMode(body, legs)
try:
while not rospy.is_shutdown():
rest.initial_pose()
except rospy.ROSInterruptException:
pass
When method calculateAngles(self,roll,pitch,yaw,dx,dy,dz,leg) with argument leg in last, it throws: TypeError: must be real number, not RestMode.
But when I change it to first like: calculateAngles(self,leg,roll,pitch,yaw,dx,dy,dz), then error says: TypeError: must be real number, not str with input in another module, but I tested all of the others related module, and they are fine, so I think that must be an issue in codes above!
That error is so strange:
I don't push any str as input
When changing the position of argument leg, it throws a different error.
When calling instance methods, self is an implied parameter, and should never be explicitly passed. When you are using self.rb.calculateAngles(self, ..., that second self is an instance of a RestMode class, which your IK class does not accept...
Therefore, you want
(q1,q2,q3,ht) = self.rb.calculateAngles(roll,pitch,yaw,dx,dy,dz,leg)
And change other usages within the IK class as well

Exception Handling Error: TypeError: can only concatenate list (not "odict_keys") to list

I was running pytest and using someone else's exception handling library. It supposed to run older version of python, not sure which one. However when I try to run it with python3, it spouted error that I didn't understand, also for some reason I have trouble finding the meaning of the keyword error (odict_keys) in the web.
The following was the result from the pytest. The exception handling inside test_analysis procedure was calling run_with_timeout(timeoutwrapper_analysis,max_seconds_per_call,(),{}) before the error occurred here. Inside run_with_timeout, the error happened when it raised e as an exception:
#pytest.mark.parametrize("inputs,outputs,description", portfolio_test_cases)
def test_analysis(inputs, outputs, description, grader):
"""Test get_portfolio_value() and get_portfolio_stats() return correct values.
Requires test inputs, expected outputs, description, and a grader fixture.
"""
points_earned = 0.0 # initialize points for this test case
try:
# Try to import student code (only once)
if not main_code in globals():
import importlib
# * Import module
mod = importlib.import_module(main_code)
globals()[main_code] = mod
# Unpack test case
start_date_str = inputs['start_date'].split('-')
start_date = datetime.datetime(int(start_date_str[0]),int(start_date_str[1]),int(start_date_str[2]))
end_date_str = inputs['end_date'].split('-')
end_date = datetime.datetime(int(end_date_str[0]),int(end_date_str[1]),int(end_date_str[2]))
symbols = inputs['symbol_allocs'].keys() # e.g.: ['GOOG', 'AAPL', 'GLD', 'XOM']
allocs = inputs['symbol_allocs'].values() # e.g.: [0.2, 0.3, 0.4, 0.1]
start_val = inputs['start_val']
risk_free_rate = inputs.get('risk_free_rate',0.0)
# the wonky unpacking here is so that we only pull out the values we say we'll test.
def timeoutwrapper_analysis():
student_rv = analysis.assess_portfolio(\
sd=start_date, ed=end_date,\
syms=symbols,\
allocs=allocs,\
sv=start_val, rfr=risk_free_rate, sf=252.0, \
gen_plot=False)
return student_rv
# Error happen in the following line:
result = run_with_timeout(timeoutwrapper_analysis,max_seconds_per_call,(),{})
grade_analysis.py:176:
func = .timeoutwrapper_analysis at 0x7f8c458347b8>, timeout_seconds = 5, pos_args = (), keyword_args = {}
def run_with_timeout(func,timeout_seconds,pos_args,keyword_args):
rv_dict = timeout_manager.dict()
p = multiprocessing.Process(target=proc_wrapper,args=(func,rv_dict,pos_args,keyword_args))
p.start()
p.join(timeout_seconds)
if p.is_alive():
p.terminate()
raise TimeoutException("Exceeded time limit!")
if not('output' in rv_dict):
if 'exception' in rv_dict:
e = rv_dict['exception']
e.grading_traceback=None
if 'traceback' in rv_dict:
e.grading_traceback = rv_dict['traceback']
# Error occurred after the following line:
raise e
E TypeError: can only concatenate list (not "odict_keys") to list
grading.py:134: TypeError
Looks the script didn't like
raise e
statement. What is that to do with odict_keys?
regards
two of the inputs of analysis.assess_portfolio, symbols and allocs are in the forms of odic_keys. Apparently, this worked in python 2.7, however when running with python 3, they need to be in the form of list, thus changing the input statement from
symbols = inputs['symbol_allocs'].keys()
allocs = inputs['symbol_allocs'].values()
to
symbols = list(inputs['symbol_allocs'].keys())
allocs = list(inputs['symbol_allocs'].values())
fixed it

Python3 Class Syntax Error: non-default argument follows default argument

I'm messing around with Class' and I have a python3 file with the following code:
class playerstats(object):
def __init__(self, name, baselevel=1, hp, mana, basedmg=0, atkdmg, basedef=0, chardef):
self.name = name
self.baselevel = baselevel
self.hp = hp
self.mana = mana
self.basedmg = basedmg
self.atkdmg = atkdmg
self.basedef = basedef
self.chardef = chardef
return self.name, self.baselevel, self.basedmg, self.basedef
def selectedclass(self, chosenclass):
if chosenclass == 'W' or chosenclass == 'w':
self.hp = 100
self.mana = 50
elif chosenclass == 'M' or chosenclass == 'm':
self.hp = 75
self.mana = 100
else:
print('Error')
return self.hp, self.mana
charcreation = playerstats('Tom', baselevel, self.chosenclass, self.chosenclass, basedmg, 0, basedef, 0)
self.chosenclass = 'w'
print(playerstats.hp)
When I run it, I get this Error:
File "..\Playground\", line 2
def init(self, name, baselevel=1, hp, mana, basedmg=0, atkdmg, basedef=0, chardef):
^
SyntaxError: non-default argument follows default argument
Can someone help me understand why?
You need to change the order of parameters in __init__ function.
Generally, non-default argument should not follow default argument , it means you can't define (a="b",c) in function.
The order of defining parameter in function are :
positional parameter or non-default parameter i.e (a,b,c)
keyword parameter or default parameter i.e (a="bcd",r="jef")
keyword-only parameter i.e (*args)
var-keyword parameter i.e (**kwargs)

shared variable become NoneType after set the value in theano

class sharedvariable_test:
def __init__(self, sizes):
self.param = [theano.shared(p)
for p in sizes]
def update(self):
temp_p = [None] * len(self.param)
for i in range(len(self.param)):
temp_p[i] = 1
self.param = [p.set_value(tp)
for p, tp in zip(self.param, temp_p)]
for p in self.param:
print(p.get_value()) # error occurred here
after the function update, the shared variable in list self.param become NoneType, and the error message is "The NoneType has no attribute of get_value",and am I supposed to name the shared variable ? and not just put it into a list
I think
self.param = [p.set_value(tw)
for p, tw in zip(self.param, temp_w)]
is the reason that caused the error
and just to convert it to
for p, tw in zip(self.param, temp_w):
p.set_value(tw)
will be alright

Executing mathematical user inputed statements as code in Python 3

How would one allow the user to input a statement such as "math.sin(x)**2" and calculate the answer within python code.
In telling me the answer please explain why both exec() compile() are not producing the desired result.
import math
def getValue(function, x):
function = "val = " + function
#compile(function, '', 'exec')
exec(function)
print(val)
function = input("Enter a function f(x):\n")
getValue(function, 10)
Much Appreciated!
To answer your question, use eval:
>>> eval('math.sin(1)**2')
0.7080734182735712
exec is working, but you are not retrieving the result. Notice:
>>> val
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'val' is not defined
>>> exec('val=math.sin(1)**2')
>>> val
0.7080734182735712
So, using eval instead of exec works like so:
def getValue(function, x):
function = "{}({})".format(function, x)
print(function)
val=eval(function)
print(val)
That said -- it is considered an extreme security risk to execute arbitrary user code.
If you are building a calculator, a safer approach you might consider using SymPy or building your own parser using something like PyParsing (which is used in SymPy)
An example PyParsing calculator:
import sys
import operator
from pyparsing import nums, oneOf, Word, Literal, Suppress
from pyparsing import ParseException, Forward, Group
op_map = { '*' : operator.mul,\
'+' : operator.add,\
'/' : operator.div,\
'-' : operator.sub}
exp = Forward()
number = Word(nums).setParseAction(lambda s, l, t: int(t[0]))
lparen = Literal('(').suppress()
rparen = Literal(')').suppress()
op = oneOf('+ - * /').setResultsName('op').setParseAction(lambda s, l, t: op_map[t[0]])
exp << Group(lparen + op + (number | exp) + (number | exp) + rparen)
def processArg(arg):
if isinstance(arg, int):
return arg
else:
return processList(arg)
def processList(lst):
args = [processArg(x) for x in lst[1:]]
return lst.op(args[0], args[1])
def handleLine(line):
result = exp.parseString(line)
return processList(result[0])
while True:
try:
print handleLine(raw_input('> '))
except ParseException, e:
print >>sys.stderr,\
"Syntax error at position %d: %s" % (e.col, e.line)
except ZeroDivisionError:
print >>sys.stderr,\
"Division by zero error"
Which can easily be extended to include other functions.

Resources