passagemath-symbolics 10.6.37__cp314-cp314t-macosx_13_0_arm64.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/.dylibs/libgmp.10.dylib +0 -0
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.6.37.dist-info/METADATA +187 -0
- passagemath_symbolics-10.6.37.dist-info/RECORD +172 -0
- passagemath_symbolics-10.6.37.dist-info/WHEEL +6 -0
- passagemath_symbolics-10.6.37.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2826 -0
- sage/calculus/desolvers.py +1866 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-darwin.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-darwin.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1035 -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 +743 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2409 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1082 -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 +3017 -0
- sage/interfaces/magma_free.py +92 -0
- sage/interfaces/maple.py +1397 -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 +555 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4019 -0
- sage/manifolds/chart_func.py +3419 -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 +1671 -0
- sage/manifolds/differentiable/diff_form.py +1658 -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 +1520 -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 +910 -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 +1728 -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 +2764 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +885 -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 +1342 -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-darwin.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1022 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-darwin.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1029 -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 +4153 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5237 -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 +985 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +459 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1287 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1713 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +270 -0
- sage/symbolic/integration/integral.py +1115 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/random_tests.py +462 -0
- sage/symbolic/relation.py +1907 -0
- sage/symbolic/ring.cpython-314t-darwin.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyx +1396 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1470 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
"""
|
|
3
|
+
Randomized tests of GiNaC / PyNaC
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
###############################################################################
|
|
7
|
+
# Sage: Open Source Mathematical Software
|
|
8
|
+
# Copyright (C) 2008 William Stein <wstein@gmail.com>
|
|
9
|
+
# Copyright (C) 2008 Burcin Erocal <burcin@erocal.org>
|
|
10
|
+
# Distributed under the terms of the GNU General Public License (GPL),
|
|
11
|
+
# version 2 or any later version. The full text of the GPL is available at:
|
|
12
|
+
# https://www.gnu.org/licenses/
|
|
13
|
+
###############################################################################
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
from sage.misc.prandom import randint, random
|
|
17
|
+
import operator
|
|
18
|
+
from sage.rings.rational_field import QQ
|
|
19
|
+
from sage.symbolic.ring import SR
|
|
20
|
+
from sage.symbolic.expression import symbol_table, mixed_order
|
|
21
|
+
from sage.symbolic.constants import (pi, e, golden_ratio, log2, euler_gamma,
|
|
22
|
+
catalan, khinchin, twinprime, mertens)
|
|
23
|
+
from sage.functions.hypergeometric import hypergeometric
|
|
24
|
+
from sage.functions.other import (cases, element_of)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
##############################################################
|
|
28
|
+
# Generate random expressions for doctests #
|
|
29
|
+
##############################################################
|
|
30
|
+
|
|
31
|
+
def _mk_full_functions():
|
|
32
|
+
r"""
|
|
33
|
+
A simple function that returns a list of all Pynac functions of known
|
|
34
|
+
arity, sorted by name.
|
|
35
|
+
|
|
36
|
+
EXAMPLES::
|
|
37
|
+
|
|
38
|
+
sage: from sage.symbolic.random_tests import _mk_full_functions
|
|
39
|
+
sage: [f for (one,f,arity) in _mk_full_functions()] # random
|
|
40
|
+
[Ei, abs, arccos, arccosh, arccot, arccoth, arccsc, arccsch,
|
|
41
|
+
arcsec, arcsech, arcsin, arcsinh, arctan, arctan2, arctanh,
|
|
42
|
+
arg, beta, binomial, ceil, conjugate, cos, cosh, cot, coth,
|
|
43
|
+
csc, csch, dickman_rho, dilog, dirac_delta, elliptic_e,
|
|
44
|
+
elliptic_ec, elliptic_eu, elliptic_f, elliptic_kc,
|
|
45
|
+
elliptic_pi, erf, exp, factorial, floor, heaviside, imag_part,
|
|
46
|
+
integrate, kronecker_delta, log, polylog, real_part, sec,
|
|
47
|
+
sech, sgn, sin, sinh, tan, tanh, unit_step, zeta, zetaderiv]
|
|
48
|
+
|
|
49
|
+
Note that this doctest will produce different output whenever a
|
|
50
|
+
symbolic function is added or removed.
|
|
51
|
+
"""
|
|
52
|
+
excluded = [hypergeometric, cases, element_of]
|
|
53
|
+
items = sorted(symbol_table['functions'].items())
|
|
54
|
+
return [(1.0, f, f.number_of_arguments())
|
|
55
|
+
for (name, f) in items
|
|
56
|
+
if hasattr(f, 'number_of_arguments') and
|
|
57
|
+
f.number_of_arguments() > 0 and
|
|
58
|
+
f not in excluded]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# For creating simple expressions
|
|
62
|
+
|
|
63
|
+
fast_binary = [(0.4, operator.add), (0.1, operator.sub), (0.5, operator.mul)]
|
|
64
|
+
fast_unary = [(0.8, operator.neg), (0.2, operator.abs)]
|
|
65
|
+
fast_nodes = [(0.9, fast_binary, 2), (0.1, fast_unary, 1)]
|
|
66
|
+
|
|
67
|
+
# For creating expressions with the full power of Pynac's simple expression
|
|
68
|
+
# subset (with no quantifiers/operators; that is, no derivatives, integrals,
|
|
69
|
+
# etc.)
|
|
70
|
+
full_binary = [(0.3, operator.add), (0.1, operator.sub), (0.3, operator.mul), (0.2, operator.truediv), (0.1, operator.pow)]
|
|
71
|
+
full_unary = [(0.8, operator.neg), (0.2, operator.inv)]
|
|
72
|
+
full_functions = _mk_full_functions()
|
|
73
|
+
full_nullary = [(1.0, c) for c in [pi, e]] + [(0.05, c) for c in
|
|
74
|
+
[golden_ratio, log2, euler_gamma, catalan, khinchin, twinprime,
|
|
75
|
+
mertens]]
|
|
76
|
+
full_internal = [(0.6, full_binary, 2), (0.2, full_unary, 1),
|
|
77
|
+
(0.2, full_functions)]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def normalize_prob_list(pl, extra=()):
|
|
81
|
+
r"""
|
|
82
|
+
INPUT:
|
|
83
|
+
|
|
84
|
+
- ``pl`` -- list of tuples, where the first element of each tuple is
|
|
85
|
+
a floating-point number (representing a relative probability). The
|
|
86
|
+
second element of each tuple may be a list or any other kind of object.
|
|
87
|
+
|
|
88
|
+
- ``extra`` -- tuple which is to be appended to every tuple in ``pl``
|
|
89
|
+
|
|
90
|
+
This function takes such a list of tuples (a "probability list") and
|
|
91
|
+
normalizes the probabilities so that they sum to one. If any of the
|
|
92
|
+
values are lists, then those lists are first normalized; then
|
|
93
|
+
the probabilities in the list are multiplied by the main probability
|
|
94
|
+
and the sublist is merged with the main list.
|
|
95
|
+
|
|
96
|
+
For example, suppose we want to select between group A and group B with
|
|
97
|
+
50% probability each. Then within group A, we select A1 or A2 with 50%
|
|
98
|
+
probability each (so the overall probability of selecting A1 is 25%);
|
|
99
|
+
and within group B, we select B1, B2, or B3 with probabilities in
|
|
100
|
+
a 1:2:2 ratio.
|
|
101
|
+
|
|
102
|
+
EXAMPLES::
|
|
103
|
+
|
|
104
|
+
sage: from sage.symbolic.random_tests import *
|
|
105
|
+
sage: A = [(0.5, 'A1'), (0.5, 'A2')]
|
|
106
|
+
sage: B = [(1, 'B1'), (2, 'B2'), (2, 'B3')]
|
|
107
|
+
sage: top = [(50, A, 'Group A'), (50, B, 'Group B')]
|
|
108
|
+
sage: normalize_prob_list(top)
|
|
109
|
+
[(0.250000000000000, 'A1', 'Group A'), (0.250000000000000, 'A2', 'Group A'), (0.1, 'B1', 'Group B'), (0.2, 'B2', 'Group B'), (0.2, 'B3', 'Group B')]
|
|
110
|
+
"""
|
|
111
|
+
if len(pl) == 0:
|
|
112
|
+
return pl
|
|
113
|
+
result = []
|
|
114
|
+
total = sum(float(p[0]) for p in pl)
|
|
115
|
+
for p in pl:
|
|
116
|
+
prob = p[0]
|
|
117
|
+
val = p[1]
|
|
118
|
+
if len(p) > 2:
|
|
119
|
+
p_extra = p[2:]
|
|
120
|
+
else:
|
|
121
|
+
p_extra = extra
|
|
122
|
+
if isinstance(val, list):
|
|
123
|
+
norm_val = normalize_prob_list(val, extra=p_extra)
|
|
124
|
+
result.extend(((prob / total) * np[0], np[1]) + np[2:]
|
|
125
|
+
for np in norm_val)
|
|
126
|
+
else:
|
|
127
|
+
result.append(((prob / total), val) + p_extra)
|
|
128
|
+
return result
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def choose_from_prob_list(lst):
|
|
132
|
+
r"""
|
|
133
|
+
INPUT:
|
|
134
|
+
|
|
135
|
+
- ``lst`` -- list of tuples, where the first element of each tuple
|
|
136
|
+
is a nonnegative float (a probability), and the probabilities sum
|
|
137
|
+
to one
|
|
138
|
+
|
|
139
|
+
OUTPUT:
|
|
140
|
+
|
|
141
|
+
A tuple randomly selected from the list according to the given
|
|
142
|
+
probabilities.
|
|
143
|
+
|
|
144
|
+
EXAMPLES::
|
|
145
|
+
|
|
146
|
+
sage: from sage.symbolic.random_tests import *
|
|
147
|
+
sage: v = [(0.1, False), (0.9, True)]
|
|
148
|
+
sage: choose_from_prob_list(v) # random
|
|
149
|
+
(0.900000000000000, True)
|
|
150
|
+
sage: true_count = 0
|
|
151
|
+
sage: total_count = 0
|
|
152
|
+
sage: def more_samples():
|
|
153
|
+
....: global true_count, total_count
|
|
154
|
+
....: for _ in range(10000):
|
|
155
|
+
....: total_count += 1.0
|
|
156
|
+
....: if choose_from_prob_list(v)[1]:
|
|
157
|
+
....: true_count += 1.0
|
|
158
|
+
sage: more_samples()
|
|
159
|
+
sage: while abs(true_count/total_count - 0.9) > 0.01:
|
|
160
|
+
....: more_samples()
|
|
161
|
+
"""
|
|
162
|
+
r = random()
|
|
163
|
+
for i in range(len(lst) - 1):
|
|
164
|
+
if r < lst[i][0]:
|
|
165
|
+
return lst[i]
|
|
166
|
+
r -= lst[i][0]
|
|
167
|
+
return lst[-1]
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def random_integer_vector(n, length):
|
|
171
|
+
r"""
|
|
172
|
+
Give a random list of length *length*, consisting of nonnegative
|
|
173
|
+
integers that sum to *n*.
|
|
174
|
+
|
|
175
|
+
This is an approximation to IntegerVectors(n, length).random_element().
|
|
176
|
+
That gives values uniformly at random, but might be slow; this
|
|
177
|
+
routine is not uniform, but should always be fast.
|
|
178
|
+
|
|
179
|
+
(This routine is uniform if ``length`` is 1 or 2; for longer vectors,
|
|
180
|
+
we prefer approximately balanced vectors, where all the values
|
|
181
|
+
are around `n/{length}`.)
|
|
182
|
+
|
|
183
|
+
EXAMPLES::
|
|
184
|
+
|
|
185
|
+
sage: from sage.symbolic.random_tests import *
|
|
186
|
+
sage: a = random_integer_vector(100, 2); a # random
|
|
187
|
+
[11, 89]
|
|
188
|
+
sage: len(a)
|
|
189
|
+
2
|
|
190
|
+
sage: sum(a)
|
|
191
|
+
100
|
|
192
|
+
|
|
193
|
+
sage: b = random_integer_vector(10000, 20)
|
|
194
|
+
sage: len(b)
|
|
195
|
+
20
|
|
196
|
+
sage: sum(b)
|
|
197
|
+
10000
|
|
198
|
+
|
|
199
|
+
The routine is uniform if ``length`` is 2::
|
|
200
|
+
|
|
201
|
+
sage: true_count = 0
|
|
202
|
+
sage: total_count = 0
|
|
203
|
+
sage: def more_samples():
|
|
204
|
+
....: global true_count, total_count
|
|
205
|
+
....: for _ in range(1000):
|
|
206
|
+
....: total_count += 1.0
|
|
207
|
+
....: if a == random_integer_vector(100, 2):
|
|
208
|
+
....: true_count += 1.0
|
|
209
|
+
sage: more_samples()
|
|
210
|
+
sage: while abs(true_count/total_count - 0.01) > 0.01:
|
|
211
|
+
....: more_samples()
|
|
212
|
+
"""
|
|
213
|
+
if length == 0:
|
|
214
|
+
return []
|
|
215
|
+
elif length == 1:
|
|
216
|
+
return [n]
|
|
217
|
+
elif length == 2:
|
|
218
|
+
v = randint(0, n)
|
|
219
|
+
return [v, n - v]
|
|
220
|
+
else:
|
|
221
|
+
v = randint(0, 2 * n // length)
|
|
222
|
+
return [v] + random_integer_vector(n - v, length - 1)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def random_expr_helper(n_nodes, internal, leaves, verbose):
|
|
226
|
+
r"""
|
|
227
|
+
Produce a random symbolic expression of size *n_nodes* (or slightly
|
|
228
|
+
larger). Internal nodes are selected from the *internal* probability
|
|
229
|
+
list; leaves are selected from *leaves*. If *verbose* is True,
|
|
230
|
+
then a message is printed before creating an internal node.
|
|
231
|
+
|
|
232
|
+
EXAMPLES::
|
|
233
|
+
|
|
234
|
+
sage: from sage.symbolic.random_tests import *
|
|
235
|
+
sage: a = random_expr_helper(9, [(0.5, operator.add, 2),
|
|
236
|
+
....: (0.5, operator.neg, 1)], [(0.5, 1), (0.5, x)], True)
|
|
237
|
+
About to apply <built-in function ...
|
|
238
|
+
|
|
239
|
+
In small cases we will see all cases quickly::
|
|
240
|
+
|
|
241
|
+
sage: def next_expr():
|
|
242
|
+
....: return random_expr_helper(
|
|
243
|
+
....: 6, [(0.5, operator.add, 2), (0.5, operator.neg, 1)],
|
|
244
|
+
....: [(0.5, 1), (0.5, x)], False)
|
|
245
|
+
sage: all_exprs = set()
|
|
246
|
+
sage: for a in range(-4, 5):
|
|
247
|
+
....: for b in range(-4+abs(a), 5-abs(a)):
|
|
248
|
+
....: if a % 2 and abs(a) + abs(b) == 4 and sign(a) != sign(b):
|
|
249
|
+
....: continue
|
|
250
|
+
....: all_exprs.add(a*x + b)
|
|
251
|
+
sage: our_exprs = set()
|
|
252
|
+
sage: while our_exprs != all_exprs:
|
|
253
|
+
....: our_exprs.add(next_expr())
|
|
254
|
+
"""
|
|
255
|
+
if n_nodes == 1:
|
|
256
|
+
return choose_from_prob_list(leaves)[1]
|
|
257
|
+
else:
|
|
258
|
+
r = choose_from_prob_list(internal)
|
|
259
|
+
n_nodes -= 1
|
|
260
|
+
n_children = r[2]
|
|
261
|
+
n_spare_nodes = n_nodes - n_children
|
|
262
|
+
n_spare_nodes = max(0, n_spare_nodes)
|
|
263
|
+
nodes_per_child = random_integer_vector(n_spare_nodes, n_children)
|
|
264
|
+
children = [random_expr_helper(n + 1, internal, leaves, verbose)
|
|
265
|
+
for n in nodes_per_child]
|
|
266
|
+
if verbose:
|
|
267
|
+
print("About to apply %r to %r" % (r[1], children))
|
|
268
|
+
return r[1](*children)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def random_expr(size, nvars=1, ncoeffs=None, var_frac=0.5,
|
|
272
|
+
internal=full_internal,
|
|
273
|
+
nullary=full_nullary, nullary_frac=0.2,
|
|
274
|
+
coeff_generator=QQ.random_element, verbose=False):
|
|
275
|
+
r"""
|
|
276
|
+
Produce a random symbolic expression of the given size. By
|
|
277
|
+
default, the expression involves (at most) one variable, an arbitrary
|
|
278
|
+
number of coefficients, and all of the symbolic functions and constants
|
|
279
|
+
(from the probability lists full_internal and full_nullary). It is
|
|
280
|
+
possible to adjust the ratio of leaves between symbolic constants,
|
|
281
|
+
variables, and coefficients (var_frac gives the fraction of variables,
|
|
282
|
+
and nullary_frac the fraction of symbolic constants; the remaining
|
|
283
|
+
leaves are coefficients).
|
|
284
|
+
|
|
285
|
+
The actual mix of symbolic constants and internal nodes can be modified
|
|
286
|
+
by specifying different probability lists.
|
|
287
|
+
|
|
288
|
+
To use a different type for coefficients, you can specify
|
|
289
|
+
coeff_generator, which should be a function that will return
|
|
290
|
+
a random coefficient every time it is called.
|
|
291
|
+
|
|
292
|
+
This function will often raise an error because it tries to create
|
|
293
|
+
an erroneous expression (such as a division by zero).
|
|
294
|
+
|
|
295
|
+
EXAMPLES::
|
|
296
|
+
|
|
297
|
+
sage: from sage.symbolic.random_tests import *
|
|
298
|
+
sage: some_functions = [arcsinh, arctan, arctan2, arctanh,
|
|
299
|
+
....: arg, beta, binomial, ceil, conjugate, cos, cosh, cot, coth,
|
|
300
|
+
....: elliptic_pi, erf, exp, factorial, floor, heaviside, imag_part,
|
|
301
|
+
....: sech, sgn, sin, sinh, tan, tanh, unit_step, zeta, zetaderiv]
|
|
302
|
+
sage: my_internal = [(0.6, full_binary, 2), (0.2, full_unary, 1),
|
|
303
|
+
....: (0.2, [(1.0,f,f.number_of_arguments()) for f in some_functions])]
|
|
304
|
+
sage: set_random_seed(1)
|
|
305
|
+
sage: random_expr(50, nvars=3, internal=my_internal, # not tested # known bug
|
|
306
|
+
....: coeff_generator=CDF.random_element)
|
|
307
|
+
(v1^(0.9713408427702117 + 0.195868299334218*I)/cot(-pi + v1^2 + v3) + tan(arctan(v2 + arctan2(-0.35859061674557324 + 0.9407509502498164*I, v3) - 0.8419115504372718 + 0.30375717982404615*I) + arctan2((0.2275357305882964 - 0.8258002386106038*I)/factorial(v2), -v3 - 0.7604559947718565 - 0.5543672548552057*I) + ceil(1/arctan2(v1, v1))))/v2
|
|
308
|
+
sage: random_expr(5, verbose=True) # not tested # known bug
|
|
309
|
+
About to apply <built-in function inv> to [31]
|
|
310
|
+
About to apply sgn to [v1]
|
|
311
|
+
About to apply <built-in function add> to [1/31, sgn(v1)]
|
|
312
|
+
sgn(v1) + 1/31
|
|
313
|
+
"""
|
|
314
|
+
vars = [(1.0, SR.var('v%d' % (n + 1))) for n in range(nvars)]
|
|
315
|
+
if ncoeffs is None:
|
|
316
|
+
ncoeffs = size
|
|
317
|
+
coeffs = [(1.0, coeff_generator()) for _ in range(ncoeffs)]
|
|
318
|
+
leaves = [(var_frac, vars), (1.0 - var_frac - nullary_frac, coeffs), (nullary_frac, nullary)]
|
|
319
|
+
leaves = normalize_prob_list(leaves)
|
|
320
|
+
|
|
321
|
+
internal = normalize_prob_list(internal)
|
|
322
|
+
|
|
323
|
+
return random_expr_helper(size, internal, leaves, verbose)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
#####################################
|
|
327
|
+
# Test the ordering of operands #
|
|
328
|
+
#####################################
|
|
329
|
+
|
|
330
|
+
def assert_strict_weak_order(a, b, c, cmp_func):
|
|
331
|
+
r"""
|
|
332
|
+
Check that ``cmp_func`` is a strict weak order on the elements a,b,c.
|
|
333
|
+
|
|
334
|
+
A strict weak order is a binary relation ``<`` such that
|
|
335
|
+
|
|
336
|
+
* For all `x`, it is not the case that `x < x` (irreflexivity).
|
|
337
|
+
|
|
338
|
+
* For all `x\not=y`, if `x < y` then it is not the case that `y <
|
|
339
|
+
x` (asymmetry).
|
|
340
|
+
|
|
341
|
+
* For all `x`, `y`, and `z`, if `x < y` and `y < z` then `x < z`
|
|
342
|
+
(transitivity).
|
|
343
|
+
|
|
344
|
+
* For all `x`, `y`, and `z`, if x is incomparable with `y`, and
|
|
345
|
+
`y` is incomparable with `z`, then `x` is incomparable with `z`
|
|
346
|
+
(transitivity of incomparability).
|
|
347
|
+
|
|
348
|
+
INPUT:
|
|
349
|
+
|
|
350
|
+
- ``a``, ``b``, ``c`` -- anything that can be compared by ``cmp_func``
|
|
351
|
+
|
|
352
|
+
- ``cmp_func`` -- function of two arguments that returns their
|
|
353
|
+
comparison (i.e. either ``True`` or ``False``)
|
|
354
|
+
|
|
355
|
+
OUTPUT:
|
|
356
|
+
|
|
357
|
+
Nothing. Raises a :exc:`ValueError` if ``cmp_func``
|
|
358
|
+
is not a strict weak order on the three given elements.
|
|
359
|
+
|
|
360
|
+
REFERENCES:
|
|
361
|
+
|
|
362
|
+
:wikipedia:`Strict_weak_ordering`
|
|
363
|
+
|
|
364
|
+
EXAMPLES:
|
|
365
|
+
|
|
366
|
+
The usual ordering of integers is a strict weak order::
|
|
367
|
+
|
|
368
|
+
sage: from sage.symbolic.random_tests import assert_strict_weak_order
|
|
369
|
+
sage: a, b, c = [randint(-10, 10) for i in range(3)]
|
|
370
|
+
sage: assert_strict_weak_order(a, b, c, lambda x, y: x < y)
|
|
371
|
+
|
|
372
|
+
sage: x = [-SR(oo), SR(0), SR(oo)]
|
|
373
|
+
sage: cmp_M = matrix(3, 3, 0)
|
|
374
|
+
sage: for i in range(3):
|
|
375
|
+
....: for j in range(3):
|
|
376
|
+
....: if x[i] < x[j]:
|
|
377
|
+
....: cmp_M[i, j] = -1
|
|
378
|
+
....: elif x[i] > x[j]:
|
|
379
|
+
....: cmp_M[i, j] = 1
|
|
380
|
+
sage: cmp_M
|
|
381
|
+
[ 0 -1 -1]
|
|
382
|
+
[ 1 0 -1]
|
|
383
|
+
[ 1 1 0]
|
|
384
|
+
"""
|
|
385
|
+
from sage.matrix.constructor import matrix
|
|
386
|
+
from sage.combinat.permutation import Permutations
|
|
387
|
+
x = (a, b, c)
|
|
388
|
+
|
|
389
|
+
cmp_M = matrix(3, 3)
|
|
390
|
+
for i in range(3):
|
|
391
|
+
for j in range(3):
|
|
392
|
+
cmp_M[i, j] = (cmp_func(x[i], x[j]) == 1) # or -1, doesn't matter
|
|
393
|
+
|
|
394
|
+
msg = 'the binary relation failed to be a strict weak order on the elements \n'
|
|
395
|
+
msg += ' a = {}\n b = {}\n c = {}\n'.format(a, b, c)
|
|
396
|
+
msg += str(cmp_M)
|
|
397
|
+
|
|
398
|
+
for i in range(3):
|
|
399
|
+
# irreflexivity
|
|
400
|
+
if cmp_M[i, i]:
|
|
401
|
+
raise ValueError(msg)
|
|
402
|
+
|
|
403
|
+
# asymmetric
|
|
404
|
+
for j in range(i):
|
|
405
|
+
if cmp_M[i, j] and cmp_M[j, i]:
|
|
406
|
+
raise ValueError(msg)
|
|
407
|
+
|
|
408
|
+
def incomparable(i, j):
|
|
409
|
+
return not (cmp_M[i, j] or cmp_M[j, i])
|
|
410
|
+
|
|
411
|
+
for i, j, k in Permutations([0, 1, 2]):
|
|
412
|
+
# transitivity
|
|
413
|
+
if cmp_M[i, j] and cmp_M[j, k] and not cmp_M[i, k]:
|
|
414
|
+
raise ValueError(msg)
|
|
415
|
+
|
|
416
|
+
# transitivity of incomparability
|
|
417
|
+
if (incomparable(i, j) and incomparable(j, k) and
|
|
418
|
+
not incomparable(i, k)):
|
|
419
|
+
raise ValueError(msg)
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def test_symbolic_expression_order(repetitions=100):
|
|
423
|
+
r"""
|
|
424
|
+
Test whether the comparison of random symbolic expressions
|
|
425
|
+
satisfies the strict weak order axioms.
|
|
426
|
+
|
|
427
|
+
This is important because the C++ extension class uses
|
|
428
|
+
``std::sort()`` which requires a strict weak order. See also
|
|
429
|
+
:issue:`9880`.
|
|
430
|
+
|
|
431
|
+
EXAMPLES::
|
|
432
|
+
|
|
433
|
+
sage: from sage.symbolic.random_tests import test_symbolic_expression_order
|
|
434
|
+
sage: test_symbolic_expression_order(200)
|
|
435
|
+
sage: test_symbolic_expression_order(10000) # long time
|
|
436
|
+
"""
|
|
437
|
+
rnd_length = 50
|
|
438
|
+
nvars = 10
|
|
439
|
+
ncoeffs = 10
|
|
440
|
+
var_frac = 0.5
|
|
441
|
+
nullary_frac = 0.05
|
|
442
|
+
|
|
443
|
+
def coeff_generator():
|
|
444
|
+
return randint(-100, 100) / randint(1, 100)
|
|
445
|
+
|
|
446
|
+
def make_random_expr():
|
|
447
|
+
while True:
|
|
448
|
+
try:
|
|
449
|
+
return random_expr(
|
|
450
|
+
rnd_length, nvars=nvars, ncoeffs=ncoeffs, var_frac=var_frac,
|
|
451
|
+
nullary_frac=nullary_frac, coeff_generator=coeff_generator,
|
|
452
|
+
internal=fast_nodes)
|
|
453
|
+
except (ZeroDivisionError, ValueError):
|
|
454
|
+
pass
|
|
455
|
+
|
|
456
|
+
for rep in range(repetitions):
|
|
457
|
+
a = make_random_expr()
|
|
458
|
+
b = make_random_expr()
|
|
459
|
+
c = make_random_expr()
|
|
460
|
+
assert_strict_weak_order(a, b, c, mixed_order)
|
|
461
|
+
assert_strict_weak_order(a, b, c, lambda x, y: x._cmp_add(y))
|
|
462
|
+
assert_strict_weak_order(a, b, c, lambda x, y: x._cmp_mul(y))
|