Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/functions/min_max.py
4049 views
1
###############################################################################
2
# Sage: Open Source Mathematical Software
3
# Copyright (C) 2010 Burcin Erocal <[email protected]>
4
# Distributed under the terms of the GNU General Public License (GPL),
5
# version 2 or any later version. The full text of the GPL is available at:
6
# http://www.gnu.org/licenses/
7
###############################################################################
8
9
from sage.symbolic.function import BuiltinFunction
10
from sage.symbolic.expression import Expression
11
from sage.symbolic.ring import SR
12
13
from __builtin__ import max as builtin_max, min as builtin_min
14
15
class MinMax_base(BuiltinFunction):
16
def eval_helper(self, this_f, builtin_f, initial_val, args):
17
"""
18
EXAMPLES::
19
20
sage: max_symbolic(3,5,x) # indirect doctest
21
max(x, 5)
22
sage: min_symbolic(3,5,x)
23
min(x, 3)
24
"""
25
# __call__ ensures that if args is a singleton, the element is iterable
26
arg_is_iter = False
27
if len(args) == 1:
28
arg_is_iter = True
29
args = args[0]
30
31
symb_args = []
32
res = initial_val
33
num_non_symbolic_args = 0
34
for x in args:
35
if isinstance(x, Expression):
36
symb_args.append(x)
37
else:
38
num_non_symbolic_args += 1
39
res = builtin_f(res, x)
40
41
# if no symbolic arguments, return the result
42
if len(symb_args) == 0:
43
if res is None:
44
# this is a hack to get the function to return None to the user
45
# the convention to leave a given symbolic function unevaluated
46
# is to return None from the _eval_ function, so we need
47
# a trick to indicate that the return value of the function is
48
# really None
49
# this is caught in the __call__ method, which knows to return
50
# None in this case
51
raise ValueError("return None")
52
return res
53
54
# if all arguments were symbolic return
55
if num_non_symbolic_args <= 1 and not arg_is_iter:
56
return None
57
58
if res is not None: symb_args.append(res)
59
return this_f(*symb_args)
60
61
def __call__(self, *args, **kwds):
62
"""
63
EXAMPLES::
64
65
sage: max_symbolic(3,5,x)
66
max(x, 5)
67
sage: max_symbolic(3,5,x, hold=True)
68
max(3, 5, x)
69
sage: max_symbolic([3,5,x])
70
max(x, 5)
71
72
::
73
74
sage: min_symbolic(3,5,x)
75
min(x, 3)
76
sage: min_symbolic(3,5,x, hold=True)
77
min(3, 5, x)
78
sage: min_symbolic([3,5,x])
79
min(x, 3)
80
81
TESTS:
82
83
We get an exception if no arguments are given::
84
85
sage: max_symbolic()
86
Traceback (most recent call last):
87
...
88
ValueError: number of arguments must be > 0
89
90
Check if we return None, when the builtin function would::
91
92
sage: max_symbolic([None]) is None
93
True
94
sage: max_symbolic([None, None]) is None
95
True
96
sage: min_symbolic([None]) is None
97
True
98
sage: min_symbolic([None, None]) is None
99
True
100
101
Check if a single argument which is not iterable works::
102
103
sage: max_symbolic(None)
104
Traceback (most recent call last):
105
...
106
TypeError: 'NoneType' object is not iterable
107
sage: max_symbolic(5)
108
Traceback (most recent call last):
109
...
110
TypeError: 'sage.rings.integer.Integer' object is not iterable
111
sage: max_symbolic(x)
112
Traceback (most recent call last):
113
...
114
TypeError: 'sage.symbolic.expression.Expression' object is not iterable
115
sage: min_symbolic(5)
116
Traceback (most recent call last):
117
...
118
TypeError: 'sage.rings.integer.Integer' object is not iterable
119
sage: min_symbolic(x)
120
Traceback (most recent call last):
121
...
122
TypeError: 'sage.symbolic.expression.Expression' object is not iterable
123
"""
124
if len(args) == 0:
125
raise ValueError("number of arguments must be > 0")
126
if len(args) == 1:
127
try:
128
args=(SR._force_pyobject(iter(args[0])),)
129
except TypeError, e:
130
raise e
131
132
try:
133
return BuiltinFunction.__call__(self, *args, **kwds)
134
except ValueError, e:
135
if e.args[0] == "return None":
136
return None
137
138
class MaxSymbolic(MinMax_base):
139
def __init__(self):
140
r"""
141
Symbolic `max` function.
142
143
The Python builtin `max` function doesn't work as expected when symbolic
144
expressions are given as arguments. This function delays evaluation
145
until all symbolic arguments are substituted with values.
146
147
EXAMPLES::
148
149
sage: max_symbolic(3, x)
150
max(3, x)
151
sage: max_symbolic(3, x).subs(x=5)
152
5
153
sage: max_symbolic(3, 5, x)
154
max(x, 5)
155
sage: max_symbolic([3,5,x])
156
max(x, 5)
157
158
TESTS::
159
160
sage: loads(dumps(max_symbolic(x,5)))
161
max(x, 5)
162
sage: latex(max_symbolic(x,5))
163
\max\left(x, 5\right)
164
"""
165
BuiltinFunction.__init__(self, 'max', nargs=0, latex_name="\max")
166
167
def _eval_(self, *args):
168
"""
169
EXAMPLES::
170
171
sage: t = max_symbolic(x, 5); t
172
max(x, 5)
173
sage: t.subs(x=3) # indirect doctest
174
5
175
sage: max_symbolic(5,3)
176
5
177
sage: u = max_symbolic(*(range(10)+[x])); u
178
max(x, 9)
179
sage: u.subs(x=-1)
180
9
181
sage: u.subs(x=10)
182
10
183
sage: max_symbolic([0,x])
184
max(x, 0)
185
186
TESTS::
187
188
sage: max_symbolic()
189
Traceback (most recent call last):
190
...
191
ValueError: number of arguments must be > 0
192
"""
193
return self.eval_helper(max_symbolic, builtin_max, None, args)
194
195
def _evalf_(self, *args, **kwds):
196
"""
197
EXAMPLES::
198
199
sage: t = max_symbolic(sin(x), cos(x))
200
sage: t.subs(x=1).n(200)
201
0.84147098480789650665250232163029899962256306079837106567275
202
sage: var('y')
203
y
204
sage: t = max_symbolic(sin(x), cos(x), y)
205
sage: u = t.subs(x=1); u
206
max(sin(1), cos(1), y)
207
sage: u.n()
208
Traceback (most recent call last):
209
...
210
TypeError: cannot evaluate symbolic expression numerically
211
212
::
213
214
sage: f = max_symbolic(sin(x), cos(x))
215
sage: r = integral(f, x, 0, 1)
216
sage: r.n()
217
0.8739124411567263
218
"""
219
return max_symbolic(args)
220
221
max_symbolic = MaxSymbolic()
222
223
224
class MinSymbolic(MinMax_base):
225
def __init__(self):
226
r"""
227
Symbolic `min` function.
228
229
The Python builtin `min` function doesn't work as expected when symbolic
230
expressions are given as arguments. This function delays evaluation
231
until all symbolic arguments are substituted with values.
232
233
EXAMPLES::
234
235
sage: min_symbolic(3, x)
236
min(3, x)
237
sage: min_symbolic(3, x).subs(x=5)
238
3
239
sage: min_symbolic(3, 5, x)
240
min(x, 3)
241
sage: min_symbolic([3,5,x])
242
min(x, 3)
243
244
TESTS::
245
246
sage: loads(dumps(min_symbolic(x,5)))
247
min(x, 5)
248
sage: latex(min_symbolic(x,5))
249
\min\left(x, 5\right)
250
"""
251
BuiltinFunction.__init__(self, 'min', nargs=0, latex_name="\min")
252
253
def _eval_(self, *args):
254
"""
255
EXAMPLES::
256
257
sage: t = min_symbolic(x, 5); t
258
min(x, 5)
259
sage: t.subs(x=3) # indirect doctest
260
3
261
sage: min_symbolic(5,3)
262
3
263
sage: u = min_symbolic(*(range(10)+[x])); u
264
min(x, 0)
265
sage: u.subs(x=-1)
266
-1
267
sage: u.subs(x=10)
268
0
269
sage: min_symbolic([3,x])
270
min(x, 3)
271
272
TESTS::
273
274
sage: min_symbolic()
275
Traceback (most recent call last):
276
...
277
ValueError: number of arguments must be > 0
278
"""
279
return self.eval_helper(min_symbolic, builtin_min, float('inf'), args)
280
281
def _evalf_(self, *args, **kwds):
282
"""
283
EXAMPLES::
284
285
sage: t = min_symbolic(sin(x), cos(x))
286
sage: t.subs(x=1).n(200)
287
0.54030230586813971740093660744297660373231042061792222767010
288
sage: var('y')
289
y
290
sage: t = min_symbolic(sin(x), cos(x), y)
291
sage: u = t.subs(x=1); u
292
min(sin(1), cos(1), y)
293
sage: u.n()
294
Traceback (most recent call last):
295
...
296
TypeError: cannot evaluate symbolic expression numerically
297
"""
298
return min_symbolic(args)
299
300
min_symbolic = MinSymbolic()
301
302