Turning Equation Into Function? - python

I need to turn following equation into a python function.
k = people[i]
i = people[j]
costs[i][j]
costs[j][k]
change = -costs[i][k] - costs[j][l] + costs[i][l] + cost[j][k]

I think what you're looking for is:
def change(i,j,costs,people):
k = people[i]
l = people[j] # was originally i = people[j] but unsure where l comes from otherwise
result = -costs[i][k] - costs[j][l] + costs[i][l] + cost[j][k]
return result
(and then call with:
mychange = change(i,j,costs,people)
)
Note that if my assumption on where l comes from is wrong, change that 3rd line back to i = people[j] and pass in l as well.
Also note that using l as a variable is a bad idea as it's rather hard to tell apart from 1 (and also, using i,j,k,l is bad when you could use a more descriptive value to make it clearer what this means)

Related

Error while writing optimization constraint in cplex python api

My goal is to write the following model using docplex.mp.model in python. which ptj takes binary variable {0,1}.
[summation from of Ptj from j=1 to t][t = 1,.....,8]
here is the code I wrote:
N = 8
(period_list = [t for t in range(1, no_of_period+1)])
(j = period_list)
p = Mode.binary_var_dict(period_list, name = 'p')
for t in period_list:
for j in range(1,t+1):
Model.add_constraints(Model.sum(p[t,j]) == 1)
but I got an error. Could anyone help me with this problem please?
Your code has numerous issues.
First, you need to create one instance of docplex.mp.model.Model to add constraints to: all your calls to Model.<fn> should be rewritten as mdl.<fn> as they are instance methods.
Second, the variable dict you create has periods as keys, that is, 1,2,..P
so querying p[t,j] is sure to crash with KeyError. If you need a square matrix of variables for each couple of periods, use Model.binary_var_matrix.
Third: Model.add_constraints (with a final S) expects an iterable, but you are passing one constraint, this is also sure to crash.
Lastly, using ranges starting at 1 is not the simplest nor the safest choice with Docplex.
Here is a code, freely derived from your sample, which I guess is close to what you need:
pr = range(1, no_of_period+1)
from docplex.mp.model import Model
m = Model()
p = m.binary_var_matrix(pr, pr, name = 'p')
m.add_constraints( (m.sum(p[t,j] for j in pr) == 1) for t in pr)
print(m.lp_string)
and the output is:
Minimize
obj:
Subject To
c1: p_1_1 + p_1_2 + p_1_3 = 1
c2: p_2_1 + p_2_2 + p_2_3 = 1
c3: p_3_1 + p_3_2 + p_3_3 = 1
[..snip..]

Why is python code running but there is no output when using equation?

