So I recently decided to learn python and as a exercise (plus making something useful) I decided to make a Euler's Modified Method algorithm for solving higher-then-first order differential equations. An example input would be:
python script_name.py -y[0] [10,0]
where the first argument is the deferential equation (here: y''=-y), and the second one the initial conditions (here: y(0)=10, y'(0)=0). It is then meant to out put the resusts to two files (x-data.txt, and y-data.txt).
Heres the problem:
When in run the code with the specified the final line (at t=1) reads -0.0, but if you solve the ODE (y=10*cos(x)), it should read 5.4. Even if you go through the program with a pen and paper and execute the code, your (and the computers) results apart to diverge by the second iteration). Any idea what could have caused this?
NB: I'm using python 2.7 on a os x
Here's my code:
#! /usr/bin/python
# A higher order differential equation solver using Euler's Modified Method
import math
import sys
step_size = 0.01
x=0
x_max=1
def derivative(x, y):
d = eval(sys.argv[1])
return d
y=eval(sys.argv[2])
order = len(y)
y_derivative=y
xfile = open('x-data.txt','w+')
yfile = open('y-data.txt','w+')
while (x<x_max):
xfile.write(str(x)+"\n")
yfile.write(str(y[0])+"\n")
for i in range(order-1):
y_derivative[i]=y[(i+1)]
y_derivative[(order-1)] = derivative(x,y)
for i in range(order):
y[i]=y[i]+step_size*y_derivative[i]
x=x+step_size
xfile.close()
yfile.close()
print('done')
When you say y_derivative=y they are the SAME list with different names. I.e. when you change y_derivative[i]=y[i+1] both lists are changing. You want to use y_derivative=y[:] to make a copy of y to put in y_derivative
See How to clone or copy a list? for more info
Also see http://effbot.org/zone/python-list.htm
Note, I was able to debug this in IDLE by replacing sys.argv with your provided example. Then if you turn on the debugger and step through the code, you can see both lists change.
Related
i am seeking a solution for the following equation in Python.
345-0.25*t = 37.5 * x_a
'with'
t = max(0, 10-x_a)*(20-10) + max(0,25-5*x_a)*(3-4) + max(0,4-0.25*x_a)*(30-12.5)
'x_a = ??'
If there is more than one solution to the problem (I am not even sure, whether this can happen from a mathematical point of view?), I want my code to return a positive(!) value for x_a, that minimizes t.
With my previous knowledge in the Basics of Python, Pandas and NumPy I actually have no clue, how to tackle this problem. Can someone give me a hint?
For Clarification: I inserted some exemplary numbers in the equation to make it easier to gasp the problem. In my final code, there might of course be different numbers for different scenarios. However, in every scenario x_a is the only unknown variable.
Update
I thought about the problem again and came up with the following solution, which yields the same result as the calculations done by MichaĆ Mazur:
import itertools
from sympy import Eq, Symbol, solve
import numpy as np
x_a = Symbol('x_a')
possible_elements = np.array([10-x_a, 25-5*x_a, 4-0.25*x_a])
assumptions = np.array(list(itertools.product([True, False], repeat=3)))
for assumption in assumptions:
x_a = Symbol('x_a')
elements = assumption.astype(int) * possible_elements
t = elements[0]*(20-10) + elements[1]*(3-4) + elements[2]*(30-12.5)
eqn = Eq(300-0.25*t, 40*x_a)
solution = solve(eqn)
if len(solution)>2:
print('Warning! the code may suppress possible solutions')
if len(solution)==1:
solution = solution[0]
if (((float(possible_elements[0].subs(x_a,solution))) > 0) == assumption[0]) &\
(((float(possible_elements[1].subs(x_a,solution))) > 0) == assumption[1]) &\
(((float(possible_elements[2].subs(x_a,solution)))> 0) == assumption[2]):
print('solution:', solution)
Compared to the already suggested approach this may have an little advantage as it does not rely on testing all possible values and therefore can be used for very small as well as very big solutions without taking a lot of time (?). However, it probably only is useful as long as you don't have more complex functions for t (even having for example 5 max(...) statements and therefore (2^5=)32 scenarios to test seems quite cumbersome).
As far as I'm concerned, I just realized that my problem is even more complex as i thought. For my project the calculations needed to derive the value of "t" are pretty entangled and can not be written in just one equation. However it still is a function, that only relies on x_a. So I am still hoping for a Python-Solution similar to the proposed Solver in Excel... or I will stick to the approach of simply testing out all possible numbers.
If you are interested in a solution a bit different than the Python one, then I will give you a hand. Open up your Excel, with Solver extention and plug in
the data you are interested in cheking, as the following:
Into the E2 you plug the command I just have writen, into E4 you plug in
=300-0,25*E2
Into the F4 you plug:
=40*F2
Then you open up your Solver menu
Into the Set Objective you put the variable t, which you want to minimize.
Into Changing Variables you put the a.
Into Constraint Menu you put the equality of E4 and F4 cells.
You check the "Make Unconstarained Variables be non-negative" which will prevent your a variable to go below 0. Your method of computing is strictly non-linear, so you leave this option there.
You click solve. The computed value is presented in the screen.
The python approach I can think of:
minimumval=10100
minxa=10000
eps=0.01
for i in range(100000):
k=i/10000
x_a=k
t = max(0, 10-x_a)*(20-10) + max(0,25-5*x_a)*(3-4) + max(0,4-0.25*x_a)*(30-12.5)
val=abs(300-0.25*t-40*x_a)
if (val<eps):
if t<minimumval:
minimumval=t
minxa=x_a
It isn't direct solution, as in it only controls the error that you make in the equality by eps value. However, it gives solution.
I am trying to minimize a function of 3 input variables using scipy. The function reads like so-
def myfunc(x):
x[0] = a
x[1] = b
x[2] = c
n = f(a,b,c)
return n
bound1 = (80,100)
bound2 = (10,20)
bound3 = (312,740)
guess = [a0,b0,c0]
bds = (bound1,bound2,bound3)
result = minimize(myfunc, guess,method='L-BFGS-B',bounds=bds)
The function I am trying to currently run reaches a minimum at a=100,b=10,c=740, which is at the end of the bounds.
The minimize function keeps trying to iterate past the end of bound 3 (gets to c0 value of 740.0000000149012 on its last iteration.
Is there any way to stop this from happening? i.e. stop the iteration at the actual end of my bound?
This happens due to numerical-differentiation, which itself is not only needed to infer the step-direction and size, but also to reason about termination.
In general you can't do much without being very careful in regards to whatever solver (and there are many backend-solvers) being used. The basic idea is to replace the automatic numerical-differentiation with one provided by you: this one then respects those bounds and must be careful about the solvers-internals, e.g. "how to reason about termination at this end".
Fix A:
Your problem should vanish automatically when using: Pull-request #10673, which touches your configuration: L-BFGS-B.
It seems, this PR is not part of the current release SciPy 1.4.1 (as this was 2 months before the PR).
See also #6026, where a milestone of 1.5.0 is mentioned in regards to some changes including respecting bounds in num-diff.
For above PR, you will need to install scipy from the sources, which is:
quite doable on linux (and maybe os x)
not something you should try on windows!
trust me...
See the documentation if needed.
Fix B:
Apart from that, as you are doing unconstrained-optimization (with variable-bounds) where more solver-backends are available (compared to constrained-optimization), you might try another solver, trust-constr, which has explicit support for this, see #9098.
Be careful to recognize, that you need to signal this explicitly when setting up the bounds!
I need to write a semidefinite program that minimizes the trace of an operator, say R, subject to the constraint that tr_A(R)^{Tb} >>0 . That means that R represents a 3 qubit quantum system and the trace over the first system gives you an operator that represents the remaining 2 qubit systems. Taking the partial transpose with respect to one of the qubits, you get the partially transposed quantum state of the restricted 2 qubit system. It is this state that I want to make positive semidefinite.
I am using PICOS (to write the SDP) and qutip (to do the operations).
P = pic.Problem()
Rho = P.add_variable('Rho',(n,n),'hermitian')
P.add_constraint(pic.trace(Rho)==1)
P.add_constraint(Rho>>0)
RhoQOBJ = Qobj(Rho)
RhoABtr = ptrace(RhoQOBJ, [0,1])
RhoABqbj = partial_transpose(RhoABtr, [0], method='dense')
RhoAB = RhoABqbj.full()
Problem: I need to make Rho a Qobj, for qutip to be able to understand it, but Rho above is only an instance of the Variable class. Anyone has any idea on how to do this?
Also I looked here, http://picos.zib.de/tuto.html#variables , it became even more confusing as this function puts the instance in a dictionary and only gives you back a key.
You need to be able to output a numpy array or sparse matrix to convert to a Qobj. I could not find anything in the picos docs that discusses this option.
I am seeing this post very late, but maybe I can help... I am not sure what the function Qobj() is doing, can you please tell me more about it.
Otherwise, there is now a new partial_transpose() function in PICOS (version released today), which hopefully does what you need.
Best,
Guillaume.
I have written some very simple trial-and-error code in Sage (a computer algebra system written in python where you can use regular python syntax in scripting). The little code snippet creates a polynomial and does some calculations with the coefficients, especially it determines the Groebner basis for the ideal generated by three expressions in the coefficients.
The problem is: This program goes on and eats up all my memory until it's killed by the kernel. Every iteration consumes only like 200kB, but this memory is never freed again.
Here is the code. The details are not that important and very bulky, therefore left out:
R = PolynomialRing(QQ, 2, 'bc', order='lex')
expr1, expr2, expr3 = ...
for i in range (0,50):
for j in range(i+1,50):
for k in range(j+1,50):
for l in range(k+1,50):
for m in range(l+1,50):
for n in range(m+1,50):
poly = (x-i)*(x-j)*(x-k)*(x-l)*(x-m)*(x-n)
r = poly.coeffs()
p1 = expr1.substitute(r...)
p2 = expr2.substitute(r...)
p3 = expr3.substitute(r...)
I = (p1, p2, p3)*R
B = I.groebner_basis()
As far as I understood python's memory management, the variables in the loop body are freed every so often. Now, it may be a programming problem, an internal python problem or some problem in the Sage routines. I don't know. Can you spot a problem with my code or is it something else?
The problem doesn't appear to be your loops (in python2.7, OS-X 10.5.8):
a = 0
for i in range (0,50):
for j in range(i+1,50):
for k in range(j+1,50):
for l in range(k+1,50):
for m in range(l+1,50):
for n in range(m+1,50):
a += 1
print( a )
Which takes very little additional memory on both python2.x and python3.x.
And it really doesn't take all that long to run either:
time python test.py
15890700
real 0m6.015s
user 0m5.940s
sys 0m0.032s
Perhaps something is funky when running with sage? Or maybe it's something else in your loops that is causing the problem...
The origin of the bug might be the call method on multivariate polynomials. Something as innocent as:
` for i in xrange(really_big_number):
polynomial(1,0,0,0)==0 `
will explode.
This might either happen in p1 = expr1.substitute(r...) or well inside the algorithm for the Groebner Basis.
I wrote the following code in python to solve
problem 15 from Project Euler:
grid_size = 2
def get_paths(node):
global paths
if node[0] >= grid_size and node[1] >= grid_size:
paths += 1
return
else:
if node[0]<grid_size+1 and node[1] < grid_size+1:
get_paths((node[0]+1,node[1]))
get_paths((node[0],node[1]+1))
return paths
def euler():
print get_paths((0,0))
paths = 0
if __name__ == '__main__':
euler()
Although it runs quite well for a 2 X 2 grid, it's been running for hours for a 20 X 20 grid. How can I optimise the code so that it can run on larger grids?
Is it a kind of breadth first search problem? (It seems so to me.)
How can I measure the complexity of my solution in its current form?
You might want to look into the maths behind this problem. It's not necessary to actually iterate through all routes. (In fact, you'll never make the 1 minute mark like that).
I can post a hint but won't do so unless you ask for it, since I wouldn't want to spoil it for you.
Edit:
Yes, the algorithm you're using will never really be optimal since there's no way to reduce the search space of your problem. This means that (as pg1989 stated) you'll have to look into alternative means of solving this problem.
As sverre said looking over here might give a nudge in the right direction:
http://en.wikipedia.org/wiki/Binomial_coefficient
A direct solution may be found here (warning, big spoiler):
http://www.joaoff.com/2008/01/20/a-square-grid-path-problem/
Your algorithm is exponential, but only because you are re-evaluating get_paths with the same input many times. Adding Memoization to it will make it run in time. Also, you'll need to get rid of the global variable, and use return values instead. See also Dynamic Programming for a similar idea.
When solving problems on Project Euler, think about the math behind the problem for a long time before starting to code. This problem can be solved without any code whatsoever.
We're trying to count the number of ways through a grid. If you observe that the number of moves down and right do not change regardless of the path, then you only need to worry about the order in which you move down and right. So in the 2x2 case, the following combinations work:
DDRR
DRDR
RDRD
RRDD
RDDR
DRRD
Notice that if we pick where we put the R moves, the placement of the D moves is determined. So really we only have to choose, from the 4 movement slots available, which get the R moves. Can you think of a mathematical operation that does this?
Probably not the way the project Euler guys wanted this problem to be solved but the answer is just the central binomial coefficient of a 20x20 grid.
Using the formula provided at the wiki article you get:
from math import factorial, pow
grid = 20
print int(factorial(2 * grid) / pow(factorial(grid), 2))
The key is not to make your algorithm run faster, as it will (potentially) run in exponential time, no matter how fast each step is.
It is probably better to find another way of computing the answer. Using your (expensive, but correct) solution as a comparison for small values is probably a sanity-preserver during the algorithm optimization effort.
This question provides some good insight into optimization. The code is in c# but the algorithms are applicable. Watch out for spoilers, though.
Project Euler #15
It can be solved by simple observation of the pattern for small grids, and determining a straightforward formula for larger grids. There are over 100 billion paths for a 20x20 grid and any iterative solution will take too long to compute.
Here's my solution:
memo = {(0, 1) : 1, (1, 0) : 1}
def get_pathways(x, y):
if (x, y) in memo : return memo[(x, y)]
pathways = 0
if 0 in (x, y):
pathways = 1
else:
pathways = get_pathways(x-1, y) + get_pathways(x, y-1)
memo[(x, y)] = pathways
return pathways
enjoy :)