# HG changeset patch
# User Yuri Karadzhov <yuri.karadzhov@gmail.com>
# Date 1269721789 0
# Node ID acadcfa52c47da58a72fe835959b7f429e9298af
# Parent 46b1ee5997ac7e7faafdd86751fe7d121b6c1385
Trac 8616: Add functionality. Symbolic type checking and expression parcing module
Provides unified interface for standard python types and sage specific types.
Treats everything as symbolic expression which allows to check its type, take
operator and operands and extract subexpressions by given types.
diff -r 46b1ee5997ac -r acadcfa52c47 sage/calculus/all.py
a
|
b
|
|
8 | 8 | |
9 | 9 | from functions import (wronskian,jacobian) |
10 | 10 | |
11 | | from desolvers import (desolve, desolve_laplace, desolve_system, |
12 | | eulers_method, eulers_method_2x2, |
| 11 | from desolvers import (desolve, dsolve, desolve_laplace, dsolve_laplace, desolve_system, |
| 12 | eulers_method, eulers_method_2x2, |
13 | 13 | eulers_method_2x2_plot, desolve_rk4, desolve_system_rk4) |
14 | 14 | |
15 | 15 | from var import (var, function, clear_vars) |
… |
… |
|
27 | 27 | - a symbolic expression. |
28 | 28 | |
29 | 29 | EXAMPLES:: |
30 | | |
| 30 | |
31 | 31 | sage: a = symbolic_expression(3/2); a |
32 | 32 | 3/2 |
33 | 33 | sage: type(a) |
… |
… |
|
53 | 53 | sage: symbolic_expression(E) |
54 | 54 | x*y + y^2 + y == x^3 + x^2 - 10*x - 10 |
55 | 55 | sage: symbolic_expression(E) in SR |
56 | | True |
| 56 | True |
57 | 57 | """ |
58 | 58 | from sage.symbolic.expression import Expression |
59 | 59 | from sage.symbolic.ring import SR |
diff -r 46b1ee5997ac -r acadcfa52c47 sage/calculus/desolvers.py
a
|
b
|
|
32 | 32 | - ``eulers_method_2x2_plot`` - Plots the sequence of points obtained |
33 | 33 | from Euler's method. |
34 | 34 | |
35 | | AUTHORS: |
| 35 | AUTHORS: |
36 | 36 | |
37 | 37 | - David Joyner (3-2006) - Initial version of functions |
38 | 38 | |
… |
… |
|
42 | 42 | |
43 | 43 | - Robert Marik (10-2009) - Some bugfixes and enhancements |
44 | 44 | |
| 45 | - Yuri Karadzhov (2010-03-27) - Autodetection of dependent and independent vars |
| 46 | |
45 | 47 | """ |
46 | 48 | |
47 | 49 | ########################################################################## |
… |
… |
|
58 | 60 | from sage.symbolic.expression import is_SymbolicEquation |
59 | 61 | from sage.symbolic.ring import is_SymbolicVariable |
60 | 62 | from sage.calculus.functional import diff |
| 63 | from sage.symbolic.mtype import * |
61 | 64 | |
62 | 65 | maxima = Maxima() |
63 | 66 | |
64 | | def desolve(de, dvar, ics=None, ivar=None, show_method=False, contrib_ode=False): |
| 67 | def desolve(de, dvar=None, ics=None, ivar=None, show_method=False, contrib_ode=False): |
65 | 68 | """ |
66 | 69 | Solves a 1st or 2nd order linear ODE via maxima. Including IVP and BVP. |
67 | | |
| 70 | |
68 | 71 | *Use* ``desolve? <tab>`` *if the output in truncated in notebook.* |
69 | 72 | |
70 | 73 | INPUT: |
71 | | |
| 74 | |
72 | 75 | - ``de`` - an expression or equation representing the ODE |
73 | | |
74 | | - ``dvar`` - the dependent variable (hereafter called ``y``) |
| 76 | |
| 77 | - ``dvar`` - (optional) the dependent variable (hereafter called ``y``) |
75 | 78 | |
76 | 79 | - ``ics`` - (optional) the initial or boundary conditions |
77 | 80 | |
… |
… |
|
79 | 82 | |
80 | 83 | - for a second-order equation, specify the initial ``x``, ``y``, |
81 | 84 | and ``dy/dx`` |
82 | | |
| 85 | |
83 | 86 | - for a second-order boundary solution, specify initial and |
84 | 87 | final ``x`` and ``y`` initial conditions gives error if the |
85 | 88 | solution is not SymbolicEquation (as happens for example for |
86 | 89 | clairot equation) |
87 | | |
| 90 | |
88 | 91 | - ``ivar`` - (optional) the independent variable (hereafter called |
89 | 92 | x), which must be specified if there is more than one |
90 | 93 | independent variable in the equation. |
91 | | |
| 94 | |
92 | 95 | - ``show_method`` - (optional) if true, then Sage returns pair |
93 | 96 | ``[solution, method]``, where method is the string describing |
94 | 97 | method which has been used to get solution (Maxima uses the |
… |
… |
|
107 | 110 | |
108 | 111 | |
109 | 112 | OUTPUT: |
110 | | |
| 113 | |
111 | 114 | In most cases returns SymbolicEquation which defines the solution |
112 | 115 | implicitly. If the result is in the form y(x)=... (happens for |
113 | 116 | linear eqs.), returns the right-hand side only. The possible |
… |
… |
|
118 | 121 | |
119 | 122 | sage: x = var('x') |
120 | 123 | sage: y = function('y', x) |
121 | | sage: desolve(diff(y,x) + y - 1, y) |
| 124 | sage: desolve(diff(y,x) + y - 1) |
122 | 125 | (c + e^x)*e^(-x) |
123 | | |
| 126 | |
124 | 127 | :: |
125 | 128 | |
126 | | sage: f = desolve(diff(y,x) + y - 1, y, ics=[10,2]); f |
| 129 | sage: f = desolve(diff(y,x) + y - 1, ics=[10,2]); f |
127 | 130 | (e^10 + e^x)*e^(-x) |
128 | 131 | |
129 | 132 | :: |
130 | 133 | |
131 | 134 | sage: plot(f) |
132 | | |
| 135 | |
133 | 136 | We can also solve second-order differential equations.:: |
134 | | |
| 137 | |
135 | 138 | sage: x = var('x') |
136 | 139 | sage: y = function('y', x) |
137 | 140 | sage: de = diff(y,x,2) - y == x |
138 | | sage: desolve(de, y) |
| 141 | sage: desolve(de) |
139 | 142 | k1*e^x + k2*e^(-x) - x |
140 | | |
| 143 | |
141 | 144 | |
142 | 145 | :: |
143 | 146 | |
… |
… |
|
150 | 153 | |
151 | 154 | :: |
152 | 155 | |
| 156 | sage: f = desolve(de, ics=[10,2,1]); f |
| 157 | -x + 5*e^(-x + 10) + 7*e^(x - 10) |
| 158 | sage: f(x=10) |
| 159 | 2 |
| 160 | sage: diff(f,x)(x=10) |
| 161 | 1 |
| 162 | |
| 163 | :: |
| 164 | |
153 | 165 | sage: de = diff(y,x,2) + y == 0 |
154 | | sage: desolve(de, y) |
| 166 | sage: desolve(de) |
155 | 167 | k1*sin(x) + k2*cos(x) |
156 | | sage: desolve(de, y, [0,1,pi/2,4]) |
| 168 | sage: desolve(de, ics=[0,1,pi/2,4]) |
157 | 169 | 4*sin(x) + cos(x) |
158 | | |
159 | | sage: desolve(y*diff(y,x)+sin(x)==0,y) |
| 170 | |
| 171 | sage: desolve(y*diff(y,x)+sin(x)==0) |
160 | 172 | -1/2*y(x)^2 == c - cos(x) |
161 | 173 | |
162 | 174 | Clairot equation: general and singular solutions:: |
163 | 175 | |
164 | | sage: desolve(diff(y,x)^2+x*diff(y,x)-y==0,y,contrib_ode=True,show_method=True) |
| 176 | sage: desolve(diff(y,x)^2+x*diff(y,x)-y==0,contrib_ode=True,show_method=True) |
165 | 177 | [[y(x) == c^2 + c*x, y(x) == -1/4*x^2], 'clairault'] |
166 | | |
167 | | For equations involving more variables we specify independent variable:: |
| 178 | |
| 179 | For equations involving more variables we shouldn't specify independent variable if they are obvious:: |
168 | 180 | |
169 | 181 | sage: a,b,c,n=var('a b c n') |
170 | | sage: desolve(x^2*diff(y,x)==a+b*x^n+c*x^2*y^2,y,ivar=x,contrib_ode=True) |
| 182 | sage: desolve(x^2*diff(y,x)==a+b*x^n+c*x^2*y^2,contrib_ode=True) |
171 | 183 | [[y(x) == 0, (b*x^(n - 2) + a/x^2)*c^2*u == 0]] |
172 | | sage: desolve(x^2*diff(y,x)==a+b*x^n+c*x^2*y^2,y,ivar=x,contrib_ode=True,show_method=True) |
| 184 | sage: desolve(x^2*diff(y,x)==a+b*x^n+c*x^2*y^2,contrib_ode=True,show_method=True) |
173 | 185 | [[[y(x) == 0, (b*x^(n - 2) + a/x^2)*c^2*u == 0]], 'riccati'] |
174 | 186 | |
175 | 187 | |
176 | 188 | Higher orded, not involving independent variable:: |
177 | 189 | |
178 | | sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y).expand() |
| 190 | sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0).expand() |
179 | 191 | 1/6*y(x)^3 + k1*y(x) == k2 + x |
180 | | sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y,[0,1,1,3]).expand() |
| 192 | sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,ics=[0,1,1,3]).expand() |
181 | 193 | 1/6*y(x)^3 - 5/3*y(x) == x - 3/2 |
182 | | sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y,[0,1,1,3],show_method=True) |
| 194 | sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,ics=[0,1,1,3],show_method=True) |
183 | 195 | [1/6*y(x)^3 - 5/3*y(x) == x - 3/2, 'freeofx'] |
184 | 196 | |
185 | 197 | Separable equations - Sage returns solution in implicit form:: |
186 | 198 | |
187 | | sage: desolve(diff(y,x)*sin(y) == cos(x),y) |
| 199 | sage: desolve(diff(y,x)*sin(y) == cos(x)) |
188 | 200 | -cos(y(x)) == c + sin(x) |
189 | | sage: desolve(diff(y,x)*sin(y) == cos(x),y,show_method=True) |
| 201 | sage: desolve(diff(y,x)*sin(y) == cos(x),show_method=True) |
190 | 202 | [-cos(y(x)) == c + sin(x), 'separable'] |
191 | | sage: desolve(diff(y,x)*sin(y) == cos(x),y,[pi/2,1]) |
| 203 | sage: desolve(diff(y,x)*sin(y) == cos(x),ics=[pi/2,1]) |
192 | 204 | -cos(y(x)) == sin(x) - cos(1) - 1 |
193 | 205 | |
194 | 206 | Linear equation - Sage returns the expression on the right hand side only:: |
195 | 207 | |
196 | | sage: desolve(diff(y,x)+(y) == cos(x),y) |
| 208 | sage: desolve(diff(y,x)+(y) == cos(x)) |
197 | 209 | 1/2*((sin(x) + cos(x))*e^x + 2*c)*e^(-x) |
198 | | sage: desolve(diff(y,x)+(y) == cos(x),y,show_method=True) |
| 210 | sage: desolve(diff(y,x)+(y) == cos(x),show_method=True) |
199 | 211 | [1/2*((sin(x) + cos(x))*e^x + 2*c)*e^(-x), 'linear'] |
200 | | sage: desolve(diff(y,x)+(y) == cos(x),y,[0,1]) |
| 212 | sage: desolve(diff(y,x)+(y) == cos(x),ics=[0,1]) |
201 | 213 | 1/2*(e^x*sin(x) + e^x*cos(x) + 1)*e^(-x) |
202 | 214 | |
203 | 215 | This ODE with separated variables is solved as |
204 | 216 | exact. Explanation - factor does not split `e^{x-y}` in Maxima |
205 | 217 | into `e^{x}e^{y}`:: |
206 | 218 | |
207 | | sage: desolve(diff(y,x)==exp(x-y),y,show_method=True) |
| 219 | sage: desolve(diff(y,x)==exp(x-y),show_method=True) |
208 | 220 | [-e^x + e^y(x) == c, 'exact'] |
209 | 221 | |
210 | 222 | You can solve Bessel equations. You can also use initial |
… |
… |
|
212 | 224 | condition at x=0, since this point is singlar point of the |
213 | 225 | equation. Anyway, if the solution should be bounded at x=0, then |
214 | 226 | k2=0.:: |
215 | | |
216 | | sage: desolve(x^2*diff(y,x,x)+x*diff(y,x)+(x^2-4)*y==0,y) |
| 227 | |
| 228 | sage: desolve(x^2*diff(y,x,x)+x*diff(y,x)+(x^2-4)*y==0) |
217 | 229 | k1*bessel_j(2, x) + k2*bessel_y(2, x) |
218 | | |
| 230 | |
219 | 231 | Difficult ODE produces error:: |
220 | 232 | |
221 | 233 | sage: desolve(sqrt(y)*diff(y,x)+e^(y)+cos(x)-sin(x+y)==0,y) # not tested |
222 | 234 | Traceback (click to the left for traceback) |
223 | 235 | ... |
224 | 236 | NotImplementedError, "Maxima was unable to solve this ODE. Consider to set option contrib_ode to True." |
225 | | |
| 237 | |
226 | 238 | Difficult ODE produces error - moreover, takes a long time :: |
227 | 239 | |
228 | 240 | sage: desolve(sqrt(y)*diff(y,x)+e^(y)+cos(x)-sin(x+y)==0,y,contrib_ode=True) # not tested |
… |
… |
|
233 | 245 | [[y(x) == c + log(x), y(x) == c*e^x], 'factor'] |
234 | 246 | |
235 | 247 | :: |
236 | | |
| 248 | |
237 | 249 | sage: desolve(diff(y,x)==(x+y)^2,y,contrib_ode=True,show_method=True) |
238 | 250 | [[[x == c - arctan(sqrt(t)), y(x) == -x - sqrt(t)], [x == c + arctan(sqrt(t)), y(x) == -x + sqrt(t)]], 'lagrange'] |
239 | 251 | |
… |
… |
|
245 | 257 | Traceback (click to the left for traceback) |
246 | 258 | ... |
247 | 259 | NotImplementedError, "Maxima was unable to solve this ODE. Consider to set option contrib_ode to True." |
248 | | |
| 260 | |
249 | 261 | :: |
250 | 262 | |
251 | 263 | sage: desolve(diff(y,x,2)+y*(diff(y,x,1))^3==0,y,[0,1,2],show_method=True) # not tested |
… |
… |
|
267 | 279 | 3*((e^(1/2*pi) - 2)*x/pi + 1)*e^(-x) + 1/2*sin(x) |
268 | 280 | sage: desolve(diff(y,x,2)+2*diff(y,x)+y == cos(x),y,[0,3,pi/2,2],show_method=True) |
269 | 281 | [3*((e^(1/2*pi) - 2)*x/pi + 1)*e^(-x) + 1/2*sin(x), 'variationofparameters'] |
270 | | |
| 282 | |
271 | 283 | sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y) |
272 | 284 | (k2*x + k1)*e^(-x) |
273 | 285 | sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y,show_method=True) |
… |
… |
|
281 | 293 | sage: desolve(diff(y,x,2)+2*diff(y,x)+y == 0,y,[0,3,pi/2,2],show_method=True) |
282 | 294 | [(2*(2*e^(1/2*pi) - 3)*x/pi + 3)*e^(-x), 'constcoeff'] |
283 | 295 | |
284 | | |
| 296 | |
285 | 297 | This equation can be solved within Maxima but not within Sage. It |
286 | 298 | needs assumptions assume(x>0,y>0) and works in Maxima, but not in Sage:: |
287 | 299 | |
… |
… |
|
289 | 301 | sage: assume(y>0) # not tested |
290 | 302 | sage: desolve(x*diff(y,x)-x*sqrt(y^2+x^2)-y,y,show_method=True) # not tested |
291 | 303 | |
292 | | |
| 304 | |
293 | 305 | TESTS: |
294 | | |
| 306 | |
295 | 307 | Trac #6479 fixed:: |
296 | 308 | |
297 | 309 | sage: x = var('x') |
… |
… |
|
300 | 312 | x |
301 | 313 | |
302 | 314 | :: |
303 | | |
| 315 | |
304 | 316 | sage: desolve( diff(y,x,x) == 0, y, [0,1,1]) |
305 | 317 | x + 1 |
306 | 318 | |
307 | 319 | |
308 | 320 | AUTHORS: |
309 | | |
| 321 | |
310 | 322 | - David Joyner (1-2006) |
311 | 323 | |
312 | 324 | - Robert Bradshaw (10-2008) |
313 | 325 | |
314 | 326 | - Robert Marik (10-2009) |
315 | 327 | |
| 328 | - Yuri Karadzhov (2010-03-27) |
| 329 | |
316 | 330 | """ |
317 | 331 | if is_SymbolicEquation(de): |
318 | 332 | de = de.lhs() - de.rhs() |
319 | | if is_SymbolicVariable(dvar): |
320 | | raise ValueError, "You have to declare dependent variable as a function, eg. y=function('y',x)" |
321 | | # for backwards compatibility |
322 | | if isinstance(dvar, list): |
323 | | dvar, ivar = dvar |
324 | | elif ivar is None: |
325 | | ivars = de.variables() |
326 | | ivars = [t for t in ivars if t is not dvar] |
| 333 | diff_list = map(ops,indets(de,'_diff')) |
| 334 | if len(diff_list) == 0: |
| 335 | raise ValueError, "First argument is not differential equation." |
| 336 | if dvar is None: |
| 337 | dvars = set([x[0] for x in diff_list]) |
| 338 | if len(dvars) != 1: |
| 339 | raise ValueError, "Unable to determine dependent variable, please specify." |
| 340 | dvar=dvars.pop() |
| 341 | else: |
| 342 | if is_SymbolicVariable(dvar): |
| 343 | raise ValueError, "You have to declare dependent variable as a function, eg. y=function('y',x)" |
| 344 | # for backwards compatibility |
| 345 | if isinstance(dvar, list): |
| 346 | dvar, ivar = dvar |
| 347 | if ivar is None: |
| 348 | ivars = set() |
| 349 | for el in diff_list: |
| 350 | ivars = ivars.union(el[1:]) |
327 | 351 | if len(ivars) != 1: |
328 | 352 | raise ValueError, "Unable to determine independent variable, please specify." |
329 | | ivar = ivars[0] |
| 353 | ivar = ivars.pop() |
330 | 354 | def sanitize_var(exprs): |
331 | | return exprs.replace("'"+dvar_str+"("+ivar_str+")",dvar_str) |
| 355 | return exprs.replace("'"+dvar_str+"("+ivar_str+")",dvar_str) |
332 | 356 | dvar_str=dvar.operator()._maxima_().str() |
333 | 357 | ivar_str=ivar._maxima_().str() |
334 | 358 | de00 = de._maxima_().str() |
335 | 359 | de0 = sanitize_var(de00) |
336 | 360 | ode_solver="ode2" |
337 | | cmd="(TEMP:%s(%s,%s,%s), if TEMP=false then TEMP else substitute(%s=%s(%s),TEMP))"%(ode_solver,de0,dvar_str,ivar_str,dvar_str,dvar_str,ivar_str) |
| 361 | cmd="(TEMP:%s(%s,%s,%s), if TEMP=false then TEMP else substitute(%s=%s(%s),TEMP))"%(ode_solver,de0,dvar_str,ivar_str,dvar_str,dvar_str,ivar_str) |
338 | 362 | # we produce string like this |
339 | 363 | # ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y(x),x) |
340 | 364 | soln = maxima(cmd) |
… |
… |
|
343 | 367 | if contrib_ode: |
344 | 368 | ode_solver="contrib_ode" |
345 | 369 | maxima("load('contrib_ode)") |
346 | | cmd="(TEMP:%s(%s,%s,%s), if TEMP=false then TEMP else substitute(%s=%s(%s),TEMP))"%(ode_solver,de0,dvar_str,ivar_str,dvar_str,dvar_str,ivar_str) |
| 370 | cmd="(TEMP:%s(%s,%s,%s), if TEMP=false then TEMP else substitute(%s=%s(%s),TEMP))"%(ode_solver,de0,dvar_str,ivar_str,dvar_str,dvar_str,ivar_str) |
347 | 371 | # we produce string like this |
348 | 372 | # (TEMP:contrib_ode(x*('diff(y,x,1))^2-(x*y+1)*'diff(y,x,1)+y,y,x), if TEMP=false then TEMP else substitute(y=y(x),TEMP)) |
349 | 373 | soln = maxima(cmd) |
350 | 374 | if str(soln).strip() == 'false': |
351 | | raise NotImplementedError, "Maxima was unable to solve this ODE." |
| 375 | raise NotImplementedError, "Maxima was unable to solve this ODE." |
352 | 376 | else: |
353 | 377 | raise NotImplementedError, "Maxima was unable to solve this ODE. Consider to set option contrib_ode to True." |
354 | 378 | |
… |
… |
|
357 | 381 | |
358 | 382 | if (ics is not None): |
359 | 383 | if not is_SymbolicEquation(soln.sage()): |
360 | | raise NotImplementedError, "Maxima was unable to use initial condition for this equation (%s)"%(maxima_method.str()) |
| 384 | raise NotImplementedError, "Maxima was unable to use initial condition for this equation (%s)"%(maxima_method.str()) |
361 | 385 | if len(ics) == 2: |
362 | 386 | tempic=(ivar==ics[0])._maxima_().str() |
363 | 387 | tempic=tempic+","+(dvar==ics[1])._maxima_().str() |
… |
… |
|
367 | 391 | # (TEMP:ic2(ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y,x),x=0,y=3,'diff(y,x)=1),substitute(y=y(x),TEMP)) |
368 | 392 | soln=maxima(cmd) |
369 | 393 | if len(ics) == 3: |
370 | | #fixed ic2 command from Maxima - we have to ensure that %k1, %k2 do not depend on variables, should be removed when fixed in Maxima |
| 394 | #fixed ic2 command from Maxima - we have to ensure that %k1, %k2 do not depend on variables, should be removed when fixed in Maxima |
371 | 395 | maxima("ic2_sage(soln,xa,ya,dya):=block([programmode:true,backsubst:true,singsolve:true,temp,%k2,%k1,TEMP_k], \ |
372 | 396 | noteqn(xa), noteqn(ya), noteqn(dya), boundtest('%k1,%k1), boundtest('%k2,%k2), \ |
373 | 397 | temp: lhs(soln) - rhs(soln), \ |
… |
… |
|
384 | 408 | # (TEMP:ic2(ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y,x),x=0,y=3,'diff(y,x)=1),substitute(y=y(x),TEMP)) |
385 | 409 | soln=maxima(cmd) |
386 | 410 | if str(soln).strip() == 'false': |
387 | | raise NotImplementedError, "Maxima was unable to solve this IVP. Remove the initial contition to get the general solution." |
| 411 | raise NotImplementedError, "Maxima was unable to solve this IVP. Remove the initial contition to get the general solution." |
388 | 412 | if len(ics) == 4: |
389 | | #fixed bc2 command from Maxima - we have to ensure that %k1, %k2 do not depend on variables, should be removed when fixed in Maxima |
| 413 | #fixed bc2 command from Maxima - we have to ensure that %k1, %k2 do not depend on variables, should be removed when fixed in Maxima |
390 | 414 | maxima("bc2_sage(soln,xa,ya,xb,yb):=block([programmode:true,backsubst:true,singsolve:true,temp,%k1,%k2,TEMP_k], \ |
391 | 415 | noteqn(xa), noteqn(ya), noteqn(xb), noteqn(yb), boundtest('%k1,%k1), boundtest('%k2,%k2), \ |
392 | 416 | TEMP_k:solve([subst([xa,ya],soln), subst([xb,yb],soln)], [%k1,%k2]), \ |
… |
… |
|
394 | 418 | temp: maplist(lambda([zz], subst(zz,soln)),TEMP_k), \ |
395 | 419 | if length(temp)=1 then return(first(temp)) else return(temp))") |
396 | 420 | cmd="bc2_sage(%s(%s,%s,%s),%s,%s=%s,%s,%s=%s)"%(ode_solver,de00,dvar_str,ivar_str,(ivar==ics[0])._maxima_().str(),dvar_str,(ics[1])._maxima_().str(),(ivar==ics[2])._maxima_().str(),dvar_str,(ics[3])._maxima_().str()) |
397 | | cmd="(TEMP:%s,substitute(%s=%s(%s),TEMP))"%(cmd,dvar_str,dvar_str,ivar_str) |
| 421 | cmd="(TEMP:%s,substitute(%s=%s(%s),TEMP))"%(cmd,dvar_str,dvar_str,ivar_str) |
398 | 422 | cmd=sanitize_var(cmd) |
399 | 423 | # we produce string like this |
400 | 424 | # (TEMP:bc2(ode2('diff(y,x,2)+2*'diff(y,x,1)+y-cos(x),y,x),x=0,y=3,x=%pi/2,y=2),substitute(y=y(x),TEMP)) |
401 | 425 | soln=maxima(cmd) |
402 | 426 | if str(soln).strip() == 'false': |
403 | | raise NotImplementedError, "Maxima was unable to solve this BVP. Remove the initial contition to get the general solution." |
| 427 | raise NotImplementedError, "Maxima was unable to solve this BVP. Remove the initial contition to get the general solution." |
404 | 428 | |
405 | 429 | soln=soln.sage() |
406 | 430 | if is_SymbolicEquation(soln) and soln.lhs() == dvar: |
… |
… |
|
409 | 433 | soln = soln.rhs() |
410 | 434 | if show_method: |
411 | 435 | return [soln,maxima_method.str()] |
412 | | else: |
| 436 | else: |
413 | 437 | return soln |
414 | 438 | |
| 439 | def dsolve(de, ics=None, dvar=None, ivar=None, show_method=False, contrib_ode=False): |
| 440 | """ |
| 441 | ALIAS for desolve |
| 442 | sage: y=function('y',x) |
| 443 | sage: desolve(de,[0,1,pi/2,4]) |
| 444 | 4*sin(x) + cos(x) |
| 445 | """ |
| 446 | return desolve(de, dvar, ics, ivar, show_method, contrib_ode) |
415 | 447 | |
416 | 448 | #def desolve_laplace2(de,vars,ics=None): |
417 | 449 | ## """ |
… |
… |
|
454 | 486 | # #return maxima.eval(cmd) |
455 | 487 | # return de0.desolve(vars[0]).rhs() |
456 | 488 | |
457 | | |
458 | | def desolve_laplace(de, dvar, ics=None, ivar=None): |
| 489 | |
| 490 | def desolve_laplace(de, dvar=None, ics=None, ivar=None): |
459 | 491 | """ |
460 | 492 | Solves an ODE using laplace transforms. Initials conditions are optional. |
461 | 493 | |
462 | 494 | INPUT: |
463 | | |
| 495 | |
464 | 496 | - ``de`` - a lambda expression representing the ODE (eg, de = |
465 | 497 | diff(y,x,2) == diff(y,x)+sin(x)) |
466 | 498 | |
467 | | - ``dvar`` - the dependent variable (eg y) |
| 499 | - ``dvar`` - (optional) the dependent variable (eg y) |
468 | 500 | |
469 | 501 | - ``ivar`` - (optional) the independent variable (hereafter called |
470 | 502 | x), which must be specified if there is more than one |
… |
… |
|
478 | 510 | Solution of the ODE as symbolic expression |
479 | 511 | |
480 | 512 | EXAMPLES:: |
481 | | |
| 513 | |
482 | 514 | sage: u=function('u',x) |
483 | 515 | sage: eq = diff(u,x) - exp(-x) - u == 0 |
484 | 516 | sage: desolve_laplace(eq,u) |
485 | 517 | 1/2*(2*u(0) + 1)*e^x - 1/2*e^(-x) |
486 | | |
| 518 | |
487 | 519 | We can use initial conditions:: |
488 | 520 | |
489 | 521 | sage: desolve_laplace(eq,u,ics=[0,3]) |
490 | 522 | -1/2*e^(-x) + 7/2*e^x |
491 | 523 | |
492 | | The initial conditions do not persist in the system (as they persisted |
| 524 | The initial conditions do not persist in the system (as they persisted |
493 | 525 | in previous versions):: |
494 | 526 | |
495 | 527 | sage: desolve_laplace(eq,u) |
… |
… |
|
501 | 533 | sage: eq = diff(f,x) + f == 0 |
502 | 534 | sage: desolve_laplace(eq,f,[0,1]) |
503 | 535 | e^(-x) |
504 | | |
| 536 | |
505 | 537 | :: |
506 | | |
| 538 | |
507 | 539 | sage: x = var('x') |
508 | 540 | sage: f = function('f', x) |
509 | 541 | sage: de = diff(f,x,x) - 2*diff(f,x) + f |
… |
… |
|
523 | 555 | e^(-t) + 1 |
524 | 556 | sage: soln(t=3) |
525 | 557 | e^(-3) + 1 |
526 | | |
527 | | AUTHORS: |
| 558 | |
| 559 | AUTHORS: |
528 | 560 | |
529 | 561 | - David Joyner (1-2006,8-2007) |
530 | | |
| 562 | |
531 | 563 | - Robert Marik (10-2009) |
| 564 | |
| 565 | - Yuri Karadzhov (2010-03-27) |
532 | 566 | """ |
533 | 567 | #This is the original code from David Joyner (inputs and outputs strings) |
534 | 568 | #maxima("de:"+de._repr_()+"=0;") |
… |
… |
|
544 | 578 | ## verbatim copy from desolve - begin |
545 | 579 | if is_SymbolicEquation(de): |
546 | 580 | de = de.lhs() - de.rhs() |
547 | | if is_SymbolicVariable(dvar): |
548 | | raise ValueError, "You have to declare dependent variable as a function, eg. y=function('y',x)" |
549 | | # for backwards compatibility |
550 | | if isinstance(dvar, list): |
551 | | dvar, ivar = dvar |
552 | | elif ivar is None: |
553 | | ivars = de.variables() |
554 | | ivars = [t for t in ivars if t != dvar] |
| 581 | diff_list = map(ops,indets(de,'_diff')) |
| 582 | if len(diff_list) == 0: |
| 583 | raise ValueError, "First argument is not differential equation." |
| 584 | if dvar is None: |
| 585 | dvars = set([x[0] for x in diff_list]) |
| 586 | if len(dvars) != 1: |
| 587 | raise ValueError, "Unable to determine dependent variable, please specify." |
| 588 | dvar=dvars.pop() |
| 589 | else: |
| 590 | if is_SymbolicVariable(dvar): |
| 591 | raise ValueError, "You have to declare dependent variable as a function, eg. y=function('y',x)" |
| 592 | # for backwards compatibility |
| 593 | if isinstance(dvar, list): |
| 594 | dvar, ivar = dvar |
| 595 | if ivar is None: |
| 596 | ivars = set() |
| 597 | for el in diff_list: |
| 598 | ivars = ivars.union(el[1:]) |
555 | 599 | if len(ivars) != 1: |
556 | 600 | raise ValueError, "Unable to determine independent variable, please specify." |
557 | | ivar = ivars[0] |
| 601 | ivar = ivars.pop() |
558 | 602 | ## verbatim copy from desolve - end |
559 | 603 | |
560 | 604 | def sanitize_var(exprs): # 'y(x) -> y(x) |
561 | | return exprs.replace("'"+str(dvar),str(dvar)) |
| 605 | return exprs.replace("'"+str(dvar),str(dvar)) |
562 | 606 | de0=de._maxima_() |
563 | 607 | cmd = sanitize_var("desolve("+de0.str()+","+str(dvar)+")") |
564 | 608 | soln=maxima(cmd).rhs() |
565 | 609 | if str(soln).strip() == 'false': |
566 | | raise NotImplementedError, "Maxima was unable to solve this ODE." |
| 610 | raise NotImplementedError, "Maxima was unable to solve this ODE." |
567 | 611 | soln=soln.sage() |
568 | 612 | if ics!=None: |
569 | 613 | d = len(ics) |
570 | 614 | for i in range(0,d-1): |
571 | | soln=eval('soln.substitute(diff(dvar,ivar,i)('+str(ivar)+'=ics[0])==ics[i+1])') |
| 615 | soln=eval('soln.substitute(diff(dvar,ivar,i)('+str(ivar)+'=ics[0])==ics[i+1])') |
572 | 616 | return soln |
573 | | |
574 | | |
| 617 | |
| 618 | def dsolve_laplace(de, ics=None, dvar=None, ivar=None): |
| 619 | """ |
| 620 | ALIAS for desolve_laplace |
| 621 | sage: x = var('x') |
| 622 | sage: f = function('f', x) |
| 623 | sage: de = diff(f,x,x) - 2*diff(f,x) + f |
| 624 | sage: desolve_laplace(de) |
| 625 | -x*e^x*f(0) + x*e^x*D[0](f)(0) + e^x*f(0) |
| 626 | sage: desolve_laplace(de,[0,1,2]) |
| 627 | x*e^x + e^x |
| 628 | """ |
| 629 | return desolve_laplace(de, dvar, ics, ivar) |
| 630 | |
575 | 631 | def desolve_system(des, vars, ics=None, ivar=None): |
576 | 632 | """ |
577 | 633 | Solves any size system of 1st order ODE's. Initials conditions are optional. |
578 | 634 | |
579 | 635 | INPUT: |
580 | | |
| 636 | |
581 | 637 | - ``des`` - list of ODEs |
582 | | |
| 638 | |
583 | 639 | - ``vars`` - list of dependent variables |
584 | | |
| 640 | |
585 | 641 | - ``ics`` - (optional) list of initial values for ivar and vars |
586 | | |
| 642 | |
587 | 643 | - ``ivar`` - (optional) the independent variable, which must be |
588 | 644 | specified if there is more than one independent variable in the |
589 | 645 | equation. |
… |
… |
|
598 | 654 | sage: desolve_system([de1, de2], [x,y]) |
599 | 655 | [x(t) == (x(0) - 1)*cos(t) - (y(0) - 1)*sin(t) + 1, |
600 | 656 | y(t) == (x(0) - 1)*sin(t) + (y(0) - 1)*cos(t) + 1] |
601 | | |
| 657 | |
602 | 658 | Now we give some initial conditions:: |
603 | | |
| 659 | |
604 | 660 | sage: sol = desolve_system([de1, de2], [x,y], ics=[0,1,2]); sol |
605 | 661 | [x(t) == -sin(t) + 1, y(t) == cos(t) + 1] |
606 | 662 | sage: solnx, solny = sol[0].rhs(), sol[1].rhs() |
607 | 663 | sage: plot([solnx,solny],(0,1)) |
608 | 664 | sage: parametric_plot((solnx,solny),(0,1)) |
609 | 665 | |
610 | | AUTHORS: |
| 666 | AUTHORS: |
611 | 667 | |
612 | 668 | - Robert Bradshaw (10-2008) |
613 | 669 | """ |
… |
… |
|
637 | 693 | for dvar, ic in zip(dvars, ics[:1]): |
638 | 694 | dvar.atvalue(ivar==ivar_ic, dvar) |
639 | 695 | return soln |
640 | | |
| 696 | |
641 | 697 | |
642 | 698 | def desolve_system_strings(des,vars,ics=None): |
643 | 699 | r""" |
… |
… |
|
687 | 743 | sage: P2 = parametric_plot((solnx,solny),(0,1)) |
688 | 744 | |
689 | 745 | Now type show(P1), show(P2) to view these. |
690 | | |
691 | 746 | |
692 | | AUTHORS: |
| 747 | |
| 748 | AUTHORS: |
693 | 749 | |
694 | 750 | - David Joyner (3-2006, 8-2007) |
695 | 751 | """ |
… |
… |
|
721 | 777 | last column. |
722 | 778 | |
723 | 779 | *For pedagogical purposes only.* |
724 | | |
| 780 | |
725 | 781 | EXAMPLES:: |
726 | | |
| 782 | |
727 | 783 | sage: from sage.calculus.desolvers import eulers_method |
728 | 784 | sage: x,y = PolynomialRing(QQ,2,"xy").gens() |
729 | 785 | sage: eulers_method(5*x+y-5,0,1,1/2,1) |
… |
… |
|
777 | 833 | sage: P2 = line(pts) |
778 | 834 | sage: (P1+P2).show() |
779 | 835 | |
780 | | AUTHORS: |
| 836 | AUTHORS: |
781 | 837 | |
782 | 838 | - David Joyner |
783 | 839 | """ |
… |
… |
|
812 | 868 | next (last) column. |
813 | 869 | |
814 | 870 | *For pedagogical purposes only.* |
815 | | |
| 871 | |
816 | 872 | EXAMPLES:: |
817 | 873 | |
818 | 874 | sage: from sage.calculus.desolvers import eulers_method_2x2 |
… |
… |
|
858 | 914 | 3/4 0.63 -0.0078 -0.031 0.11 |
859 | 915 | 1 0.63 0.020 0.079 0.071 |
860 | 916 | |
861 | | To numerically approximate y(1), where `y''+ty'+y=0`, `y(0)=1`, `y'(0)=0`:: |
| 917 | To numerically approximate y(1), where `y''+ty'+y=0`, `y(0)=1`, `y'(0)=0`:: |
862 | 918 | |
863 | 919 | sage: t,x,y=PolynomialRing(RR,3,"txy").gens() |
864 | 920 | sage: f = y; g = -x-y*t |
… |
… |
|
870 | 926 | 3/4 0.88 -0.15 -0.62 -0.10 |
871 | 927 | 1 0.75 -0.17 -0.68 -0.015 |
872 | 928 | |
873 | | AUTHORS: |
| 929 | AUTHORS: |
874 | 930 | |
875 | 931 | - David Joyner |
876 | 932 | """ |
… |
… |
|
900 | 956 | `x(a)=x_0`, `y' = g(t,x,y)`, `y(a) = y_0`. |
901 | 957 | |
902 | 958 | *For pedagogical purposes only.* |
903 | | |
| 959 | |
904 | 960 | EXAMPLES:: |
905 | 961 | |
906 | 962 | sage: from sage.calculus.desolvers import eulers_method_2x2_plot |
… |
… |
|
930 | 986 | def desolve_rk4_determine_bounds(ics,end_points=None): |
931 | 987 | """ |
932 | 988 | Used to determine bounds for numerical integration. |
933 | | |
| 989 | |
934 | 990 | - If end_points is None, the interval for integration is from ics[0] |
935 | 991 | to ics[0]+10 |
936 | 992 | |
… |
… |
|
945 | 1001 | sage: from sage.calculus.desolvers import desolve_rk4_determine_bounds |
946 | 1002 | sage: desolve_rk4_determine_bounds([0,2],1) |
947 | 1003 | (0, 1) |
948 | | |
| 1004 | |
949 | 1005 | :: |
950 | 1006 | |
951 | | sage: desolve_rk4_determine_bounds([0,2]) |
| 1007 | sage: desolve_rk4_determine_bounds([0,2]) |
952 | 1008 | (0, 10) |
953 | | |
| 1009 | |
954 | 1010 | :: |
955 | 1011 | |
956 | 1012 | sage: desolve_rk4_determine_bounds([0,2],[-2]) |
957 | 1013 | (-2, 0) |
958 | | |
| 1014 | |
959 | 1015 | :: |
960 | 1016 | |
961 | 1017 | sage: desolve_rk4_determine_bounds([0,2],[-2,4]) |
962 | 1018 | (-2, 4) |
963 | | |
| 1019 | |
964 | 1020 | """ |
965 | | if end_points is None: |
| 1021 | if end_points is None: |
966 | 1022 | return((ics[0],ics[0]+10)) |
967 | 1023 | if not isinstance(end_points,list): |
968 | 1024 | end_points=[end_points] |
… |
… |
|
970 | 1026 | return (min(ics[0],end_points[0]),max(ics[0],end_points[0])) |
971 | 1027 | else: |
972 | 1028 | return (min(ics[0],end_points[0]),max(ics[0],end_points[1])) |
973 | | |
| 1029 | |
974 | 1030 | |
975 | 1031 | def desolve_rk4(de, dvar, ics=None, ivar=None, end_points=None, step=0.1, output='list', **kwds): |
976 | 1032 | """ |
… |
… |
|
978 | 1034 | equation. See also ``ode_solver``. |
979 | 1035 | |
980 | 1036 | INPUT: |
981 | | |
982 | | input is similar to ``desolve`` command. The differential equation can be |
| 1037 | |
| 1038 | input is similar to ``desolve`` command. The differential equation can be |
983 | 1039 | written in a form close to the plot_slope_field or desolve command |
984 | 1040 | |
985 | 1041 | - Variant 1 (function in two variables) |
986 | | |
| 1042 | |
987 | 1043 | - ``de`` - right hand side, i.e. the function `f(x,y)` from ODE `y'=f(x,y)` |
988 | | |
| 1044 | |
989 | 1045 | - ``dvar`` - dependent variable (symbolic variable declared by var) |
990 | 1046 | |
991 | 1047 | - Variant 2 (symbolic equation) |
… |
… |
|
994 | 1050 | |
995 | 1051 | - ``dvar``` - dependent variable (declared as funciton of independent variable) |
996 | 1052 | |
997 | | - Other parameters |
| 1053 | - Other parameters |
998 | 1054 | |
999 | 1055 | - ``ivar`` - should be specified, if there are more variables or if the equation is autonomous |
1000 | 1056 | |
1001 | 1057 | - ``ics`` - initial conditions in the form [x0,y0] |
1002 | | |
| 1058 | |
1003 | 1059 | - ``end_points`` - the end points of the interval |
1004 | 1060 | |
1005 | 1061 | - if end_points is a or [a], we integrate on between min(ics[0],a) and max(ics[0],a) |
… |
… |
|
1008 | 1064 | - if end_points is [a,b] we integrate on between min(ics[0],a) and max(ics[0],b) |
1009 | 1065 | |
1010 | 1066 | - ``step`` - (optional, default:0.1) the length of the step (positive number) |
1011 | | |
| 1067 | |
1012 | 1068 | - ``output`` - (optional, default: 'list') one of 'list', |
1013 | 1069 | 'plot', 'slope_field' (graph of the solution with slope field) |
1014 | 1070 | |
1015 | | OUTPUT: |
| 1071 | OUTPUT: |
1016 | 1072 | |
1017 | 1073 | Returns a list of points, or plot produced by list_plot, |
1018 | 1074 | optionally with slope field. |
… |
… |
|
1030 | 1086 | |
1031 | 1087 | Variant 1 for input - we can pass ODE in the form used by |
1032 | 1088 | desolve function In this example we integrate bakwards, since |
1033 | | ``end_points < ics[0]``:: |
| 1089 | ``end_points < ics[0]``:: |
1034 | 1090 | |
1035 | | sage: y=function('y',x) |
1036 | | sage: desolve_rk4(diff(y,x)+y*(y-1) == x-2,y,ics=[1,1],step=0.5, end_points=0) |
| 1091 | sage: y=function('y',x) |
| 1092 | sage: desolve_rk4(diff(y,x)+y*(y-1) == x-2,y,ics=[1,1],step=0.5, end_points=0) |
1037 | 1093 | [[0.0, 8.90425710896], [0.5, 1.90932794536], [1, 1]] |
1038 | 1094 | |
1039 | 1095 | Here we show how to plot simple pictures. For more advanced |
… |
… |
|
1042 | 1098 | |
1043 | 1099 | sage: x,y=var('x y') |
1044 | 1100 | sage: P=desolve_rk4(y*(2-y),y,ics=[0,.1],ivar=x,output='slope_field',end_points=[-4,6],thickness=3) |
1045 | | |
| 1101 | |
1046 | 1102 | ALGORITHM: |
1047 | 1103 | |
1048 | 1104 | 4th order Runge-Kutta method. Wrapper for command ``rk`` in |
1049 | 1105 | Maxima's dynamics package. Perhaps could be faster by using |
1050 | 1106 | fast_float instead. |
1051 | 1107 | |
1052 | | AUTHORS: |
| 1108 | AUTHORS: |
1053 | 1109 | |
1054 | 1110 | - Robert Marik (10-2009) |
1055 | 1111 | """ |
1056 | | if ics is None: |
| 1112 | if ics is None: |
1057 | 1113 | raise ValueError, "No initial conditions, specify with ics=[x0,y0]." |
1058 | 1114 | |
1059 | 1115 | if ivar is None: |
… |
… |
|
1110 | 1166 | YMIN=sol[0][1] |
1111 | 1167 | XMAX=XMIN |
1112 | 1168 | YMAX=YMIN |
1113 | | for s,t in sol: |
| 1169 | for s,t in sol: |
1114 | 1170 | if s>XMAX:XMAX=s |
1115 | 1171 | if s<XMIN:XMIN=s |
1116 | 1172 | if t>YMAX:YMAX=t |
… |
… |
|
1124 | 1180 | r""" |
1125 | 1181 | Solves numerically system of first-order ordinary differential |
1126 | 1182 | equations using the 4th order Runge-Kutta method. Wrapper for |
1127 | | Maxima command ``rk``. See also ``ode_solver``. |
| 1183 | Maxima command ``rk``. See also ``ode_solver``. |
1128 | 1184 | |
1129 | 1185 | INPUT: |
1130 | | |
| 1186 | |
1131 | 1187 | input is similar to desolve_system and desolve_rk4 commands |
1132 | | |
| 1188 | |
1133 | 1189 | - ``des`` - right hand sides of the system |
1134 | 1190 | |
1135 | 1191 | - ``vars`` - dependent variables |
… |
… |
|
1139 | 1195 | missing |
1140 | 1196 | |
1141 | 1197 | - ``ics`` - initial conditions in the form [x0,y01,y02,y03,....] |
1142 | | |
| 1198 | |
1143 | 1199 | - ``end_points`` - the end points of the interval |
1144 | | |
| 1200 | |
1145 | 1201 | - if end_points is a or [a], we integrate on between min(ics[0],a) and max(ics[0],a) |
1146 | 1202 | - if end_points is None, we use end_points=ics[0]+10 |
1147 | 1203 | |
… |
… |
|
1164 | 1220 | sage: P=desolve_system_rk4([x*(1-y),-y*(1-x)],[x,y],ics=[0,0.5,2],ivar=t,end_points=20) |
1165 | 1221 | sage: Q=[ [i,j] for i,j,k in P] |
1166 | 1222 | sage: LP=list_plot(Q) |
1167 | | |
| 1223 | |
1168 | 1224 | sage: Q=[ [j,k] for i,j,k in P] |
1169 | 1225 | sage: LP=list_plot(Q) |
1170 | | |
| 1226 | |
1171 | 1227 | ALGORITHM: |
1172 | 1228 | |
1173 | 1229 | 4th order Runge-Kutta method. Wrapper for command ``rk`` in Maxima's |
1174 | 1230 | dynamics package. Perhaps could be faster by using ``fast_float`` |
1175 | 1231 | instead. |
1176 | 1232 | |
1177 | | AUTHOR: |
| 1233 | AUTHOR: |
1178 | 1234 | |
1179 | 1235 | - Robert Marik (10-2009) |
1180 | 1236 | """ |
1181 | 1237 | |
1182 | | if ics is None: |
| 1238 | if ics is None: |
1183 | 1239 | raise ValueError, "No initial conditions, specify with ics=[x0,y01,y02,...]." |
1184 | 1240 | |
1185 | 1241 | ivars = set([]) |
… |
… |
|
1199 | 1255 | x0=ics[0] |
1200 | 1256 | icss = [ics[i]._maxima_().str() for i in range(1,len(ics))] |
1201 | 1257 | icstr = "[" + ",".join(icss) + "]" |
1202 | | step=abs(step) |
| 1258 | step=abs(step) |
1203 | 1259 | |
1204 | 1260 | maxima("load('dynamics)") |
1205 | 1261 | lower_bound,upper_bound=desolve_rk4_determine_bounds(ics,end_points) |
diff -r 46b1ee5997ac -r acadcfa52c47 sage/symbolic/all.py
a
|
b
|
|
8 | 8 | |
9 | 9 | from sage.symbolic.relation import solve, solve_mod, solve_ineq |
10 | 10 | from sage.symbolic.assumptions import assume, forget, assumptions |
| 11 | |
| 12 | from sage.symbolic.mtype import * |