I wrote a code that works great for solving equations numerically, but there is I a specific equation that when I get in there and try running the code - it will run and no output will ever come out!
Equation I got an output for: x^3−3*x+2−a*(np.sin(x))
Equation I didn't get an output for: (x-1)(x-2)(x-3)-a*(np.cos(x))
I also tried writing the second equation without brackets, like this: x^3-6*x^2+11*x-6-a*np.cos(x)
and it didn't help. where is the problem?!
this is my code:
import math
import numpy as np
h =1e-5
eps =1e-8
#function of the equation
def nf(x,a,c):
c=math.cos(x)
solu=(x-1)*(x-2)*(x-3)-a*c
return(solu)
#numerical method
def sl(a,x):
c=math.cos(x)
f = nf(x,a,c)
while abs(f)>eps:
x = x - h*f/(nf(x+h,a,c)-f)
f = nf(x,a,c)
return(x)
N = 101
mya = np.linspace(0.0,1.0,N)
myb = np.zeros(mya.shape)
myc = np.zeros(mya.shape)
myd = np.zeros(mya.shape)
for i in range(0,N):
myb[i] = sl(mya[i],1.0)
myc[i] = sl(mya[i],2.0)
myd[i] = sl(mya[i],3.0)
print(myb[i])
print(myc[i])
print(myd[i])
The problem is that for some input to sl, abs(f)>eps might not ever become False, creating an infinite loop. I havn't investigated the mathematical problem of yours, so I can't solve this problem "for real". What I can provide is automatic detection of when this happens, so that the code returns without a result rather than looping forever.
def sl(a,x):
c=math.cos(x)
f = nf(x,a,c)
count, maxcount = 0, 1000
while abs(f)>eps:
x = x - h*f/(nf(x+h,a,c)-f)
f = nf(x,a,c)
count += 1
if count > maxcount:
return
return(x)
Here, a maximum of 1000 iterations is allowed before a solution is deemed unreachable. In such a case, sl returns None, which when inserted into your NumPy float arrays becomes np.nan.
Upon investigating the output, only myc[60] fails in this way.
Your nf function was a little weird. You were passing c = math.cos(x) into nf() but whithin nf() you tried to assign c to math.cos(x) again. Just use the value c what you passed. Commenting it out fixes your code. As for the mathematical correctness, I cannot determine that unless you provide a better explanation what youre trying to do.
import math
import numpy as np
h =1e-5
eps =1e-8
#function of the equation
def nf(x,a,c):
# this line is not needed. Commenting allows your code to run
# c=math.cos(x)
solu=(x-1)*(x-2)*(x-3)-a*c
return(solu)
#numerical method
def sl(a,x):
c = math.cos(x)
f = nf(x,a,c)
while abs(f)>eps:
x = x - h*f/(nf(x+h,a,c)-f)
f = nf(x,a,c)
return(x)
N = 101
mya = np.linspace(0.0,1.0,N)
myb = np.zeros(mya.shape)
myc = np.zeros(mya.shape)
myd = np.zeros(mya.shape)
for i in range(0,N):
myb[i] = sl(mya[i],1.0)
myc[i] = sl(mya[i],2.0)
myd[i] = sl(mya[i],3.0)
print(myb[i])
print(myc[i])
print(myd[i])
Output:
3.2036907284
0.835006605064
0.677633820877

More on dynamic programming

Two weeks ago I posted THIS question here about dynamic programming. User Andrea Corbellini answered precisely what I wanted, but I wanted to take the problem one more step further.
This is my function
def Opt(n):
if len(n) == 1:
return 0
else:
return sum(n) + min(Opt(n[:i]) + Opt(n[i:])
for i in range(1, len(n)))
Let's say you would call
Opt( [ 1,2,3,4,5 ] )
The previous question solved the problem of computing the optimal value. Now,
instead of the computing the optimum value 33 for the above example, I want to print the way we got to the most optimal solution (path to the optimal solution). So, I want to print the indices where the list got cut/divided to get to the optimal solution in the form of a list. So, the answer to the above example would be :
[ 3,2,1,4 ] ( Cut the pole/list at third marker/index, then after second index, then after first index and lastly at fourth index).
That is the answer should be in the form of a list. The first element of the list will be the index where the first cut/division of the list should happen in the optimal path. The second element will be the second cut/division of the list and so on.
There can also be a different solution:
[ 3,4,2,1 ]
They both would still lead you to the correct output. So, it doesn't matter which one you printed. But, I have no idea how to trace and print the optimal path taken by the Dynamic Programming solution.
By the way, I figured out a non-recursive solution to that problem that was solved in my previous question. But, I still can't figure out to print the path for the optimal solution. Here is the non-recursive code for the previous question, it might be helpful to solve the current problem.
def Opt(numbers):
prefix = [0]
for i in range(1,len(numbers)+1):
prefix.append(prefix[i-1]+numbers[i-1])
results = [[]]
for i in range(0,len(numbers)):
results[0].append(0)
for i in range(1,len(numbers)):
results.append([])
for j in range(0,len(numbers)):
results[i].append([])
for i in range(2,len(numbers)+1): # for all lenghts (of by 1)
for j in range(0,len(numbers)-i+1): # for all beginning
results[i-1][j] = results[0][j]+results[i-2][j+1]+prefix[j+i]-prefix[j]
for k in range(1,i-1): # for all splits
if results[k][j]+results[i-2-k][j+k+1]+prefix[j+i]-prefix[j] < results[i-1][j]:
results[i-1][j] = results[k][j]+results[i-2-k][j+k+1]+prefix[j+i]-prefix[j]
return results[len(numbers)-1][0]
Here is one way of printing the selected :
I used the recursive solution using memoization provided by #Andrea Corbellini in your previous question. This is shown below:
cache = {}
def Opt(n):
# tuple objects are hashable and can be put in the cache.
n = tuple(n)
if n in cache:
return cache[n]
if len(n) == 1:
result = 0
else:
result = sum(n) + min(Opt(n[:i]) + Opt(n[i:])
for i in range(1, len(n)))
cache[n] = result
return result
Now, we have the cache values for all the tuples including the selected ones.
Using this, we can print the selected tuples as shown below:
selectedList = []
def printSelected (n, low):
if len(n) == 1:
# No need to print because it's
# already printed at previous recursion level.
return
minVal = math.Inf
minTupleLeft = ()
minTupleRight = ()
splitI = 0
for i in range(1, len(n)):
tuple1ToI = tuple (n[:i])
tupleiToN = tuple (n[i:])
if (cache[tuple1ToI] + cache[tupleiToN]) < minVal:
minVal = cache[tuple1ToI] + cache[tupleiToN]
minTupleLeft = tuple1ToI
minTupleRight = tupleiToN
splitI = low + i
print minTupleLeft, minTupleRight, minVal
print splitI # OP just wants the split index 'i'.
selectedList.append(splitI) # or add to the list as requested by OP
printSelected (list(minTupleLeft), low)
printSelected (list(minTupleRight), splitI)
You call the above method like shown below:
printSelected (n, 0)

