Print scalar values - pyomo

Does anybody know why scalar type parameter values are not printable? I have the following code:
dtab = {
('seattle', 'new-york') : 2.5,
('seattle', 'chicago') : 1.7,
('seattle', 'topeka') : 1.8,
('san-diego','new-york'): 2.5,
('san-diego','chicago') : 1.8,
('san-diego','topeka') : 1.4,
}
model.d = Param(model.i, model.j, initialize=dtab, doc='Distance in thousands of miles')
model.f = Param(initialize=90, doc='Freight in dollars per case per thousand miles')
print model.d.values()
print model.f.values()
When i run it i get the following results:
[1.4, 1.8, 2.5, 2.5, 1.8, 1.7]
[<pyomo.core.base.param.SimpleParam object at 0x000000000B018438>]
Can anybody help i realy need to be able to print scalars for debugging.

This is due to a memory optimization that happens for immutable indexed Params. You would see the same behavior as the singleton case if mutable=True was used to initialize the indexed Param. The suggested way of accessing the value of any Param is to use the value function provided by Pyomo. E.g.,
print([value(v) for v in model.d.values()])
print([value(v) for v in model.f.values()])

Related

Unable to get the numerical result for a tanh function in Sympy

I am a python newbie. I am trying to get the two numerical results of the convection formula, but the best code I've created outputs a symbolic list containing the 'Lc' parameter, and not the expected numerical result. Anyone could give me a helping hand, please?
from sympy import var, tanh, solve
def convection ():
m = 0.9
Lc = var('Lc')
rend = 0.8
f = tanh(m*Lc)/(m*Lc)-rend
return solve(f,[m,Lc,rend],positive=True)
# Gotten : [(0.900000000000000, Lc, 1.11111111111111*tanh(0.9*Lc)/Lc)]
# Expected : [0.9, 0.986709867, 0.8] (or something like that)
Thank you in advance.
Your equation is:
In [33]: m = 0.9
In [34]: Lc = Symbol('Lc')
In [35]: rend = 0.8
In [36]: f = tanh(m*Lc)/(m*Lc)-rend
In [37]: f
Out[37]:
1.11111111111111⋅tanh(0.9⋅Lc)
-0.8 + ─────────────────────────────
Lc
The solve function is intended to find analytic solutions but that is often impossible for a transcendental equation such as this.
You are calling solve and asking it to solve for m and rend as well which is just confusing things. You should call it like:
In [38]: solve(f, Lc)
---------------------------------------------------------------------------
NotImplementedError
...
NotImplementedError: multiple generators [Lc, exp(Lc/10)]
No algorithms are implemented to solve equation -4/5 + 10*(exp(9*Lc/10) - exp(-9*Lc/10))/(9*Lc*(exp(9*Lc/10) + exp(-9*Lc/10)))
This fails because the transcendental equation can not be solved in explicit analytic form.
Instead if what you want is a numeric solution you can find that using nsolve:
In [41]: nsolve(f, Lc, 1)
Out[41]: 0.986683032622042
In [42]: nsolve(f, Lc, -1)
Out[42]: -0.986683032622042
Here we have to use an initial guess (e.g. 1 or -1) to seed the numeric solver but then we get a numeric answer.

How to sympify initial conditions for ODE in sympy?

