Acessing earlier values using scipy's odeint - python

I am solving a system of differential equations using scipy's odeint and I have a problem now that I can't seem to fix:
if a certain condition is met, I have to 'go back in time' to an earlier state, change a (global) parameter and continue integrating from there.
At first I thought, although you can't really go back in time with odeint that I will store the time(s) at which the condition is met, change the state of the system (the variable that is integrated) and just continue the integration from there.
Unfortunately I can't find a way to access the values of the variable for past times from within odeint. Does somebody know a way to solve my dilemma?
If that is not possible, can somebody suggest a different way to do this? Performance is an issue, so I would really like to not have to write my own solver in python. I could do it in C, but that would require me to change the whole implementation and that would cost me a lot of time.

Related

Python: How to integrate an initial value problem backwards AND forwards in time, using initialscipy.integrate.solve_ivp?

I am using solve_ivp from scipy.integrate to solve an initial value problem y'(t) = fun(t,y) with y(t0)=y0. The help is here, from which one can see that the most basic call of the function is of the form:
solve_ivp(fun,[t0,tf],y0)
As stated, here y0=y(t0). I already figured out, that one can integrate backwards in time by entering a tf which is smaller than t0. However I don't know how I can integrate both, backwards and forwards in time in one go.
I.e., I want to integrate over an interval [ti,tf], where ti<t0<tf and where still y0=y(t0) as before. Is that possible? Or do I have to solve twice, and then piece the solutions together afterwards?
Thanks for suggestions!

Pyomo warm start

I've a MIP to solve with Pyomo and I want to set an initial solution for cplex.
So googling I find that I can set some variable of instance to some value and then execute this:
solver.solve(instance,warmstart=True,tee=True)
But when I run cplex it seem that it doesn't use the warm start, because for example i pass a solution with value 16, but in 5 seconds it return a solution with value 60.
So I don't know there is some error or other stuff that doesn't work.
P.S.
I don't know if is a problem but my warm start solution set only some variale to a value, but not all. Could be a problem?
Make sure that the solution you give to CPLEX is feasible. Otherwise, CPLEX will reject it and start from scratch.
If your solution is feasible, it is possible that CPLEX simply found a better solution than yours, since, after all, it is CPLEX's job, and in my own experience, CPLEX is very good at it. Is this a maximization problem? If so, in your example, CPLEX found a better solution (objective=60) than yours (objective=16), which is the expected behavior.
Sadly, CPLEX is often greedy in term of verbose, so it is hard to know from the solver log if warmstart was used or not (unlike its competitor GUROBI where it is clearly written in the log). However, it seems like you started the warmstart correctly, using the warmstart=True parameter.
If, however, your problem isn't a maximization problem, it is possible that CPLEX will not make a differenciation between the variables that you gave a value and the variable that still holds a solution from last solve. Plus, giving values to only a fraction of your variables might make the problem infeasible, considering that all values not manually specified are the values previously found by CPLEX. ex: contraint x<=2y. The solver found x=2, y=1 as a feasible solution. You define x:=3, then your constraint is not respected (y is still =1 for CPLEX, so the constraint x<=2y is 3<=2, which is false). CPLEX will see it as infeasible and will reject your solution.
One alternative that I can give you, if you absolutely want to use your own values in the final solution, is instead of defining values for your variables, create a constraint that explicitly defines your variable value. This constraint can afterward be "deactivated" if needed. But be careful, as this does not necessarily yield the optimal solution, but the "optimal solution when some variables have the specific value".

Which mathematical method is used by odeint?

I'm working with scipy.integrate.odeint and want to understand it better. For this I have two slightly related questions:
Which mathematical method is it using? Runge-Kutta? Adams-Bashforth? I found this site, but it seems to be for C++, but as far as I know the python function uses the C++ version as well... It states that it switches automatically between implicit and explicit solver, does anybody know how it does this?
To understand/reuse the information I would like to know at which timepoints it evaluates the function and how exactly it computes the solution of the ODE, but fulloutput does not seem to help/I wasn't able to find out how. So to be more precise, an example with Runge-Kutta-Fehlberg: I want the different timepoints at which it evaluated f and the weights it used to multiply it.
Additional information (what for this Info is needed):
I want to reuse this information to use automatic differentiation. So I would call odeint as a black box, find out all the relevant steps it made and reuse this info to calculate the differential dx(T_end)/dx0.
If you know of any other method to solve my problem, please go ahead. Also if another ode solver might be more appropriate to d this.
PS: I'm new, so would it be better to split this question into to questions? I.e. seperate 1. and 2.?

scipy.integrate.odeint fails depending on time steps

I use python for scientific applications, esp. for solving differential equations. I´ve already used the odeint function successfully on simple equation systems.
Right now my goal is to solve a rather complex system of over 300 equations. At this point the odeint functions give me reasonable results as long as the time steps in the t-array are equal or smaller than 1e-3. But I need bigger time steps since the system has to be integrated over several thousand seconds. Bigger time steps yield the "excess work done.." error.
Does anyone have experience with odeint and can tell me, why this is the case, although the odeint function seems to choose its time steps automatically and then displays the results that match the time steps given by me?
I simply don´t understand why this happens. I think I can work around the problem by integrating multiple times, but maybe someone knows a better solution. I apologize in advance in the case there already is a solution elsewhere and I haven´t seen it.

CPLEX finds optimal LP solution but returns no basis error

I am solving a series of LP problems using the CPLEX Python API.
Since many of the problems are essentially the same, save a hand full of parameters. I want to use a warm start with the solution of the previous problem for most of them, by calling the function cpx.start.set_start(col_status, row_status, col_primal, row_primal, col_dual, row_dual) where cpx = cplex.Cplex().
This function is documented here. Two of the arguments, col_status and row_status, are obtained by calling cpx.solution.basis.get_col_basis() and cpx.solution.basis.get_row_basis().
However, despite cpx.solution.status[cpx.solution.get_status()] returning optimal and being able to obtain both cpx.solution.get_values() and cpx.solution.get_dual_values() ...
Calling cpx.solution.basis.get_basis() returns CPLEX Error 1262: No basis exists.
Now, according to this post one can call the warm start function with empty lists for the column and row basis statuses, as follows.
lastsolution = cpx.solution.get_values()
cpx.start.set_start(col_status=[], row_status=[],
col_primal=lastsolution, row_primal=[],
col_dual=[], row_dual=[])
However, this actually results in making a few more CPLEX iterations. Why more is unclear, but the overall goal is to have significantly less, obviously.
Version Info
Python 2.7.12
CPLEX 12.6.3
I'm not sure why you're getting the CPXERR_NO_BASIS. See my comment.
You may have better luck if you provide the values for row_primal, col_dual, and row_dual too. For example:
cpx2.start.set_start(col_status=[],
row_status=[],
col_primal=cpx.solution.get_values(),
row_primal=cpx.solution.get_linear_slacks(),
col_dual=cpx.solution.get_reduced_costs(),
row_dual=cpx.solution.get_dual_values())
I was able to reproduce the behavior you describe using the afiro.mps model that comes with the CPLEX examples (number of deterministic ticks actually increased when specifying col_primal alone). However, when doing the above, it did help (number of det ticks improved and iterations went to 0).
Finally, I don't believe that there is any guarantee that using set_start will always help (it may even be a bad idea in some cases). I don't have a reference for this.

Categories

Resources