Python Unknown pattern finding

Okay, basically what I want is to compress a file by reusing code and then at runtime replace missing code. What I've come up with is really ugly and slow, at least it works. The problem is that the file has no specific structure, for example 'aGVsbG8=\n', as you can see it's base64 encoding. My function is really slow because the length of the file is 1700+ and it checks for patterns 1 character at the time. Please help me with new better code or at least help me with optimizing what I got :). Anything that helps is welcome! BTW i have already tried compression libraries but they didn't compress as good as my ugly function.
def c_long(inp, cap=False, b=5):
import re,string
if cap is False: cap = len(inp)
es = re.escape; le=len; ref = re.findall; ran = range; fi = string.find
c = b;inpc = inp;pattern = inpc[:b]; l=[]
rep = string.replace; ins = list.insert
while True:
if c == le(inpc) and le(inpc) > b+1: c = b; inpc = inpc[1:]; pattern = inpc[:b]
elif le(inpc) <= b: break
if c == cap: c = b; inpc = inpc[1:]; pattern = inpc[:b]
p = ref(es(pattern),inp)
pattern += inpc[c]
if le(p) > 1 and le(pattern) >= b+1:
if l == []: l = [[pattern,le(p)+le(pattern)]]
elif le(ref(es(inpc[:c+2]),inp))+le(inpc[:c+2]) < le(p)+le(pattern):
x = [pattern,le(p)+le(inpc[:c+1])]
for i in ran(le(l)):
if x[1] >= l[i][1] and x[0][:-1] not in l[i][0]: ins(l,i,x); break
elif x[1] >= l[i][1] and x[0][:-1] in l[i][0]: l[i] = x; break
inpc = inpc[:fi(inpc,x[0])] + inpc[le(x[0]):]
pattern = inpc[:b]
c = b-1
c += 1
d = {}; c = 0
s = ran(le(l))
for x in l: inp = rep(inp,x[0],'{%d}' % s[c]); d[str(s[c])] = x[0]; c += 1
return [inp,d]
def decompress(inp,l): return apply(inp.format, [l[str(x)] for x in sorted([int(x) for x in l.keys()])])
The easiest way to compress base64-encoded data is to first convert it to binary data -- this will already save 25 percent of the storage space:
>>> s = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=\n"
>>> t = s.decode("base64")
>>> len(s)
37
>>> len(t)
26
In most cases, you can compress the string even further using some compression algorithm, like t.encode("bz2") or t.encode("zlib").
A few remarks on your code: There are lots of factors that make the code hard to read: inconsistent spacing, overly long lines, meaningless variable names, unidiomatic code, etc. An example: Your decompress() function could be equivalently written as
def decompress(compressed_string, substitutions):
subst_list = [substitutions[k] for k in sorted(substitutions, key=int)]
return compressed_string.format(*subst_list)
Now it's already much more obvious what it does. You could go one step further: Why is substitutions a dictionary with the string keys "0", "1" etc.? Not only is it strange to use strings instead of integers -- you don't need the keys at all! A simple list will do, and decompress() will simplify to
def decompress(compressed_string, substitutions):
return compressed_string.format(*substitutions)
You might think all this is secondary, but if you make the rest of your code equally readable, you will find the bugs in your code yourself. (There are bugs -- it crashes for "abcdefgabcdefg" and many other strings.)
Typically one would pump the program through a compression algorithm optimized for text, then run that through exec, e.g.
code="""..."""
exec(somelib.decompress(code), globals=???, locals=???)
It may be the case that .pyc/.pyo files are compressed already, and one could check by creating one with x="""aaaaaaaa""", then increasing the length to x="""aaaaaaaaaaaaaaaaaaaaaaa...aaaa""" and seeing if the size changes appreciably.