I am passing initial conditions as string, to be used to solving an ODE in sympy.
It is a first order ode, so for example, lets take initial conditions as y(0):3 for example. From help
ics is the set of initial/boundary conditions for the differential
equation. It should be given in the form of {f(x0): x1,
f(x).diff(x).subs(x, x2): x3}
I need to pass this to sympy.dsolve. But sympify(ic) gives an error for some reason.
What other tricks to use to make this work? Here is MWE. First one shows it works without initial conditions being string (normal mode of operation)
from sympy import *
x = Symbol('x')
y = Function('y')
ode = Eq(Derivative(y(x),x),1+2*x)
sol = dsolve(ode,y(x),ics={y(0):3})
gives sol Eq(y(x), x**2 + x + 3)
Now the case when ics is string
from sympy import *
ic = "y(0):3"
x = Symbol('x')
y = Function('y')
ode = Eq(Derivative(y(x),x),1+2*x)
sol = dsolve(ode,y(x),ics={ sympify(ic) })
gives
SympifyError: Sympify of expression 'could not parse 'y(0):3'' failed,
because of exception being raised: SyntaxError: invalid syntax
(, line 1)
So looking at sympify webpage
sympify(a, locals=None, convert_xor=True, strict=False, rational=False, evaluate=None)
And tried changing different options as shown above, still the syntax error shows up.
I also tried
sol = dsolve(ode,y(x),ics= { eval(ic) } )
But this gives syntax error as well
Is there a trick to use to convert this initial conditions string to something sympy is happy with?
Python 4.7 with sympy 1.5
As temporary work around, currently I do this
from sympy import *
ic = "y(0):3"
ic = ic.split(":")
x = Symbol('x')
y = Function('y')
ode = Eq(Derivative(y(x),x),1+2*x)
sol = dsolve(ode,y(x),ics= {S(ic[0]):S(ic[1])} )
Which works. So the problem is with : initially, sympify (or S) do not handle : it seems.
You can use sympify('{y(0):3}').
I don't know what your actual goal is but I don't recommend parsing strings like this in general. The format for ICs is actually slightly awkward so that for a second order ODE it looks like:
ics = '{y(0):3, y(x).diff(x).subs(x, 0):1}'
If you're parsing a string then you can come up with a better syntax than that like
ics = "y(0)=3, y'(0)=1"
Also you should use parse_expr rather than converting strings with sympify or S:
https://docs.sympy.org/latest/modules/parsing.html#sympy.parsing.sympy_parser.parse_expr

I need a code which sums different numbers

I got a very difficult assignment as I am new to python, I hope you will be able to help me.
I wrote this code:
def hours_per_student(student_course,course_hours):
new={}
for key in student_course.keys():
for val in student_course.values():
for m in range(len(val)):
if not new.has_key(key):
new[key]=course_hours[val[m]]
else:
new[key]=new[key]+course_hours[val[m]]
return new
for these dictionaries:
student_course = {'rina' : ['math', 'python'], 'yossi' : ['chemistry', 'biology'], 'riki' : ['python']}
course_hours = {'math' : 4, 'python' : 4, 'chemistry' : 6, 'biology' : 5}
And I need to get this:
hours_per_student(student_course, course_hours)
to return this:
{'rina': 8, 'yossi': 11, 'riki': 4}
But I keep getting identical numbers for each key.
You shouldn't be iterating over .values() if you're already iterating over .keys(), just use the key to get the value. Or where you have for m in len(val), just do for m in val and then reference m instead of val[m](the naming here stinks but I discuss that later). Python is much better at iteration than that. For instance, instead of the line
for val in student_course.values():
you should try something like
for courses in student_course[key]:
for course in courses:
if key not in new:
new[key] = course_hours[course]
else:
new[key] += course_hours[course]
Naming your variables intelligently will make it easier for you to keep track of what's happening. For example, each value in student_course is a list of courses, so you should name it that, not something ambiguous like val. Similarly, each element in courses is the name of a course, so name it as such.
Here you go:
solution = {student: sum([hours.get(course, 0) for course in s_courses]) for student, s_courses in student_course.items()}
Here are the things I found lacking in your code:
When iterating over your students, you could have just created a key for each of them, and then add the hours per course.
Naming variables so you understand what they mean is confused, refrain from using new, key or val.
You don't have to use keys() function, iterating a dictionary using for key in dictionary works the same way.
Here's a fixed code snippet:
def hours_per_student(students, course_hours):
total_hours = {}
for student in students:
courses = students[student]
total_hours[student] = 0
for course in courses:
total_hours[student] += course_hours[course]
return total_hours

Tensorflow: list of tuples as placeholder

