passagemath-symbolics 10.8.1a1__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
- passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
- passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
- passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2838 -0
- sage/calculus/desolvers.py +1864 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +2991 -0
- sage/interfaces/magma_free.py +90 -0
- sage/interfaces/maple.py +1402 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +553 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4010 -0
- sage/manifolds/chart_func.py +3416 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
- sage/manifolds/differentiable/diff_form.py +1660 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1522 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +912 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1725 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2721 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +883 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1347 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1030 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5205 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +987 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +456 -0
- sage/symbolic/callable.pyi +66 -0
- sage/symbolic/comparison_impl.pyi +38 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1286 -0
- sage/symbolic/constants_c_impl.pyi +10 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1727 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/function_factory.pyi +41 -0
- sage/symbolic/getitem_impl.pyi +24 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +271 -0
- sage/symbolic/integration/integral.py +1075 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/operators.pyi +61 -0
- sage/symbolic/pynac_constant_impl.pyi +13 -0
- sage/symbolic/pynac_function_impl.pyi +8 -0
- sage/symbolic/random_tests.py +461 -0
- sage/symbolic/relation.py +2062 -0
- sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyi +110 -0
- sage/symbolic/ring.pyx +1393 -0
- sage/symbolic/series_impl.pyi +10 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1468 -0
|
@@ -0,0 +1,987 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
"""
|
|
3
|
+
Assumptions
|
|
4
|
+
|
|
5
|
+
The ``GenericDeclaration`` class provides assumptions about a symbol or
|
|
6
|
+
function in verbal form. Such assumptions can be made using the :func:`assume`
|
|
7
|
+
function in this module, which also can take any relation of symbolic
|
|
8
|
+
expressions as argument. Use :func:`forget` to clear all assumptions.
|
|
9
|
+
Creating a variable with a specific domain is equivalent with making an
|
|
10
|
+
assumption about it.
|
|
11
|
+
|
|
12
|
+
There is only rudimentary support for consistency and satisfiability checking
|
|
13
|
+
in Sage. Assumptions are used both in Maxima and Pynac to support or refine
|
|
14
|
+
some computations. In the following we show how to make and query assumptions.
|
|
15
|
+
Please see the respective modules for more practical examples.
|
|
16
|
+
|
|
17
|
+
In addition to the global :func:`assumptions` database, :func:`assuming`
|
|
18
|
+
creates reusable, stackable context managers allowing for temporary
|
|
19
|
+
updates of the database for evaluation of a (block of) statements.
|
|
20
|
+
|
|
21
|
+
EXAMPLES:
|
|
22
|
+
|
|
23
|
+
The default domain of a symbolic variable is the complex plane::
|
|
24
|
+
|
|
25
|
+
sage: var('x')
|
|
26
|
+
x
|
|
27
|
+
sage: x.is_real()
|
|
28
|
+
False
|
|
29
|
+
sage: assume(x,'real')
|
|
30
|
+
sage: x.is_real()
|
|
31
|
+
True
|
|
32
|
+
sage: forget()
|
|
33
|
+
sage: x.is_real()
|
|
34
|
+
False
|
|
35
|
+
|
|
36
|
+
Here is the list of acceptable features::
|
|
37
|
+
|
|
38
|
+
sage: from sage.interfaces.maxima_lib import maxima
|
|
39
|
+
sage: ", ".join(map(str, maxima("features")._sage_()))
|
|
40
|
+
'integer, noninteger, even, odd, rational, irrational, real, imaginary,
|
|
41
|
+
complex, analytic, increasing, decreasing, oddfun, evenfun, posfun,
|
|
42
|
+
constant, commutative, lassociative, rassociative, symmetric,
|
|
43
|
+
antisymmetric, integervalued, one_to_one'
|
|
44
|
+
|
|
45
|
+
Set positive domain using a relation::
|
|
46
|
+
|
|
47
|
+
sage: assume(x>0)
|
|
48
|
+
sage: x.is_positive()
|
|
49
|
+
True
|
|
50
|
+
sage: x.is_real()
|
|
51
|
+
True
|
|
52
|
+
sage: assumptions()
|
|
53
|
+
[x > 0]
|
|
54
|
+
|
|
55
|
+
Assumptions also affect operations that do not use Maxima::
|
|
56
|
+
|
|
57
|
+
sage: forget()
|
|
58
|
+
sage: assume(x, 'even')
|
|
59
|
+
sage: assume(x, 'real')
|
|
60
|
+
sage: (-1)^x
|
|
61
|
+
1
|
|
62
|
+
sage: (-gamma(pi))^x
|
|
63
|
+
gamma(pi)^x
|
|
64
|
+
sage: binomial(2*x, x).is_integer()
|
|
65
|
+
True
|
|
66
|
+
|
|
67
|
+
Assumptions are added and in some cases checked for consistency::
|
|
68
|
+
|
|
69
|
+
sage: assume(x>0)
|
|
70
|
+
sage: assume(x<0)
|
|
71
|
+
Traceback (most recent call last):
|
|
72
|
+
...
|
|
73
|
+
ValueError: Assumption is inconsistent
|
|
74
|
+
sage: forget()
|
|
75
|
+
"""
|
|
76
|
+
from sage.rings.cc import CC
|
|
77
|
+
from sage.rings.integer_ring import ZZ
|
|
78
|
+
from sage.rings.rational_field import QQ
|
|
79
|
+
from sage.rings.real_mpfr import RR
|
|
80
|
+
from sage.structure.element import Expression
|
|
81
|
+
from sage.structure.unique_representation import UniqueRepresentation
|
|
82
|
+
|
|
83
|
+
# #30074: We use the keys of a dict to store the assumptions.
|
|
84
|
+
# As of Python 3.6.x, dicts preserve the insertion order.
|
|
85
|
+
# In this way, we keep the same order of the assumptions
|
|
86
|
+
# as previous code that was using lists.
|
|
87
|
+
_assumptions = dict()
|
|
88
|
+
|
|
89
|
+
_valid_feature_strings = set()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class GenericDeclaration(UniqueRepresentation):
|
|
93
|
+
"""
|
|
94
|
+
This class represents generic assumptions, such as a variable being
|
|
95
|
+
an integer or a function being increasing. It passes such
|
|
96
|
+
information to Maxima's declare (wrapped in a context so it is able
|
|
97
|
+
to forget) and to Pynac.
|
|
98
|
+
|
|
99
|
+
INPUT:
|
|
100
|
+
|
|
101
|
+
- ``var`` -- the variable about which assumptions are being made
|
|
102
|
+
|
|
103
|
+
- ``assumption`` -- string containing a Maxima feature, either user
|
|
104
|
+
defined or in the list given by ``maxima('features')``
|
|
105
|
+
|
|
106
|
+
EXAMPLES::
|
|
107
|
+
|
|
108
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration
|
|
109
|
+
sage: decl = GenericDeclaration(x, 'integer')
|
|
110
|
+
sage: decl.assume()
|
|
111
|
+
sage: sin(x*pi)
|
|
112
|
+
0
|
|
113
|
+
sage: decl.forget()
|
|
114
|
+
sage: sin(x*pi)
|
|
115
|
+
sin(pi*x)
|
|
116
|
+
sage: sin(x*pi).simplify()
|
|
117
|
+
sin(pi*x)
|
|
118
|
+
|
|
119
|
+
Here is the list of acceptable features::
|
|
120
|
+
|
|
121
|
+
sage: from sage.interfaces.maxima_lib import maxima
|
|
122
|
+
sage: ", ".join(map(str, maxima("features")._sage_()))
|
|
123
|
+
'integer, noninteger, even, odd, rational, irrational, real, imaginary,
|
|
124
|
+
complex, analytic, increasing, decreasing, oddfun, evenfun, posfun,
|
|
125
|
+
constant, commutative, lassociative, rassociative, symmetric,
|
|
126
|
+
antisymmetric, integervalued, one_to_one'
|
|
127
|
+
|
|
128
|
+
Test unique representation behavior::
|
|
129
|
+
|
|
130
|
+
sage: GenericDeclaration(x, 'integer') is GenericDeclaration(SR.var("x"), 'integer')
|
|
131
|
+
True
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
def __init__(self, var, assumption):
|
|
135
|
+
"""
|
|
136
|
+
This class represents generic assumptions, such as a variable being
|
|
137
|
+
an integer or a function being increasing. It passes such
|
|
138
|
+
information to maxima's declare (wrapped in a context so it is able
|
|
139
|
+
to forget).
|
|
140
|
+
|
|
141
|
+
INPUT:
|
|
142
|
+
|
|
143
|
+
- ``var`` -- the variable about which assumptions are being made
|
|
144
|
+
|
|
145
|
+
- ``assumption`` -- a Maxima feature, either user
|
|
146
|
+
defined or in the list given by ``maxima('features')``
|
|
147
|
+
|
|
148
|
+
EXAMPLES::
|
|
149
|
+
|
|
150
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration
|
|
151
|
+
sage: decl = GenericDeclaration(x, 'integer')
|
|
152
|
+
sage: decl.assume()
|
|
153
|
+
sage: sin(x*pi)
|
|
154
|
+
0
|
|
155
|
+
sage: decl.forget()
|
|
156
|
+
sage: sin(x*pi)
|
|
157
|
+
sin(pi*x)
|
|
158
|
+
|
|
159
|
+
Here is the list of acceptable features::
|
|
160
|
+
|
|
161
|
+
sage: from sage.interfaces.maxima_lib import maxima
|
|
162
|
+
sage: ", ".join(map(str, maxima("features")._sage_()))
|
|
163
|
+
'integer, noninteger, even, odd, rational, irrational, real,
|
|
164
|
+
imaginary, complex, analytic, increasing, decreasing, oddfun,
|
|
165
|
+
evenfun, posfun, constant, commutative, lassociative, rassociative,
|
|
166
|
+
symmetric, antisymmetric, integervalued, one_to_one'
|
|
167
|
+
"""
|
|
168
|
+
self._var = var
|
|
169
|
+
self._assumption = assumption
|
|
170
|
+
self._context = None
|
|
171
|
+
|
|
172
|
+
def __repr__(self):
|
|
173
|
+
"""
|
|
174
|
+
EXAMPLES::
|
|
175
|
+
|
|
176
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration
|
|
177
|
+
sage: GenericDeclaration(x, 'foo')
|
|
178
|
+
x is foo
|
|
179
|
+
"""
|
|
180
|
+
return "%s is %s" % (self._var, self._assumption)
|
|
181
|
+
|
|
182
|
+
def has(self, arg):
|
|
183
|
+
"""
|
|
184
|
+
Check if this assumption contains the argument ``arg``.
|
|
185
|
+
|
|
186
|
+
EXAMPLES::
|
|
187
|
+
|
|
188
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration as GDecl
|
|
189
|
+
sage: var('y')
|
|
190
|
+
y
|
|
191
|
+
sage: d = GDecl(x, 'integer')
|
|
192
|
+
sage: d.has(x)
|
|
193
|
+
True
|
|
194
|
+
sage: d.has(y)
|
|
195
|
+
False
|
|
196
|
+
"""
|
|
197
|
+
return (arg - self._var).is_trivial_zero()
|
|
198
|
+
|
|
199
|
+
def _validate_feature(self):
|
|
200
|
+
"""
|
|
201
|
+
Check if this assumption is a known maxima feature, raise an error otherwise.
|
|
202
|
+
|
|
203
|
+
EXAMPLES::
|
|
204
|
+
|
|
205
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration as GDecl
|
|
206
|
+
sage: var('b')
|
|
207
|
+
b
|
|
208
|
+
sage: GDecl(b, 'bougie')
|
|
209
|
+
b is bougie
|
|
210
|
+
sage: _.assume()
|
|
211
|
+
Traceback (most recent call last):
|
|
212
|
+
...
|
|
213
|
+
ValueError: bougie not a valid assumption, must be one of ['analytic', ... 'symmetric']
|
|
214
|
+
"""
|
|
215
|
+
from sage.calculus.calculus import maxima
|
|
216
|
+
global _valid_feature_strings
|
|
217
|
+
if self._assumption in _valid_feature_strings:
|
|
218
|
+
return
|
|
219
|
+
# We get the list here because features may be added with time.
|
|
220
|
+
_valid_feature_strings.update(repr(x).strip() for x in list(maxima("features")))
|
|
221
|
+
if self._assumption in _valid_feature_strings:
|
|
222
|
+
return
|
|
223
|
+
raise ValueError("%s not a valid assumption, must be one of %s"
|
|
224
|
+
% (self._assumption, sorted(_valid_feature_strings)))
|
|
225
|
+
|
|
226
|
+
def assume(self):
|
|
227
|
+
"""
|
|
228
|
+
Make this assumption.
|
|
229
|
+
|
|
230
|
+
TESTS::
|
|
231
|
+
|
|
232
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration
|
|
233
|
+
sage: decl = GenericDeclaration(x, 'even')
|
|
234
|
+
sage: decl.assume()
|
|
235
|
+
sage: cos(x*pi).simplify()
|
|
236
|
+
1
|
|
237
|
+
sage: decl2 = GenericDeclaration(x, 'odd')
|
|
238
|
+
sage: decl2.assume()
|
|
239
|
+
Traceback (most recent call last):
|
|
240
|
+
...
|
|
241
|
+
ValueError: Assumption is inconsistent
|
|
242
|
+
sage: decl.forget()
|
|
243
|
+
"""
|
|
244
|
+
if self in _assumptions:
|
|
245
|
+
return
|
|
246
|
+
from sage.calculus.calculus import maxima
|
|
247
|
+
cur = None
|
|
248
|
+
context = None
|
|
249
|
+
if self._context is None:
|
|
250
|
+
self._validate_feature()
|
|
251
|
+
cur = maxima.get("context")
|
|
252
|
+
# newcontext makes a fresh context that only has $global as
|
|
253
|
+
# a subcontext, and makes it the current $context,
|
|
254
|
+
# but does not deactivate other current contexts.
|
|
255
|
+
context = maxima.newcontext('context' + maxima._next_var_name())
|
|
256
|
+
must_declare = True
|
|
257
|
+
elif not maxima.featurep(self._var, self._assumption):
|
|
258
|
+
# Reactivating a previously active context.
|
|
259
|
+
# Run $declare again with the assumption
|
|
260
|
+
# to catch possible inconsistency
|
|
261
|
+
# with the active contexts.
|
|
262
|
+
cur = maxima.get("context")
|
|
263
|
+
# Redeclaring on the existing context does not seem to trigger
|
|
264
|
+
# inconsistency checking.
|
|
265
|
+
# maxima.set("context", self._context._maxima_init_())
|
|
266
|
+
# Instead, use a temporary context for this purpose
|
|
267
|
+
context = maxima.newcontext('context' + maxima._next_var_name())
|
|
268
|
+
must_declare = True
|
|
269
|
+
else:
|
|
270
|
+
must_declare = False
|
|
271
|
+
|
|
272
|
+
if must_declare:
|
|
273
|
+
try:
|
|
274
|
+
maxima.eval("declare(%s, %s)" % (self._var._maxima_init_(), self._assumption))
|
|
275
|
+
except RuntimeError as mess:
|
|
276
|
+
if 'inconsistent' in str(mess): # note Maxima doesn't tell you if declarations are redundant
|
|
277
|
+
# Inconsistency with one of the active contexts.
|
|
278
|
+
raise ValueError("Assumption is inconsistent")
|
|
279
|
+
else:
|
|
280
|
+
raise
|
|
281
|
+
else:
|
|
282
|
+
if self._context is None:
|
|
283
|
+
self._context = context
|
|
284
|
+
context = None
|
|
285
|
+
finally:
|
|
286
|
+
assert cur is not None
|
|
287
|
+
maxima.set("context", cur)
|
|
288
|
+
if context is not None:
|
|
289
|
+
maxima.killcontext(context)
|
|
290
|
+
|
|
291
|
+
maxima.activate(self._context)
|
|
292
|
+
self._var.decl_assume(self._assumption)
|
|
293
|
+
_assumptions[self] = True
|
|
294
|
+
|
|
295
|
+
def forget(self):
|
|
296
|
+
"""
|
|
297
|
+
Forget this assumption.
|
|
298
|
+
|
|
299
|
+
TESTS::
|
|
300
|
+
|
|
301
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration
|
|
302
|
+
sage: decl = GenericDeclaration(x, 'odd')
|
|
303
|
+
sage: decl.assume()
|
|
304
|
+
sage: cos(pi*x)
|
|
305
|
+
cos(pi*x)
|
|
306
|
+
sage: cos(pi*x).simplify()
|
|
307
|
+
-1
|
|
308
|
+
sage: decl.forget()
|
|
309
|
+
sage: cos(x*pi).simplify()
|
|
310
|
+
cos(pi*x)
|
|
311
|
+
"""
|
|
312
|
+
self._var.decl_forget(self._assumption)
|
|
313
|
+
from sage.calculus.calculus import maxima
|
|
314
|
+
if self._context is not None:
|
|
315
|
+
try:
|
|
316
|
+
del _assumptions[self]
|
|
317
|
+
except KeyError:
|
|
318
|
+
return
|
|
319
|
+
maxima.deactivate(self._context)
|
|
320
|
+
else: # trying to forget a declaration explicitly rather than implicitly
|
|
321
|
+
for x in _assumptions:
|
|
322
|
+
if repr(self) == repr(x): # so by implication x is also a GenericDeclaration
|
|
323
|
+
x.forget()
|
|
324
|
+
break
|
|
325
|
+
return
|
|
326
|
+
|
|
327
|
+
def contradicts(self, soln):
|
|
328
|
+
"""
|
|
329
|
+
Return ``True`` if this assumption is violated by the given
|
|
330
|
+
variable assignment(s).
|
|
331
|
+
|
|
332
|
+
INPUT:
|
|
333
|
+
|
|
334
|
+
- ``soln`` -- either a dictionary with variables as keys or a symbolic
|
|
335
|
+
relation with a variable on the left hand side
|
|
336
|
+
|
|
337
|
+
EXAMPLES::
|
|
338
|
+
|
|
339
|
+
sage: from sage.symbolic.assumptions import GenericDeclaration
|
|
340
|
+
sage: GenericDeclaration(x, 'integer').contradicts(x==4)
|
|
341
|
+
False
|
|
342
|
+
sage: GenericDeclaration(x, 'integer').contradicts(x==4.0)
|
|
343
|
+
False
|
|
344
|
+
sage: GenericDeclaration(x, 'integer').contradicts(x==4.5)
|
|
345
|
+
True
|
|
346
|
+
sage: GenericDeclaration(x, 'integer').contradicts(x==sqrt(17))
|
|
347
|
+
True
|
|
348
|
+
sage: GenericDeclaration(x, 'noninteger').contradicts(x==sqrt(17))
|
|
349
|
+
False
|
|
350
|
+
sage: GenericDeclaration(x, 'noninteger').contradicts(x==17)
|
|
351
|
+
True
|
|
352
|
+
sage: GenericDeclaration(x, 'even').contradicts(x==3)
|
|
353
|
+
True
|
|
354
|
+
sage: GenericDeclaration(x, 'complex').contradicts(x==3)
|
|
355
|
+
False
|
|
356
|
+
sage: GenericDeclaration(x, 'imaginary').contradicts(x==3)
|
|
357
|
+
True
|
|
358
|
+
sage: GenericDeclaration(x, 'imaginary').contradicts(x==I)
|
|
359
|
+
False
|
|
360
|
+
|
|
361
|
+
sage: var('y,z')
|
|
362
|
+
(y, z)
|
|
363
|
+
sage: GenericDeclaration(x, 'imaginary').contradicts(x==y+z)
|
|
364
|
+
False
|
|
365
|
+
|
|
366
|
+
sage: GenericDeclaration(x, 'rational').contradicts(y==pi)
|
|
367
|
+
False
|
|
368
|
+
sage: GenericDeclaration(x, 'rational').contradicts(x==pi)
|
|
369
|
+
True
|
|
370
|
+
sage: GenericDeclaration(x, 'irrational').contradicts(x!=pi)
|
|
371
|
+
False
|
|
372
|
+
sage: GenericDeclaration(x, 'rational').contradicts({x: pi, y: pi})
|
|
373
|
+
True
|
|
374
|
+
sage: GenericDeclaration(x, 'rational').contradicts({z: pi, y: pi})
|
|
375
|
+
False
|
|
376
|
+
"""
|
|
377
|
+
if isinstance(soln, dict):
|
|
378
|
+
value = soln.get(self._var)
|
|
379
|
+
if value is None:
|
|
380
|
+
return False
|
|
381
|
+
elif soln.lhs() == self._var:
|
|
382
|
+
value = soln.rhs()
|
|
383
|
+
else:
|
|
384
|
+
return False
|
|
385
|
+
try:
|
|
386
|
+
CC(value)
|
|
387
|
+
except TypeError:
|
|
388
|
+
return False
|
|
389
|
+
if self._assumption == 'integer':
|
|
390
|
+
return value not in ZZ
|
|
391
|
+
elif self._assumption == 'noninteger':
|
|
392
|
+
return value in ZZ
|
|
393
|
+
elif self._assumption == 'even':
|
|
394
|
+
return value not in ZZ or bool(ZZ(value) % 2)
|
|
395
|
+
elif self._assumption == 'odd':
|
|
396
|
+
return value not in ZZ or not (ZZ(value) % 2)
|
|
397
|
+
elif self._assumption == 'rational':
|
|
398
|
+
return value not in QQ
|
|
399
|
+
elif self._assumption == 'irrational':
|
|
400
|
+
return value in QQ
|
|
401
|
+
elif self._assumption == 'real':
|
|
402
|
+
return value not in RR
|
|
403
|
+
elif self._assumption == 'imaginary':
|
|
404
|
+
return value not in CC or CC(value).real() != 0
|
|
405
|
+
elif self._assumption == 'complex':
|
|
406
|
+
return value not in CC
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
def preprocess_assumptions(args):
|
|
410
|
+
"""
|
|
411
|
+
Turn a list of the form ``(var1, var2, ..., 'property')`` into a
|
|
412
|
+
sequence of declarations ``(var1 is property), (var2 is property),
|
|
413
|
+
...``
|
|
414
|
+
|
|
415
|
+
EXAMPLES::
|
|
416
|
+
|
|
417
|
+
sage: from sage.symbolic.assumptions import preprocess_assumptions
|
|
418
|
+
sage: preprocess_assumptions([x, 'integer', x > 4])
|
|
419
|
+
[x is integer, x > 4]
|
|
420
|
+
sage: var('x, y')
|
|
421
|
+
(x, y)
|
|
422
|
+
sage: preprocess_assumptions([x, y, 'integer', x > 4, y, 'even'])
|
|
423
|
+
[x is integer, y is integer, x > 4, y is even]
|
|
424
|
+
"""
|
|
425
|
+
args = list(args)
|
|
426
|
+
last = None
|
|
427
|
+
for i, x in reversed(list(enumerate(args))):
|
|
428
|
+
if isinstance(x, str):
|
|
429
|
+
del args[i]
|
|
430
|
+
last = x
|
|
431
|
+
elif ((not hasattr(x, 'assume')
|
|
432
|
+
or (isinstance(x, Expression) and x.is_symbol()))
|
|
433
|
+
and last is not None):
|
|
434
|
+
args[i] = GenericDeclaration(x, last)
|
|
435
|
+
else:
|
|
436
|
+
last = None
|
|
437
|
+
return args
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
def assume(*args):
|
|
441
|
+
r"""
|
|
442
|
+
Make the given assumptions.
|
|
443
|
+
|
|
444
|
+
INPUT:
|
|
445
|
+
|
|
446
|
+
- ``*args`` -- a variable-length sequence of assumptions, each
|
|
447
|
+
consisting of:
|
|
448
|
+
|
|
449
|
+
- any number of symbolic inequalities, like ``0 < x, x < 1``
|
|
450
|
+
|
|
451
|
+
- a subsequence of variable names, followed by some property that
|
|
452
|
+
should be assumed for those variables; for example, ``x, y, z,
|
|
453
|
+
'integer'`` would assume that each of ``x``, ``y``, and ``z``
|
|
454
|
+
are integer variables, and ``x, 'odd'`` would assume that ``x``
|
|
455
|
+
is odd (as opposed to even).
|
|
456
|
+
|
|
457
|
+
The two types can be combined, but a symbolic inequality cannot
|
|
458
|
+
appear in the middle of a list of variables.
|
|
459
|
+
|
|
460
|
+
OUTPUT: if everything goes as planned, there is no output
|
|
461
|
+
|
|
462
|
+
If you assume something that is not one of the two forms above, then
|
|
463
|
+
an :exc:`AttributeError` is raised as we try to call its ``assume``
|
|
464
|
+
method.
|
|
465
|
+
|
|
466
|
+
If you make inconsistent assumptions (for example, that ``x`` is
|
|
467
|
+
both even and odd), then a :exc:`ValueError` is raised.
|
|
468
|
+
|
|
469
|
+
.. WARNING::
|
|
470
|
+
|
|
471
|
+
Do not use Python's chained comparison notation in assumptions.
|
|
472
|
+
Python literally translates the expression ``0 < x < 1`` to
|
|
473
|
+
``(0 < x) and (x < 1)``, but the value of ``bool(0 < x)`` is
|
|
474
|
+
``False`` when ``x`` is a symbolic variable. Therefore, by the
|
|
475
|
+
definition of Python's logical "and" operator, the entire expression
|
|
476
|
+
is equal to ``0 < x``.
|
|
477
|
+
|
|
478
|
+
EXAMPLES:
|
|
479
|
+
|
|
480
|
+
Assumptions are typically used to ensure certain relations are
|
|
481
|
+
evaluated as true that are not true in general.
|
|
482
|
+
|
|
483
|
+
Here, we verify that for `x>0`, `\sqrt{x^2}=x`::
|
|
484
|
+
|
|
485
|
+
sage: assume(x > 0)
|
|
486
|
+
sage: bool(sqrt(x^2) == x)
|
|
487
|
+
True
|
|
488
|
+
|
|
489
|
+
This will be assumed in the current Sage session until forgotten::
|
|
490
|
+
|
|
491
|
+
sage: bool(sqrt(x^2) == x)
|
|
492
|
+
True
|
|
493
|
+
sage: forget()
|
|
494
|
+
sage: bool(sqrt(x^2) == x)
|
|
495
|
+
False
|
|
496
|
+
|
|
497
|
+
Another major use case is in taking certain integrals and limits
|
|
498
|
+
where the answers may depend on some sign condition::
|
|
499
|
+
|
|
500
|
+
sage: var('x, n')
|
|
501
|
+
(x, n)
|
|
502
|
+
sage: assume(n+1>0)
|
|
503
|
+
sage: integral(x^n,x)
|
|
504
|
+
x^(n + 1)/(n + 1)
|
|
505
|
+
sage: forget()
|
|
506
|
+
|
|
507
|
+
::
|
|
508
|
+
|
|
509
|
+
sage: var('q, a, k')
|
|
510
|
+
(q, a, k)
|
|
511
|
+
sage: assume(q > 1)
|
|
512
|
+
sage: sum(a*q^k, k, 0, oo)
|
|
513
|
+
Traceback (most recent call last):
|
|
514
|
+
...
|
|
515
|
+
ValueError: Sum is divergent.
|
|
516
|
+
sage: forget()
|
|
517
|
+
sage: assume(abs(q) < 1)
|
|
518
|
+
sage: sum(a*q^k, k, 0, oo)
|
|
519
|
+
-a/(q - 1)
|
|
520
|
+
sage: forget()
|
|
521
|
+
|
|
522
|
+
An integer constraint::
|
|
523
|
+
|
|
524
|
+
sage: n,P,r,r2 = SR.var('n, P, r, r2')
|
|
525
|
+
sage: assume(n, 'integer')
|
|
526
|
+
sage: c = P*e^(r*n)
|
|
527
|
+
sage: d = P*(1+r2)^n
|
|
528
|
+
sage: solve(c==d,r2)
|
|
529
|
+
[r2 == e^r - 1]
|
|
530
|
+
sage: forget()
|
|
531
|
+
|
|
532
|
+
Simplifying certain well-known identities works as well::
|
|
533
|
+
|
|
534
|
+
sage: n = SR.var('n')
|
|
535
|
+
sage: assume(n, 'integer')
|
|
536
|
+
sage: sin(n*pi)
|
|
537
|
+
0
|
|
538
|
+
sage: forget()
|
|
539
|
+
sage: sin(n*pi).simplify()
|
|
540
|
+
sin(pi*n)
|
|
541
|
+
|
|
542
|
+
Instead of using chained comparison notation, each relationship
|
|
543
|
+
should be passed as a separate assumption::
|
|
544
|
+
|
|
545
|
+
sage: x = SR.var('x')
|
|
546
|
+
sage: assume(0 < x, x < 1) # instead of assume(0 < x < 1)
|
|
547
|
+
sage: assumptions()
|
|
548
|
+
[0 < x, x < 1]
|
|
549
|
+
sage: forget()
|
|
550
|
+
|
|
551
|
+
If you make inconsistent or meaningless assumptions,
|
|
552
|
+
Sage will let you know::
|
|
553
|
+
|
|
554
|
+
sage: assume(x<0)
|
|
555
|
+
sage: assume(x>0)
|
|
556
|
+
Traceback (most recent call last):
|
|
557
|
+
...
|
|
558
|
+
ValueError: Assumption is inconsistent
|
|
559
|
+
sage: assume(x<1)
|
|
560
|
+
Traceback (most recent call last):
|
|
561
|
+
...
|
|
562
|
+
ValueError: Assumption is redundant
|
|
563
|
+
sage: assumptions()
|
|
564
|
+
[x < 0]
|
|
565
|
+
sage: forget()
|
|
566
|
+
sage: assume(x,'even')
|
|
567
|
+
sage: assume(x,'odd')
|
|
568
|
+
Traceback (most recent call last):
|
|
569
|
+
...
|
|
570
|
+
ValueError: Assumption is inconsistent
|
|
571
|
+
sage: forget()
|
|
572
|
+
|
|
573
|
+
You can also use assumptions to evaluate simple
|
|
574
|
+
truth values::
|
|
575
|
+
|
|
576
|
+
sage: x, y, z = var('x, y, z')
|
|
577
|
+
sage: assume(x>=y,y>=z,z>=x)
|
|
578
|
+
sage: bool(x==z)
|
|
579
|
+
True
|
|
580
|
+
sage: bool(z<x)
|
|
581
|
+
False
|
|
582
|
+
sage: bool(z>y)
|
|
583
|
+
False
|
|
584
|
+
sage: bool(y==z)
|
|
585
|
+
True
|
|
586
|
+
sage: forget()
|
|
587
|
+
sage: assume(x>=1,x<=1)
|
|
588
|
+
sage: bool(x==1)
|
|
589
|
+
True
|
|
590
|
+
sage: bool(x>1)
|
|
591
|
+
False
|
|
592
|
+
sage: forget()
|
|
593
|
+
|
|
594
|
+
TESTS:
|
|
595
|
+
|
|
596
|
+
Test that you can do two non-relational
|
|
597
|
+
declarations at once (fixing :issue:`7084`)::
|
|
598
|
+
|
|
599
|
+
sage: var('m,n')
|
|
600
|
+
(m, n)
|
|
601
|
+
sage: assume(n, 'integer'); assume(m, 'integer')
|
|
602
|
+
sage: sin(n*pi).simplify()
|
|
603
|
+
0
|
|
604
|
+
sage: sin(m*pi).simplify()
|
|
605
|
+
0
|
|
606
|
+
sage: forget()
|
|
607
|
+
sage: sin(n*pi).simplify()
|
|
608
|
+
sin(pi*n)
|
|
609
|
+
sage: sin(m*pi).simplify()
|
|
610
|
+
sin(pi*m)
|
|
611
|
+
|
|
612
|
+
Check that positive integers can be created (:issue:`20132`)
|
|
613
|
+
|
|
614
|
+
sage: x = SR.var('x', domain='positive')
|
|
615
|
+
sage: assume(x, 'integer')
|
|
616
|
+
sage: x.is_positive() and x.is_integer()
|
|
617
|
+
True
|
|
618
|
+
sage: forget()
|
|
619
|
+
|
|
620
|
+
sage: x = SR.var('x', domain='integer')
|
|
621
|
+
sage: assume(x > 0)
|
|
622
|
+
sage: x.is_positive() and x.is_integer()
|
|
623
|
+
True
|
|
624
|
+
sage: forget()
|
|
625
|
+
|
|
626
|
+
sage: assume(x, "integer")
|
|
627
|
+
sage: assume(x > 0)
|
|
628
|
+
sage: x.is_positive() and x.is_integer()
|
|
629
|
+
True
|
|
630
|
+
sage: forget()
|
|
631
|
+
|
|
632
|
+
Ensure that an :exc:`AttributeError` is raised if we are given junk::
|
|
633
|
+
|
|
634
|
+
sage: assume(3)
|
|
635
|
+
Traceback (most recent call last):
|
|
636
|
+
...
|
|
637
|
+
AttributeError: 'sage.rings.integer.Integer' object has no
|
|
638
|
+
attribute 'assume'...
|
|
639
|
+
|
|
640
|
+
Ensure that we can combine the two types of assumptions, as documented::
|
|
641
|
+
|
|
642
|
+
sage: x,y = SR.var('x,y')
|
|
643
|
+
sage: assume(x > 0, x, y, 'integer')
|
|
644
|
+
sage: assumptions()
|
|
645
|
+
[x > 0, x is integer, y is integer]
|
|
646
|
+
sage: forget()
|
|
647
|
+
sage: assume(x, y, 'integer', x > 0)
|
|
648
|
+
sage: assumptions()
|
|
649
|
+
[x is integer, y is integer, x > 0]
|
|
650
|
+
sage: forget()
|
|
651
|
+
|
|
652
|
+
Test that our WARNING block is accurate::
|
|
653
|
+
|
|
654
|
+
sage: x = SR.var('x')
|
|
655
|
+
sage: bool(0 < x)
|
|
656
|
+
False
|
|
657
|
+
sage: 0 < x < 1
|
|
658
|
+
0 < x
|
|
659
|
+
sage: assume(0 < x < 1)
|
|
660
|
+
sage: assumptions()
|
|
661
|
+
[0 < x]
|
|
662
|
+
sage: forget()
|
|
663
|
+
|
|
664
|
+
Check that :issue:`28538` is fixed::
|
|
665
|
+
|
|
666
|
+
sage: x, y = SR.var('x, y')
|
|
667
|
+
sage: assume(x > 0)
|
|
668
|
+
sage: assume(y > 0)
|
|
669
|
+
sage: bool(y*(x - y) == 0)
|
|
670
|
+
False
|
|
671
|
+
"""
|
|
672
|
+
for x in preprocess_assumptions(args):
|
|
673
|
+
if isinstance(x, (tuple, list)):
|
|
674
|
+
assume(*x)
|
|
675
|
+
else:
|
|
676
|
+
x.assume()
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
def forget(*args):
|
|
680
|
+
"""
|
|
681
|
+
Forget the given assumption, or call with no arguments to forget
|
|
682
|
+
all assumptions.
|
|
683
|
+
|
|
684
|
+
Here an assumption is some sort of symbolic constraint.
|
|
685
|
+
|
|
686
|
+
INPUT:
|
|
687
|
+
|
|
688
|
+
- ``*args`` -- assumptions (default: forget all assumptions)
|
|
689
|
+
|
|
690
|
+
EXAMPLES:
|
|
691
|
+
|
|
692
|
+
We define and forget multiple assumptions::
|
|
693
|
+
|
|
694
|
+
sage: forget()
|
|
695
|
+
sage: var('x,y,z')
|
|
696
|
+
(x, y, z)
|
|
697
|
+
sage: assume(x>0, y>0, z == 1, y>0)
|
|
698
|
+
sage: sorted(assumptions(), key=lambda x:str(x))
|
|
699
|
+
[x > 0, y > 0, z == 1]
|
|
700
|
+
sage: forget(x>0, z==1)
|
|
701
|
+
sage: assumptions()
|
|
702
|
+
[y > 0]
|
|
703
|
+
sage: assume(y, 'even', z, 'complex')
|
|
704
|
+
sage: assumptions()
|
|
705
|
+
[y > 0, y is even, z is complex]
|
|
706
|
+
sage: cos(y*pi).simplify()
|
|
707
|
+
1
|
|
708
|
+
sage: forget(y,'even')
|
|
709
|
+
sage: cos(y*pi).simplify()
|
|
710
|
+
cos(pi*y)
|
|
711
|
+
sage: assumptions()
|
|
712
|
+
[y > 0, z is complex]
|
|
713
|
+
sage: forget()
|
|
714
|
+
sage: assumptions()
|
|
715
|
+
[]
|
|
716
|
+
"""
|
|
717
|
+
if len(args) == 0:
|
|
718
|
+
_forget_all()
|
|
719
|
+
return
|
|
720
|
+
for x in preprocess_assumptions(args):
|
|
721
|
+
if isinstance(x, (tuple, list)):
|
|
722
|
+
forget(*x)
|
|
723
|
+
else:
|
|
724
|
+
try:
|
|
725
|
+
x.forget()
|
|
726
|
+
except KeyError:
|
|
727
|
+
raise TypeError("forget not defined for objects of type '%s'" % type(x))
|
|
728
|
+
|
|
729
|
+
|
|
730
|
+
def assumptions(*args):
|
|
731
|
+
"""
|
|
732
|
+
List all current symbolic assumptions.
|
|
733
|
+
|
|
734
|
+
INPUT:
|
|
735
|
+
|
|
736
|
+
- ``args`` -- list of variables which can be empty
|
|
737
|
+
|
|
738
|
+
OUTPUT: list of assumptions on variables; if ``args`` is empty it returns all
|
|
739
|
+
assumptions
|
|
740
|
+
|
|
741
|
+
EXAMPLES::
|
|
742
|
+
|
|
743
|
+
sage: var('x, y, z, w')
|
|
744
|
+
(x, y, z, w)
|
|
745
|
+
sage: forget()
|
|
746
|
+
sage: assume(x^2+y^2 > 0)
|
|
747
|
+
sage: assumptions()
|
|
748
|
+
[x^2 + y^2 > 0]
|
|
749
|
+
sage: forget(x^2+y^2 > 0)
|
|
750
|
+
sage: assumptions()
|
|
751
|
+
[]
|
|
752
|
+
sage: assume(x > y)
|
|
753
|
+
sage: assume(z > w)
|
|
754
|
+
sage: sorted(assumptions(), key=lambda x: str(x))
|
|
755
|
+
[x > y, z > w]
|
|
756
|
+
sage: forget()
|
|
757
|
+
sage: assumptions()
|
|
758
|
+
[]
|
|
759
|
+
|
|
760
|
+
It is also possible to query for assumptions on a variable independently::
|
|
761
|
+
|
|
762
|
+
sage: x, y, z = var('x y z')
|
|
763
|
+
sage: assume(x, 'integer')
|
|
764
|
+
sage: assume(y > 0)
|
|
765
|
+
sage: assume(y**2 + z**2 == 1)
|
|
766
|
+
sage: assume(x < 0)
|
|
767
|
+
sage: assumptions()
|
|
768
|
+
[x is integer, y > 0, y^2 + z^2 == 1, x < 0]
|
|
769
|
+
sage: assumptions(x)
|
|
770
|
+
[x is integer, x < 0]
|
|
771
|
+
sage: assumptions(x, y)
|
|
772
|
+
[x is integer, x < 0, y > 0, y^2 + z^2 == 1]
|
|
773
|
+
sage: assumptions(z)
|
|
774
|
+
[y^2 + z^2 == 1]
|
|
775
|
+
"""
|
|
776
|
+
if len(args) == 0:
|
|
777
|
+
return list(_assumptions)
|
|
778
|
+
|
|
779
|
+
result = []
|
|
780
|
+
if len(args) == 1:
|
|
781
|
+
result.extend([statement for statement in _assumptions
|
|
782
|
+
if statement.has(args[0])])
|
|
783
|
+
else:
|
|
784
|
+
for v in args:
|
|
785
|
+
result += [statement for statement in list(_assumptions)
|
|
786
|
+
if str(v) in str(statement)]
|
|
787
|
+
return result
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
def _forget_all():
|
|
791
|
+
"""
|
|
792
|
+
Forget all symbolic assumptions.
|
|
793
|
+
|
|
794
|
+
This is called by ``forget()``.
|
|
795
|
+
|
|
796
|
+
EXAMPLES::
|
|
797
|
+
|
|
798
|
+
sage: forget()
|
|
799
|
+
sage: var('x,y')
|
|
800
|
+
(x, y)
|
|
801
|
+
sage: assume(x > 0, y < 0)
|
|
802
|
+
sage: bool(x*y < 0) # means definitely true
|
|
803
|
+
True
|
|
804
|
+
sage: bool(x*y > 0) # might not be true
|
|
805
|
+
False
|
|
806
|
+
sage: forget() # implicitly calls _forget_all
|
|
807
|
+
sage: bool(x*y < 0) # might not be true
|
|
808
|
+
False
|
|
809
|
+
sage: bool(x*y > 0) # might not be true
|
|
810
|
+
False
|
|
811
|
+
|
|
812
|
+
TESTS:
|
|
813
|
+
|
|
814
|
+
Check that :issue:`7315` is fixed::
|
|
815
|
+
|
|
816
|
+
sage: var('m,n')
|
|
817
|
+
(m, n)
|
|
818
|
+
sage: assume(n, 'integer'); assume(m, 'integer')
|
|
819
|
+
sage: sin(n*pi).simplify()
|
|
820
|
+
0
|
|
821
|
+
sage: sin(m*pi).simplify()
|
|
822
|
+
0
|
|
823
|
+
sage: forget()
|
|
824
|
+
sage: sin(n*pi).simplify()
|
|
825
|
+
sin(pi*n)
|
|
826
|
+
sage: sin(m*pi).simplify()
|
|
827
|
+
sin(pi*m)
|
|
828
|
+
"""
|
|
829
|
+
global _assumptions
|
|
830
|
+
if not _assumptions:
|
|
831
|
+
return
|
|
832
|
+
for x in list(_assumptions):
|
|
833
|
+
# need to do this because x.forget() removes x from _assumptions
|
|
834
|
+
x.forget()
|
|
835
|
+
_assumptions = dict()
|
|
836
|
+
|
|
837
|
+
|
|
838
|
+
class assuming:
|
|
839
|
+
"""
|
|
840
|
+
Temporarily modify assumptions.
|
|
841
|
+
|
|
842
|
+
Create a context manager in which temporary assumptions are added
|
|
843
|
+
(or substituted) to the current assumptions set.
|
|
844
|
+
|
|
845
|
+
The set of possible assumptions and declarations is the same as for
|
|
846
|
+
:func:`assume`.
|
|
847
|
+
|
|
848
|
+
This can be useful in interactive mode to discover the assumptions
|
|
849
|
+
necessary to a given integration, or the exact solution to a system of
|
|
850
|
+
equations.
|
|
851
|
+
|
|
852
|
+
It can also be used to explore the branches of a :func:`cases()` expression.
|
|
853
|
+
|
|
854
|
+
As with :func:`assume`, it is an error to add an assumption either redundant
|
|
855
|
+
or inconsistent with the current assumption set (unless ``replace=True`` is
|
|
856
|
+
used). See examples.
|
|
857
|
+
|
|
858
|
+
INPUT:
|
|
859
|
+
|
|
860
|
+
- ``*args`` -- assumptions (same format as for :func:`assume`)
|
|
861
|
+
|
|
862
|
+
- ``replace`` -- boolean (default: ``False``); specifies whether the new
|
|
863
|
+
assumptions are added to (default) or replace (if ``replace=True``) the
|
|
864
|
+
current assumption set
|
|
865
|
+
|
|
866
|
+
OUTPUT:
|
|
867
|
+
|
|
868
|
+
A context manager useable in a ``with`` statement (see examples).
|
|
869
|
+
|
|
870
|
+
EXAMPLES:
|
|
871
|
+
|
|
872
|
+
Basic functionality : inside a :func:`with assuming:` block, Sage uses the
|
|
873
|
+
updated assumptions database. After exit, the original database is
|
|
874
|
+
restored. ::
|
|
875
|
+
|
|
876
|
+
sage: var("x")
|
|
877
|
+
x
|
|
878
|
+
sage: forget(assumptions())
|
|
879
|
+
sage: solve(x^2 == 4,x)
|
|
880
|
+
[x == -2, x == 2]
|
|
881
|
+
sage: with assuming(x > 0):
|
|
882
|
+
....: solve(x^2 == 4,x)
|
|
883
|
+
[x == 2]
|
|
884
|
+
sage: assumptions()
|
|
885
|
+
[]
|
|
886
|
+
|
|
887
|
+
The local assumptions can be stacked. We can use this functionality to
|
|
888
|
+
discover incrementally the assumptions necessary to a given calculation
|
|
889
|
+
(and by the way, to check that Sage's default integrator
|
|
890
|
+
(Maxima's, that is), sometimes nitpicks for naught). ::
|
|
891
|
+
|
|
892
|
+
sage: var("y,k,theta")
|
|
893
|
+
(y, k, theta)
|
|
894
|
+
sage: dgamma(y,k,theta)=y^(k-1)*e^(-y/theta)/(theta^k*gamma(k))
|
|
895
|
+
sage: integrate(dgamma(y,k,theta),y,0,oo)
|
|
896
|
+
Traceback (most recent call last):
|
|
897
|
+
...
|
|
898
|
+
ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(theta>0)', see `assume?` for more details)
|
|
899
|
+
Is theta positive or negative?
|
|
900
|
+
sage: a1=assuming(theta>0)
|
|
901
|
+
sage: with a1:integrate(dgamma(y,k,theta),y,0,oo)
|
|
902
|
+
Traceback (most recent call last):
|
|
903
|
+
...
|
|
904
|
+
ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(k>0)', see `assume?` for more details)
|
|
905
|
+
Is k positive, negative or zero?
|
|
906
|
+
sage: a2=assuming(k>0)
|
|
907
|
+
sage: with a1,a2:integrate(dgamma(y,k,theta),y,0,oo)
|
|
908
|
+
Traceback (most recent call last):
|
|
909
|
+
...
|
|
910
|
+
ValueError: Computation failed since Maxima requested additional constraints; using the 'assume' command before evaluation *may* help (example of legal syntax is 'assume(k>0)', see `assume?` for more details)
|
|
911
|
+
Is k an integer?
|
|
912
|
+
sage: a3=assuming(k,"noninteger")
|
|
913
|
+
sage: with a1,a2,a3:integrate(dgamma(y,k,theta),y,0,oo)
|
|
914
|
+
1
|
|
915
|
+
sage: a4=assuming(k,"integer")
|
|
916
|
+
sage: with a1,a2,a4:integrate(dgamma(y,k,theta),y,0,oo)
|
|
917
|
+
1
|
|
918
|
+
|
|
919
|
+
As mentioned above, it is an error to try to introduce redundant or
|
|
920
|
+
inconsistent assumptions. ::
|
|
921
|
+
|
|
922
|
+
sage: assume(x > 0)
|
|
923
|
+
sage: with assuming(x > -1): "I won't see this"
|
|
924
|
+
Traceback (most recent call last):
|
|
925
|
+
...
|
|
926
|
+
ValueError: Assumption is redundant
|
|
927
|
+
|
|
928
|
+
sage: with assuming(x < -1): "I won't see this"
|
|
929
|
+
Traceback (most recent call last):
|
|
930
|
+
...
|
|
931
|
+
ValueError: Assumption is inconsistent
|
|
932
|
+
"""
|
|
933
|
+
def __init__(self, *args, **kwds):
|
|
934
|
+
r"""
|
|
935
|
+
EXAMPLES::
|
|
936
|
+
|
|
937
|
+
sage: forget()
|
|
938
|
+
sage: foo = assuming(x>0)
|
|
939
|
+
sage: foo.Ass
|
|
940
|
+
(x > 0,)
|
|
941
|
+
sage: bool(x>-1)
|
|
942
|
+
False
|
|
943
|
+
"""
|
|
944
|
+
self.replace = kwds.pop("replace", False)
|
|
945
|
+
self.Ass = args
|
|
946
|
+
|
|
947
|
+
def __enter__(self):
|
|
948
|
+
r"""
|
|
949
|
+
EXAMPLES::
|
|
950
|
+
|
|
951
|
+
sage: forget()
|
|
952
|
+
sage: foo = assuming(x>0)
|
|
953
|
+
sage: bool(x>-1)
|
|
954
|
+
False
|
|
955
|
+
sage: foo.__enter__()
|
|
956
|
+
sage: bool(x>-1)
|
|
957
|
+
True
|
|
958
|
+
sage: foo.__exit__()
|
|
959
|
+
sage: bool(x>-1)
|
|
960
|
+
False
|
|
961
|
+
"""
|
|
962
|
+
if self.replace:
|
|
963
|
+
self.OldAss = assumptions()
|
|
964
|
+
forget(assumptions())
|
|
965
|
+
assume(self.Ass)
|
|
966
|
+
|
|
967
|
+
def __exit__(self, *args, **kwds):
|
|
968
|
+
r"""
|
|
969
|
+
EXAMPLES::
|
|
970
|
+
|
|
971
|
+
sage: forget()
|
|
972
|
+
sage: foo = assuming(x>0)
|
|
973
|
+
sage: bool(x>-1)
|
|
974
|
+
False
|
|
975
|
+
sage: foo.__enter__()
|
|
976
|
+
sage: bool(x>-1)
|
|
977
|
+
True
|
|
978
|
+
sage: foo.__exit__()
|
|
979
|
+
sage: bool(x>-1)
|
|
980
|
+
False
|
|
981
|
+
sage: forget()
|
|
982
|
+
"""
|
|
983
|
+
if self.replace:
|
|
984
|
+
forget(assumptions())
|
|
985
|
+
assume(self.OldAss)
|
|
986
|
+
elif len(self.Ass) > 0:
|
|
987
|
+
forget(self.Ass)
|