Better looping, for string manipulation (python)

If i have this code
s = 'abcdefghi'
for grp in (s[:3],s[3:6],s[6:]):
print "'%s'"%(grp)
total = calc_total(grp)
if (grp==s[:3]):
# more code than this
p = total + random_value
x1 = my_function(p)
if (grp==s[3:6]):
# more code than this
p = total + x1
x2 = my_function(p)
if (grp==s[6:]):
# more code than this
p = total + x2
x3 = my_function(p)
If the group is the first group, perform code for this group, if the group is the second group, perform code using the a value generated from code performed for the first group, the same applies for the third group, using a generated value from code for the second group:
How can i tidy this up to use better looping?
Thanks
I may have misunderstood what you're doing, but it appears that you want to do something to s[:3] on the first iteration, something different to s[3:6] on the second, and something else again to s[6:] on the third. In other words, that isn't a loop at all! Just write those three blocks of code out one after another, with s[:3] and so on in place of grp.
I must say I agree with Peter in that the loop is redundant. If you are afraid of duplicating code, then just move the repeating code into a function and call it multiple times:
s = 'abcdefghi'
def foo(grp):
# Anything more you would like to happen over and over again
print "'%s'"%(grp)
return calc_total(grp)
def bar(grp, value):
total = foo(grp)
# more code than this
return my_function(total + value)
x1 = bar(s[:3], random_value)
x2 = bar(s[3:6], x1)
x3 = bar(s[6:], x2)
If
# more code than this
contains non-duplicate code, then you must of course move that out of "bar" (which together with "foo" should be given a more descriptive name).
I'd code something like this as follows:
for i, grp in enumerate((s[:3],s[3:6],s[6:])):
print "'%s'"%(grp)
total = calc_total(grp)
# more code that needs to happen every time
if i == 0:
# code that needs to happen only the first time
elif i == 1:
# code that needs to happen only the second time
etc. The == checks can be misleading if one of the groups "just happens" to be the same as another one, while the enumerate approach runs no such risk.
x = reduce(lambda x, grp: my_function(calc_total(list(grp)) + x),
map(None, *[iter(s)] * 3), random_value)
At the end, you'll have the last x.
Or, if you want to keep the intermediary results around,
x = []
for grp in map(None, *[iter(s)] * 3):
x.append(my_function(calc_total(list(grp)) + (x or [random_value])[-1]))
Then you have x[0], x[1], x[2].
Get your data into the list you want, then try the following:
output = 0
seed = get_random_number()
for group in input_list:
total = get_total(group)
p = total + seed
seed = my_function(p)
input_list will need to look like ['abc', 'def', 'ghi']. But if you want to extend it to ['abc','def','ghi','jkl','mno','pqr'], this should still work.

Categories

Resources