I want to use compute_gradients and generate local gradients. These gradients are to be averaged with multiple local gradients from other machines after which apply_gradients will be called. I am using 2 session.runs with a feed_dict in the second one that accepts gradients. Since apply_gradients expects a list of tuples, I am looking for an efficient way to do this.
This is how I am generating the list of tuples placeholder :
grads = cifar10.train_part1(loss, global_step)
xx = [tf.placeholder(tf.float32, shape=grads[0][0].shape) for i in range(10)]
yy = [tf.placeholder(tf.float32, shape=grads[0][0].shape) for i in range(10)]
xyz = zip(xx,yy)
train_op = cifar10.train_part2(loss,global_step, xyz)
I get the following error :
NotImplementedError: ('Trying to optimize unsupported type ', tf.Tensor 'Placeholder_10:0' shape=(5, 5, 3, 64) dtype=float32)

difflib.get_close_matches GET SCORE

I am trying to get the score of the best match using difflib.get_close_matches:
import difflib
best_match = difflib.get_close_matches(str,str_list,1)[0]
I know of the option to add 'cutoff' parameter, but couldn't find out how to get the actual score after setting the threshold.
Am I missing something? Is there a better solution to match unicode strings?
I found that difflib.get_close_matches is the simplest way for matching/fuzzy-matching strings. But there are a few other more advanced libraries like fuzzywuzzy as you mentioned in the comments.
But if you want to use difflib, you can use difflib.SequenceMatcher to get the score as follows:
import difflib
my_str = 'apple'
str_list = ['ape' , 'fjsdf', 'aerewtg', 'dgyow', 'paepd']
best_match = difflib.get_close_matches(my_str,str_list,1)[0]
score = difflib.SequenceMatcher(None, my_str, best_match).ratio()
In this example, the best match between 'apple' and the list is 'ape' and the score is 0.75.
You can also loop through the list and compute all the scores to check:
for word in str_list:
print "score for: " + my_str + " vs. " + word + " = " + str(difflib.SequenceMatcher(None, my_str, word).ratio())
For this example, you get the following:
score for: apple vs. ape = 0.75
score for: apple vs. fjsdf = 0.0
score for: apple vs. aerewtg = 0.333333333333
score for: apple vs. dgyow = 0.0
score for: apple vs. paepd = 0.4
Documentation for difflib can be found here: https://docs.python.org/2/library/difflib.html
To answer the question, the usual route would be to obtain the comparative score for a match returned by get_close_matches() individually in this manner:
match_ratio = difflib.SequenceMatcher(None, 'aple', 'apple').ratio()
Here's a way that increases speed in my case by about 10% ...
I'm using get_close_matches() for spellcheck, it runs SequenceMatcher() under the hood but strips the scores returning just a list of matching strings. Normally.
But with a small change in Lib/difflib.py currently around line 736 the return can be a dictionary with scores as values, thus no need to run SequenceMatcher again on each list item to obtain their score ratios. In the examples I've shortened the output float values for clarity (like 0.8888888888888888 to 0.889). Input n=7 says to limit the return items to 7 if there are more than 7, i.e. the highest 7, and that could apply if candidates are many.
Current mere list return
In this example result would normally be like ['apple', 'staple', 'able', 'lapel']
... at the default cutoff of .6 if omitted (as in Ben's answer, no judgement).
The change
in difflib.py is simple (this line to the right shows the original):
return {v: k for (k, v) in result} # hack to return dict with scores instead of list, original was ... [x for score, x in result]
New dictionary return
includes scores like {'apple': 0.889, 'staple': 0.8, 'able': 0.75, 'lapel': 0.667}
>>> to_match = 'aple'
>>> candidates = ['lapel', 'staple', 'zoo', 'able', 'apple', 'appealing']
Increasing minimum score cutoff/threshold from .4 to .8:
>>> difflib.get_close_matches(to_match, candidates, n=7, cutoff=.4)
{'apple': 0.889, 'staple': 0.8, 'able': 0.75, 'lapel': 0.667, 'appealing': 0.461}
>>> difflib.get_close_matches(to_match, candidates, n=7, cutoff=.7)
{'apple': 0.889, 'staple': 0.8, 'able': 0.75}
>>> difflib.get_close_matches(to_match, candidates, n=7, cutoff=.8)
{'apple': 0.889, 'staple': 0.8}