passagemath-categories 10.6.32__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.
Files changed (719) hide show
  1. passagemath_categories-10.6.32.dist-info/METADATA +156 -0
  2. passagemath_categories-10.6.32.dist-info/RECORD +719 -0
  3. passagemath_categories-10.6.32.dist-info/WHEEL +5 -0
  4. passagemath_categories-10.6.32.dist-info/top_level.txt +2 -0
  5. passagemath_categories.libs/libgcc_s-2d945d6c.so.1 +0 -0
  6. passagemath_categories.libs/libgmp-28992bcb.so.10.5.0 +0 -0
  7. passagemath_categories.libs/libstdc++-85f2cd6d.so.6.0.33 +0 -0
  8. sage/all__sagemath_categories.py +28 -0
  9. sage/arith/all.py +38 -0
  10. sage/arith/constants.pxd +27 -0
  11. sage/arith/functions.cpython-314t-aarch64-linux-musl.so +0 -0
  12. sage/arith/functions.pxd +4 -0
  13. sage/arith/functions.pyx +221 -0
  14. sage/arith/misc.py +6552 -0
  15. sage/arith/multi_modular.cpython-314t-aarch64-linux-musl.so +0 -0
  16. sage/arith/multi_modular.pxd +39 -0
  17. sage/arith/multi_modular.pyx +994 -0
  18. sage/arith/rational_reconstruction.cpython-314t-aarch64-linux-musl.so +0 -0
  19. sage/arith/rational_reconstruction.pxd +4 -0
  20. sage/arith/rational_reconstruction.pyx +115 -0
  21. sage/arith/srange.cpython-314t-aarch64-linux-musl.so +0 -0
  22. sage/arith/srange.pyx +571 -0
  23. sage/calculus/all__sagemath_categories.py +2 -0
  24. sage/calculus/functional.py +481 -0
  25. sage/calculus/functions.py +151 -0
  26. sage/categories/additive_groups.py +73 -0
  27. sage/categories/additive_magmas.py +1044 -0
  28. sage/categories/additive_monoids.py +114 -0
  29. sage/categories/additive_semigroups.py +184 -0
  30. sage/categories/affine_weyl_groups.py +238 -0
  31. sage/categories/algebra_ideals.py +95 -0
  32. sage/categories/algebra_modules.py +96 -0
  33. sage/categories/algebras.py +349 -0
  34. sage/categories/algebras_with_basis.py +377 -0
  35. sage/categories/all.py +160 -0
  36. sage/categories/aperiodic_semigroups.py +29 -0
  37. sage/categories/associative_algebras.py +47 -0
  38. sage/categories/bialgebras.py +101 -0
  39. sage/categories/bialgebras_with_basis.py +414 -0
  40. sage/categories/bimodules.py +206 -0
  41. sage/categories/chain_complexes.py +268 -0
  42. sage/categories/classical_crystals.py +480 -0
  43. sage/categories/coalgebras.py +405 -0
  44. sage/categories/coalgebras_with_basis.py +232 -0
  45. sage/categories/coercion_methods.cpython-314t-aarch64-linux-musl.so +0 -0
  46. sage/categories/coercion_methods.pyx +52 -0
  47. sage/categories/commutative_additive_groups.py +104 -0
  48. sage/categories/commutative_additive_monoids.py +45 -0
  49. sage/categories/commutative_additive_semigroups.py +48 -0
  50. sage/categories/commutative_algebra_ideals.py +87 -0
  51. sage/categories/commutative_algebras.py +94 -0
  52. sage/categories/commutative_ring_ideals.py +58 -0
  53. sage/categories/commutative_rings.py +736 -0
  54. sage/categories/complete_discrete_valuation.py +293 -0
  55. sage/categories/complex_reflection_groups.py +145 -0
  56. sage/categories/complex_reflection_or_generalized_coxeter_groups.py +1249 -0
  57. sage/categories/coxeter_group_algebras.py +186 -0
  58. sage/categories/coxeter_groups.py +3402 -0
  59. sage/categories/crystals.py +2628 -0
  60. sage/categories/cw_complexes.py +216 -0
  61. sage/categories/dedekind_domains.py +137 -0
  62. sage/categories/discrete_valuation.py +325 -0
  63. sage/categories/distributive_magmas_and_additive_magmas.py +100 -0
  64. sage/categories/division_rings.py +114 -0
  65. sage/categories/domains.py +95 -0
  66. sage/categories/drinfeld_modules.py +789 -0
  67. sage/categories/dual.py +42 -0
  68. sage/categories/enumerated_sets.py +1146 -0
  69. sage/categories/euclidean_domains.py +271 -0
  70. sage/categories/examples/algebras_with_basis.py +102 -0
  71. sage/categories/examples/all.py +1 -0
  72. sage/categories/examples/commutative_additive_monoids.py +130 -0
  73. sage/categories/examples/commutative_additive_semigroups.py +199 -0
  74. sage/categories/examples/coxeter_groups.py +8 -0
  75. sage/categories/examples/crystals.py +236 -0
  76. sage/categories/examples/cw_complexes.py +163 -0
  77. sage/categories/examples/facade_sets.py +187 -0
  78. sage/categories/examples/filtered_algebras_with_basis.py +204 -0
  79. sage/categories/examples/filtered_modules_with_basis.py +154 -0
  80. sage/categories/examples/finite_coxeter_groups.py +252 -0
  81. sage/categories/examples/finite_dimensional_algebras_with_basis.py +148 -0
  82. sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +495 -0
  83. sage/categories/examples/finite_enumerated_sets.py +208 -0
  84. sage/categories/examples/finite_monoids.py +150 -0
  85. sage/categories/examples/finite_semigroups.py +190 -0
  86. sage/categories/examples/finite_weyl_groups.py +191 -0
  87. sage/categories/examples/graded_connected_hopf_algebras_with_basis.py +152 -0
  88. sage/categories/examples/graded_modules_with_basis.py +168 -0
  89. sage/categories/examples/graphs.py +122 -0
  90. sage/categories/examples/hopf_algebras_with_basis.py +145 -0
  91. sage/categories/examples/infinite_enumerated_sets.py +190 -0
  92. sage/categories/examples/lie_algebras.py +352 -0
  93. sage/categories/examples/lie_algebras_with_basis.py +196 -0
  94. sage/categories/examples/magmas.py +162 -0
  95. sage/categories/examples/manifolds.py +94 -0
  96. sage/categories/examples/monoids.py +144 -0
  97. sage/categories/examples/posets.py +178 -0
  98. sage/categories/examples/semigroups.py +580 -0
  99. sage/categories/examples/semigroups_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  100. sage/categories/examples/semigroups_cython.pyx +221 -0
  101. sage/categories/examples/semirings.py +249 -0
  102. sage/categories/examples/sets_cat.py +706 -0
  103. sage/categories/examples/sets_with_grading.py +101 -0
  104. sage/categories/examples/with_realizations.py +542 -0
  105. sage/categories/fields.py +991 -0
  106. sage/categories/filtered_algebras.py +63 -0
  107. sage/categories/filtered_algebras_with_basis.py +548 -0
  108. sage/categories/filtered_hopf_algebras_with_basis.py +138 -0
  109. sage/categories/filtered_modules.py +210 -0
  110. sage/categories/filtered_modules_with_basis.py +1209 -0
  111. sage/categories/finite_complex_reflection_groups.py +1506 -0
  112. sage/categories/finite_coxeter_groups.py +1138 -0
  113. sage/categories/finite_crystals.py +103 -0
  114. sage/categories/finite_dimensional_algebras_with_basis.py +1860 -0
  115. sage/categories/finite_dimensional_bialgebras_with_basis.py +33 -0
  116. sage/categories/finite_dimensional_coalgebras_with_basis.py +33 -0
  117. sage/categories/finite_dimensional_graded_lie_algebras_with_basis.py +231 -0
  118. sage/categories/finite_dimensional_hopf_algebras_with_basis.py +38 -0
  119. sage/categories/finite_dimensional_lie_algebras_with_basis.py +2774 -0
  120. sage/categories/finite_dimensional_modules_with_basis.py +1407 -0
  121. sage/categories/finite_dimensional_nilpotent_lie_algebras_with_basis.py +167 -0
  122. sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +270 -0
  123. sage/categories/finite_enumerated_sets.py +769 -0
  124. sage/categories/finite_fields.py +252 -0
  125. sage/categories/finite_groups.py +256 -0
  126. sage/categories/finite_lattice_posets.py +242 -0
  127. sage/categories/finite_monoids.py +316 -0
  128. sage/categories/finite_permutation_groups.py +339 -0
  129. sage/categories/finite_posets.py +1994 -0
  130. sage/categories/finite_semigroups.py +136 -0
  131. sage/categories/finite_sets.py +93 -0
  132. sage/categories/finite_weyl_groups.py +39 -0
  133. sage/categories/finitely_generated_lambda_bracket_algebras.py +112 -0
  134. sage/categories/finitely_generated_lie_conformal_algebras.py +114 -0
  135. sage/categories/finitely_generated_magmas.py +57 -0
  136. sage/categories/finitely_generated_semigroups.py +214 -0
  137. sage/categories/function_fields.py +76 -0
  138. sage/categories/g_sets.py +77 -0
  139. sage/categories/gcd_domains.py +65 -0
  140. sage/categories/generalized_coxeter_groups.py +94 -0
  141. sage/categories/graded_algebras.py +85 -0
  142. sage/categories/graded_algebras_with_basis.py +258 -0
  143. sage/categories/graded_bialgebras.py +32 -0
  144. sage/categories/graded_bialgebras_with_basis.py +32 -0
  145. sage/categories/graded_coalgebras.py +65 -0
  146. sage/categories/graded_coalgebras_with_basis.py +51 -0
  147. sage/categories/graded_hopf_algebras.py +41 -0
  148. sage/categories/graded_hopf_algebras_with_basis.py +169 -0
  149. sage/categories/graded_lie_algebras.py +91 -0
  150. sage/categories/graded_lie_algebras_with_basis.py +44 -0
  151. sage/categories/graded_lie_conformal_algebras.py +74 -0
  152. sage/categories/graded_modules.py +133 -0
  153. sage/categories/graded_modules_with_basis.py +329 -0
  154. sage/categories/graphs.py +138 -0
  155. sage/categories/group_algebras.py +430 -0
  156. sage/categories/groupoid.py +94 -0
  157. sage/categories/groups.py +667 -0
  158. sage/categories/h_trivial_semigroups.py +64 -0
  159. sage/categories/hecke_modules.py +185 -0
  160. sage/categories/highest_weight_crystals.py +980 -0
  161. sage/categories/hopf_algebras.py +219 -0
  162. sage/categories/hopf_algebras_with_basis.py +309 -0
  163. sage/categories/infinite_enumerated_sets.py +115 -0
  164. sage/categories/integral_domains.py +203 -0
  165. sage/categories/j_trivial_semigroups.py +29 -0
  166. sage/categories/kac_moody_algebras.py +82 -0
  167. sage/categories/kahler_algebras.py +203 -0
  168. sage/categories/l_trivial_semigroups.py +63 -0
  169. sage/categories/lambda_bracket_algebras.py +280 -0
  170. sage/categories/lambda_bracket_algebras_with_basis.py +107 -0
  171. sage/categories/lattice_posets.py +89 -0
  172. sage/categories/left_modules.py +49 -0
  173. sage/categories/lie_algebras.py +1070 -0
  174. sage/categories/lie_algebras_with_basis.py +261 -0
  175. sage/categories/lie_conformal_algebras.py +350 -0
  176. sage/categories/lie_conformal_algebras_with_basis.py +147 -0
  177. sage/categories/lie_groups.py +73 -0
  178. sage/categories/loop_crystals.py +1290 -0
  179. sage/categories/magmas.py +1189 -0
  180. sage/categories/magmas_and_additive_magmas.py +149 -0
  181. sage/categories/magmatic_algebras.py +365 -0
  182. sage/categories/manifolds.py +352 -0
  183. sage/categories/matrix_algebras.py +40 -0
  184. sage/categories/metric_spaces.py +387 -0
  185. sage/categories/modular_abelian_varieties.py +78 -0
  186. sage/categories/modules.py +989 -0
  187. sage/categories/modules_with_basis.py +2794 -0
  188. sage/categories/monoid_algebras.py +38 -0
  189. sage/categories/monoids.py +739 -0
  190. sage/categories/noetherian_rings.py +87 -0
  191. sage/categories/number_fields.py +242 -0
  192. sage/categories/ore_modules.py +189 -0
  193. sage/categories/partially_ordered_monoids.py +49 -0
  194. sage/categories/permutation_groups.py +63 -0
  195. sage/categories/pointed_sets.py +42 -0
  196. sage/categories/polyhedra.py +74 -0
  197. sage/categories/poor_man_map.py +270 -0
  198. sage/categories/posets.py +722 -0
  199. sage/categories/principal_ideal_domains.py +270 -0
  200. sage/categories/quantum_group_representations.py +543 -0
  201. sage/categories/quotient_fields.py +728 -0
  202. sage/categories/r_trivial_semigroups.py +45 -0
  203. sage/categories/regular_crystals.py +898 -0
  204. sage/categories/regular_supercrystals.py +170 -0
  205. sage/categories/right_modules.py +49 -0
  206. sage/categories/ring_ideals.py +74 -0
  207. sage/categories/rings.py +1904 -0
  208. sage/categories/rngs.py +175 -0
  209. sage/categories/schemes.py +393 -0
  210. sage/categories/semigroups.py +1060 -0
  211. sage/categories/semirings.py +71 -0
  212. sage/categories/semisimple_algebras.py +114 -0
  213. sage/categories/sets_with_grading.py +235 -0
  214. sage/categories/shephard_groups.py +43 -0
  215. sage/categories/signed_tensor.py +120 -0
  216. sage/categories/simplicial_complexes.py +134 -0
  217. sage/categories/simplicial_sets.py +1206 -0
  218. sage/categories/super_algebras.py +149 -0
  219. sage/categories/super_algebras_with_basis.py +144 -0
  220. sage/categories/super_hopf_algebras_with_basis.py +126 -0
  221. sage/categories/super_lie_conformal_algebras.py +193 -0
  222. sage/categories/super_modules.py +229 -0
  223. sage/categories/super_modules_with_basis.py +193 -0
  224. sage/categories/supercommutative_algebras.py +99 -0
  225. sage/categories/supercrystals.py +406 -0
  226. sage/categories/tensor.py +110 -0
  227. sage/categories/topological_spaces.py +170 -0
  228. sage/categories/triangular_kac_moody_algebras.py +439 -0
  229. sage/categories/tutorial.py +58 -0
  230. sage/categories/unique_factorization_domains.py +318 -0
  231. sage/categories/unital_algebras.py +426 -0
  232. sage/categories/vector_bundles.py +159 -0
  233. sage/categories/vector_spaces.py +357 -0
  234. sage/categories/weyl_groups.py +853 -0
  235. sage/combinat/all__sagemath_categories.py +34 -0
  236. sage/combinat/backtrack.py +180 -0
  237. sage/combinat/combinat.py +2269 -0
  238. sage/combinat/combinat_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  239. sage/combinat/combinat_cython.pxd +6 -0
  240. sage/combinat/combinat_cython.pyx +390 -0
  241. sage/combinat/combination.py +796 -0
  242. sage/combinat/combinatorial_map.py +416 -0
  243. sage/combinat/composition.py +2192 -0
  244. sage/combinat/dlx.py +510 -0
  245. sage/combinat/integer_lists/__init__.py +7 -0
  246. sage/combinat/integer_lists/base.cpython-314t-aarch64-linux-musl.so +0 -0
  247. sage/combinat/integer_lists/base.pxd +16 -0
  248. sage/combinat/integer_lists/base.pyx +713 -0
  249. sage/combinat/integer_lists/invlex.cpython-314t-aarch64-linux-musl.so +0 -0
  250. sage/combinat/integer_lists/invlex.pxd +4 -0
  251. sage/combinat/integer_lists/invlex.pyx +1650 -0
  252. sage/combinat/integer_lists/lists.py +328 -0
  253. sage/combinat/integer_lists/nn.py +48 -0
  254. sage/combinat/integer_vector.py +1818 -0
  255. sage/combinat/integer_vector_weighted.py +413 -0
  256. sage/combinat/matrices/all__sagemath_categories.py +5 -0
  257. sage/combinat/matrices/dancing_links.cpython-314t-aarch64-linux-musl.so +0 -0
  258. sage/combinat/matrices/dancing_links.pyx +1159 -0
  259. sage/combinat/matrices/dancing_links_c.h +380 -0
  260. sage/combinat/matrices/dlxcpp.py +136 -0
  261. sage/combinat/partition.py +10070 -0
  262. sage/combinat/partitions.cpython-314t-aarch64-linux-musl.so +0 -0
  263. sage/combinat/partitions.pyx +743 -0
  264. sage/combinat/permutation.py +10168 -0
  265. sage/combinat/permutation_cython.cpython-314t-aarch64-linux-musl.so +0 -0
  266. sage/combinat/permutation_cython.pxd +11 -0
  267. sage/combinat/permutation_cython.pyx +407 -0
  268. sage/combinat/q_analogues.py +1090 -0
  269. sage/combinat/ranker.py +268 -0
  270. sage/combinat/subset.py +1561 -0
  271. sage/combinat/subsets_hereditary.py +202 -0
  272. sage/combinat/subsets_pairwise.py +184 -0
  273. sage/combinat/tools.py +63 -0
  274. sage/combinat/tuple.py +348 -0
  275. sage/data_structures/all.py +2 -0
  276. sage/data_structures/all__sagemath_categories.py +2 -0
  277. sage/data_structures/binary_matrix.pxd +138 -0
  278. sage/data_structures/binary_search.cpython-314t-aarch64-linux-musl.so +0 -0
  279. sage/data_structures/binary_search.pxd +3 -0
  280. sage/data_structures/binary_search.pyx +66 -0
  281. sage/data_structures/bitset.cpython-314t-aarch64-linux-musl.so +0 -0
  282. sage/data_structures/bitset.pxd +40 -0
  283. sage/data_structures/bitset.pyx +2385 -0
  284. sage/data_structures/bitset_base.cpython-314t-aarch64-linux-musl.so +0 -0
  285. sage/data_structures/bitset_base.pxd +926 -0
  286. sage/data_structures/bitset_base.pyx +117 -0
  287. sage/data_structures/bitset_intrinsics.h +487 -0
  288. sage/data_structures/blas_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  289. sage/data_structures/blas_dict.pxd +12 -0
  290. sage/data_structures/blas_dict.pyx +469 -0
  291. sage/data_structures/list_of_pairs.cpython-314t-aarch64-linux-musl.so +0 -0
  292. sage/data_structures/list_of_pairs.pxd +16 -0
  293. sage/data_structures/list_of_pairs.pyx +122 -0
  294. sage/data_structures/mutable_poset.py +3312 -0
  295. sage/data_structures/pairing_heap.cpython-314t-aarch64-linux-musl.so +0 -0
  296. sage/data_structures/pairing_heap.h +346 -0
  297. sage/data_structures/pairing_heap.pxd +88 -0
  298. sage/data_structures/pairing_heap.pyx +1464 -0
  299. sage/data_structures/sparse_bitset.pxd +62 -0
  300. sage/data_structures/stream.py +5070 -0
  301. sage/databases/all__sagemath_categories.py +7 -0
  302. sage/databases/sql_db.py +2236 -0
  303. sage/ext/all__sagemath_categories.py +3 -0
  304. sage/ext/fast_callable.cpython-314t-aarch64-linux-musl.so +0 -0
  305. sage/ext/fast_callable.pxd +4 -0
  306. sage/ext/fast_callable.pyx +2746 -0
  307. sage/ext/fast_eval.cpython-314t-aarch64-linux-musl.so +0 -0
  308. sage/ext/fast_eval.pxd +1 -0
  309. sage/ext/fast_eval.pyx +102 -0
  310. sage/ext/interpreters/__init__.py +1 -0
  311. sage/ext/interpreters/all__sagemath_categories.py +2 -0
  312. sage/ext/interpreters/wrapper_el.cpython-314t-aarch64-linux-musl.so +0 -0
  313. sage/ext/interpreters/wrapper_el.pxd +18 -0
  314. sage/ext/interpreters/wrapper_el.pyx +148 -0
  315. sage/ext/interpreters/wrapper_py.cpython-314t-aarch64-linux-musl.so +0 -0
  316. sage/ext/interpreters/wrapper_py.pxd +17 -0
  317. sage/ext/interpreters/wrapper_py.pyx +133 -0
  318. sage/functions/airy.py +937 -0
  319. sage/functions/all.py +97 -0
  320. sage/functions/bessel.py +2102 -0
  321. sage/functions/error.py +784 -0
  322. sage/functions/exp_integral.py +1529 -0
  323. sage/functions/gamma.py +1087 -0
  324. sage/functions/generalized.py +672 -0
  325. sage/functions/hyperbolic.py +747 -0
  326. sage/functions/hypergeometric.py +1156 -0
  327. sage/functions/jacobi.py +1705 -0
  328. sage/functions/log.py +1402 -0
  329. sage/functions/min_max.py +338 -0
  330. sage/functions/orthogonal_polys.py +3106 -0
  331. sage/functions/other.py +2303 -0
  332. sage/functions/piecewise.py +1505 -0
  333. sage/functions/prime_pi.cpython-314t-aarch64-linux-musl.so +0 -0
  334. sage/functions/prime_pi.pyx +262 -0
  335. sage/functions/special.py +1212 -0
  336. sage/functions/spike_function.py +278 -0
  337. sage/functions/transcendental.py +690 -0
  338. sage/functions/trig.py +1062 -0
  339. sage/functions/wigner.py +726 -0
  340. sage/geometry/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  341. sage/geometry/abc.pyx +82 -0
  342. sage/geometry/all__sagemath_categories.py +1 -0
  343. sage/groups/all__sagemath_categories.py +11 -0
  344. sage/groups/generic.py +1733 -0
  345. sage/groups/groups_catalog.py +113 -0
  346. sage/groups/perm_gps/all__sagemath_categories.py +1 -0
  347. sage/groups/perm_gps/partn_ref/all.py +1 -0
  348. sage/groups/perm_gps/partn_ref/all__sagemath_categories.py +1 -0
  349. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.cpython-314t-aarch64-linux-musl.so +0 -0
  350. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pxd +52 -0
  351. sage/groups/perm_gps/partn_ref/automorphism_group_canonical_label.pyx +906 -0
  352. sage/groups/perm_gps/partn_ref/canonical_augmentation.cpython-314t-aarch64-linux-musl.so +0 -0
  353. sage/groups/perm_gps/partn_ref/canonical_augmentation.pxd +85 -0
  354. sage/groups/perm_gps/partn_ref/canonical_augmentation.pyx +534 -0
  355. sage/groups/perm_gps/partn_ref/data_structures.cpython-314t-aarch64-linux-musl.so +0 -0
  356. sage/groups/perm_gps/partn_ref/data_structures.pxd +576 -0
  357. sage/groups/perm_gps/partn_ref/data_structures.pyx +1792 -0
  358. sage/groups/perm_gps/partn_ref/double_coset.cpython-314t-aarch64-linux-musl.so +0 -0
  359. sage/groups/perm_gps/partn_ref/double_coset.pxd +45 -0
  360. sage/groups/perm_gps/partn_ref/double_coset.pyx +739 -0
  361. sage/groups/perm_gps/partn_ref/refinement_lists.cpython-314t-aarch64-linux-musl.so +0 -0
  362. sage/groups/perm_gps/partn_ref/refinement_lists.pxd +18 -0
  363. sage/groups/perm_gps/partn_ref/refinement_lists.pyx +82 -0
  364. sage/groups/perm_gps/partn_ref/refinement_python.cpython-314t-aarch64-linux-musl.so +0 -0
  365. sage/groups/perm_gps/partn_ref/refinement_python.pxd +16 -0
  366. sage/groups/perm_gps/partn_ref/refinement_python.pyx +564 -0
  367. sage/groups/perm_gps/partn_ref/refinement_sets.cpython-314t-aarch64-linux-musl.so +0 -0
  368. sage/groups/perm_gps/partn_ref/refinement_sets.pxd +60 -0
  369. sage/groups/perm_gps/partn_ref/refinement_sets.pyx +858 -0
  370. sage/interfaces/abc.py +140 -0
  371. sage/interfaces/all.py +58 -0
  372. sage/interfaces/all__sagemath_categories.py +1 -0
  373. sage/interfaces/expect.py +1643 -0
  374. sage/interfaces/interface.py +1682 -0
  375. sage/interfaces/process.cpython-314t-aarch64-linux-musl.so +0 -0
  376. sage/interfaces/process.pxd +5 -0
  377. sage/interfaces/process.pyx +288 -0
  378. sage/interfaces/quit.py +167 -0
  379. sage/interfaces/sage0.py +604 -0
  380. sage/interfaces/sagespawn.cpython-314t-aarch64-linux-musl.so +0 -0
  381. sage/interfaces/sagespawn.pyx +308 -0
  382. sage/interfaces/tab_completion.py +101 -0
  383. sage/misc/all__sagemath_categories.py +78 -0
  384. sage/misc/allocator.cpython-314t-aarch64-linux-musl.so +0 -0
  385. sage/misc/allocator.pxd +6 -0
  386. sage/misc/allocator.pyx +47 -0
  387. sage/misc/binary_tree.cpython-314t-aarch64-linux-musl.so +0 -0
  388. sage/misc/binary_tree.pxd +29 -0
  389. sage/misc/binary_tree.pyx +537 -0
  390. sage/misc/callable_dict.cpython-314t-aarch64-linux-musl.so +0 -0
  391. sage/misc/callable_dict.pyx +89 -0
  392. sage/misc/citation.cpython-314t-aarch64-linux-musl.so +0 -0
  393. sage/misc/citation.pyx +159 -0
  394. sage/misc/converting_dict.py +293 -0
  395. sage/misc/defaults.py +129 -0
  396. sage/misc/derivative.cpython-314t-aarch64-linux-musl.so +0 -0
  397. sage/misc/derivative.pyx +223 -0
  398. sage/misc/functional.py +2005 -0
  399. sage/misc/html.py +589 -0
  400. sage/misc/latex.py +2673 -0
  401. sage/misc/latex_macros.py +236 -0
  402. sage/misc/latex_standalone.py +1833 -0
  403. sage/misc/map_threaded.py +38 -0
  404. sage/misc/mathml.py +76 -0
  405. sage/misc/method_decorator.py +88 -0
  406. sage/misc/mrange.py +755 -0
  407. sage/misc/multireplace.py +41 -0
  408. sage/misc/object_multiplexer.py +92 -0
  409. sage/misc/parser.cpython-314t-aarch64-linux-musl.so +0 -0
  410. sage/misc/parser.pyx +1107 -0
  411. sage/misc/random_testing.py +264 -0
  412. sage/misc/rest_index_of_methods.py +377 -0
  413. sage/misc/search.cpython-314t-aarch64-linux-musl.so +0 -0
  414. sage/misc/search.pxd +2 -0
  415. sage/misc/search.pyx +68 -0
  416. sage/misc/stopgap.cpython-314t-aarch64-linux-musl.so +0 -0
  417. sage/misc/stopgap.pyx +95 -0
  418. sage/misc/table.py +853 -0
  419. sage/monoids/all__sagemath_categories.py +1 -0
  420. sage/monoids/indexed_free_monoid.py +1071 -0
  421. sage/monoids/monoid.py +82 -0
  422. sage/numerical/all__sagemath_categories.py +1 -0
  423. sage/numerical/backends/all__sagemath_categories.py +1 -0
  424. sage/numerical/backends/generic_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  425. sage/numerical/backends/generic_backend.pxd +61 -0
  426. sage/numerical/backends/generic_backend.pyx +1893 -0
  427. sage/numerical/backends/generic_sdp_backend.cpython-314t-aarch64-linux-musl.so +0 -0
  428. sage/numerical/backends/generic_sdp_backend.pxd +38 -0
  429. sage/numerical/backends/generic_sdp_backend.pyx +755 -0
  430. sage/parallel/all.py +6 -0
  431. sage/parallel/decorate.py +575 -0
  432. sage/parallel/map_reduce.py +1997 -0
  433. sage/parallel/multiprocessing_sage.py +76 -0
  434. sage/parallel/ncpus.py +35 -0
  435. sage/parallel/parallelism.py +364 -0
  436. sage/parallel/reference.py +47 -0
  437. sage/parallel/use_fork.py +333 -0
  438. sage/rings/abc.cpython-314t-aarch64-linux-musl.so +0 -0
  439. sage/rings/abc.pxd +31 -0
  440. sage/rings/abc.pyx +526 -0
  441. sage/rings/algebraic_closure_finite_field.py +1154 -0
  442. sage/rings/all__sagemath_categories.py +91 -0
  443. sage/rings/big_oh.py +227 -0
  444. sage/rings/continued_fraction.py +2754 -0
  445. sage/rings/continued_fraction_gosper.py +220 -0
  446. sage/rings/factorint.cpython-314t-aarch64-linux-musl.so +0 -0
  447. sage/rings/factorint.pyx +295 -0
  448. sage/rings/fast_arith.cpython-314t-aarch64-linux-musl.so +0 -0
  449. sage/rings/fast_arith.pxd +21 -0
  450. sage/rings/fast_arith.pyx +535 -0
  451. sage/rings/finite_rings/all__sagemath_categories.py +9 -0
  452. sage/rings/finite_rings/conway_polynomials.py +542 -0
  453. sage/rings/finite_rings/element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  454. sage/rings/finite_rings/element_base.pxd +12 -0
  455. sage/rings/finite_rings/element_base.pyx +1176 -0
  456. sage/rings/finite_rings/finite_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  457. sage/rings/finite_rings/finite_field_base.pxd +7 -0
  458. sage/rings/finite_rings/finite_field_base.pyx +2171 -0
  459. sage/rings/finite_rings/finite_field_constructor.py +827 -0
  460. sage/rings/finite_rings/finite_field_prime_modn.py +372 -0
  461. sage/rings/finite_rings/galois_group.py +154 -0
  462. sage/rings/finite_rings/hom_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  463. sage/rings/finite_rings/hom_finite_field.pxd +23 -0
  464. sage/rings/finite_rings/hom_finite_field.pyx +856 -0
  465. sage/rings/finite_rings/hom_prime_finite_field.cpython-314t-aarch64-linux-musl.so +0 -0
  466. sage/rings/finite_rings/hom_prime_finite_field.pxd +15 -0
  467. sage/rings/finite_rings/hom_prime_finite_field.pyx +164 -0
  468. sage/rings/finite_rings/homset.py +357 -0
  469. sage/rings/finite_rings/integer_mod.cpython-314t-aarch64-linux-musl.so +0 -0
  470. sage/rings/finite_rings/integer_mod.pxd +56 -0
  471. sage/rings/finite_rings/integer_mod.pyx +4586 -0
  472. sage/rings/finite_rings/integer_mod_limits.h +11 -0
  473. sage/rings/finite_rings/integer_mod_ring.py +2044 -0
  474. sage/rings/finite_rings/residue_field.cpython-314t-aarch64-linux-musl.so +0 -0
  475. sage/rings/finite_rings/residue_field.pxd +30 -0
  476. sage/rings/finite_rings/residue_field.pyx +1811 -0
  477. sage/rings/finite_rings/stdint.pxd +19 -0
  478. sage/rings/fraction_field.py +1452 -0
  479. sage/rings/fraction_field_element.cpython-314t-aarch64-linux-musl.so +0 -0
  480. sage/rings/fraction_field_element.pyx +1357 -0
  481. sage/rings/function_field/all.py +7 -0
  482. sage/rings/function_field/all__sagemath_categories.py +2 -0
  483. sage/rings/function_field/constructor.py +218 -0
  484. sage/rings/function_field/element.cpython-314t-aarch64-linux-musl.so +0 -0
  485. sage/rings/function_field/element.pxd +11 -0
  486. sage/rings/function_field/element.pyx +1008 -0
  487. sage/rings/function_field/element_rational.cpython-314t-aarch64-linux-musl.so +0 -0
  488. sage/rings/function_field/element_rational.pyx +513 -0
  489. sage/rings/function_field/extensions.py +230 -0
  490. sage/rings/function_field/function_field.py +1468 -0
  491. sage/rings/function_field/function_field_rational.py +1005 -0
  492. sage/rings/function_field/ideal.py +1155 -0
  493. sage/rings/function_field/ideal_rational.py +629 -0
  494. sage/rings/function_field/jacobian_base.py +826 -0
  495. sage/rings/function_field/jacobian_hess.py +1053 -0
  496. sage/rings/function_field/jacobian_khuri_makdisi.py +1027 -0
  497. sage/rings/function_field/maps.py +1039 -0
  498. sage/rings/function_field/order.py +281 -0
  499. sage/rings/function_field/order_basis.py +586 -0
  500. sage/rings/function_field/order_rational.py +576 -0
  501. sage/rings/function_field/place.py +426 -0
  502. sage/rings/function_field/place_rational.py +181 -0
  503. sage/rings/generic.py +320 -0
  504. sage/rings/homset.py +332 -0
  505. sage/rings/ideal.py +1885 -0
  506. sage/rings/ideal_monoid.py +215 -0
  507. sage/rings/infinity.py +1890 -0
  508. sage/rings/integer.cpython-314t-aarch64-linux-musl.so +0 -0
  509. sage/rings/integer.pxd +45 -0
  510. sage/rings/integer.pyx +7874 -0
  511. sage/rings/integer_ring.cpython-314t-aarch64-linux-musl.so +0 -0
  512. sage/rings/integer_ring.pxd +8 -0
  513. sage/rings/integer_ring.pyx +1693 -0
  514. sage/rings/laurent_series_ring.py +931 -0
  515. sage/rings/laurent_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  516. sage/rings/laurent_series_ring_element.pxd +11 -0
  517. sage/rings/laurent_series_ring_element.pyx +1927 -0
  518. sage/rings/lazy_series.py +7815 -0
  519. sage/rings/lazy_series_ring.py +4356 -0
  520. sage/rings/localization.py +1043 -0
  521. sage/rings/morphism.cpython-314t-aarch64-linux-musl.so +0 -0
  522. sage/rings/morphism.pxd +39 -0
  523. sage/rings/morphism.pyx +3299 -0
  524. sage/rings/multi_power_series_ring.py +1145 -0
  525. sage/rings/multi_power_series_ring_element.py +2184 -0
  526. sage/rings/noncommutative_ideals.cpython-314t-aarch64-linux-musl.so +0 -0
  527. sage/rings/noncommutative_ideals.pyx +423 -0
  528. sage/rings/number_field/all__sagemath_categories.py +1 -0
  529. sage/rings/number_field/number_field_base.cpython-314t-aarch64-linux-musl.so +0 -0
  530. sage/rings/number_field/number_field_base.pxd +8 -0
  531. sage/rings/number_field/number_field_base.pyx +507 -0
  532. sage/rings/number_field/number_field_element_base.cpython-314t-aarch64-linux-musl.so +0 -0
  533. sage/rings/number_field/number_field_element_base.pxd +6 -0
  534. sage/rings/number_field/number_field_element_base.pyx +36 -0
  535. sage/rings/number_field/number_field_ideal.py +3550 -0
  536. sage/rings/padics/all__sagemath_categories.py +4 -0
  537. sage/rings/padics/local_generic.py +1670 -0
  538. sage/rings/padics/local_generic_element.cpython-314t-aarch64-linux-musl.so +0 -0
  539. sage/rings/padics/local_generic_element.pxd +5 -0
  540. sage/rings/padics/local_generic_element.pyx +1017 -0
  541. sage/rings/padics/misc.py +256 -0
  542. sage/rings/padics/padic_generic.py +1911 -0
  543. sage/rings/padics/pow_computer.cpython-314t-aarch64-linux-musl.so +0 -0
  544. sage/rings/padics/pow_computer.pxd +38 -0
  545. sage/rings/padics/pow_computer.pyx +671 -0
  546. sage/rings/padics/precision_error.py +24 -0
  547. sage/rings/polynomial/all__sagemath_categories.py +25 -0
  548. sage/rings/polynomial/commutative_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  549. sage/rings/polynomial/commutative_polynomial.pxd +6 -0
  550. sage/rings/polynomial/commutative_polynomial.pyx +24 -0
  551. sage/rings/polynomial/cyclotomic.cpython-314t-aarch64-linux-musl.so +0 -0
  552. sage/rings/polynomial/cyclotomic.pyx +404 -0
  553. sage/rings/polynomial/flatten.py +711 -0
  554. sage/rings/polynomial/ideal.py +102 -0
  555. sage/rings/polynomial/infinite_polynomial_element.py +1768 -0
  556. sage/rings/polynomial/infinite_polynomial_ring.py +1653 -0
  557. sage/rings/polynomial/laurent_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  558. sage/rings/polynomial/laurent_polynomial.pxd +18 -0
  559. sage/rings/polynomial/laurent_polynomial.pyx +2190 -0
  560. sage/rings/polynomial/laurent_polynomial_ideal.py +590 -0
  561. sage/rings/polynomial/laurent_polynomial_ring.py +832 -0
  562. sage/rings/polynomial/laurent_polynomial_ring_base.py +708 -0
  563. sage/rings/polynomial/multi_polynomial.cpython-314t-aarch64-linux-musl.so +0 -0
  564. sage/rings/polynomial/multi_polynomial.pxd +12 -0
  565. sage/rings/polynomial/multi_polynomial.pyx +3082 -0
  566. sage/rings/polynomial/multi_polynomial_element.py +2570 -0
  567. sage/rings/polynomial/multi_polynomial_ideal.py +5771 -0
  568. sage/rings/polynomial/multi_polynomial_ring.py +947 -0
  569. sage/rings/polynomial/multi_polynomial_ring_base.cpython-314t-aarch64-linux-musl.so +0 -0
  570. sage/rings/polynomial/multi_polynomial_ring_base.pxd +15 -0
  571. sage/rings/polynomial/multi_polynomial_ring_base.pyx +1855 -0
  572. sage/rings/polynomial/multi_polynomial_sequence.py +2204 -0
  573. sage/rings/polynomial/polydict.cpython-314t-aarch64-linux-musl.so +0 -0
  574. sage/rings/polynomial/polydict.pxd +45 -0
  575. sage/rings/polynomial/polydict.pyx +2701 -0
  576. sage/rings/polynomial/polynomial_compiled.cpython-314t-aarch64-linux-musl.so +0 -0
  577. sage/rings/polynomial/polynomial_compiled.pxd +59 -0
  578. sage/rings/polynomial/polynomial_compiled.pyx +509 -0
  579. sage/rings/polynomial/polynomial_element.cpython-314t-aarch64-linux-musl.so +0 -0
  580. sage/rings/polynomial/polynomial_element.pxd +64 -0
  581. sage/rings/polynomial/polynomial_element.pyx +13255 -0
  582. sage/rings/polynomial/polynomial_element_generic.py +1637 -0
  583. sage/rings/polynomial/polynomial_fateman.py +97 -0
  584. sage/rings/polynomial/polynomial_quotient_ring.py +2465 -0
  585. sage/rings/polynomial/polynomial_quotient_ring_element.py +779 -0
  586. sage/rings/polynomial/polynomial_ring.py +3784 -0
  587. sage/rings/polynomial/polynomial_ring_constructor.py +1051 -0
  588. sage/rings/polynomial/polynomial_ring_homomorphism.cpython-314t-aarch64-linux-musl.so +0 -0
  589. sage/rings/polynomial/polynomial_ring_homomorphism.pxd +5 -0
  590. sage/rings/polynomial/polynomial_ring_homomorphism.pyx +121 -0
  591. sage/rings/polynomial/polynomial_singular_interface.py +549 -0
  592. sage/rings/polynomial/symmetric_ideal.py +989 -0
  593. sage/rings/polynomial/symmetric_reduction.cpython-314t-aarch64-linux-musl.so +0 -0
  594. sage/rings/polynomial/symmetric_reduction.pxd +8 -0
  595. sage/rings/polynomial/symmetric_reduction.pyx +669 -0
  596. sage/rings/polynomial/term_order.py +2279 -0
  597. sage/rings/polynomial/toy_buchberger.py +449 -0
  598. sage/rings/polynomial/toy_d_basis.py +387 -0
  599. sage/rings/polynomial/toy_variety.py +362 -0
  600. sage/rings/power_series_mpoly.cpython-314t-aarch64-linux-musl.so +0 -0
  601. sage/rings/power_series_mpoly.pxd +9 -0
  602. sage/rings/power_series_mpoly.pyx +161 -0
  603. sage/rings/power_series_poly.cpython-314t-aarch64-linux-musl.so +0 -0
  604. sage/rings/power_series_poly.pxd +10 -0
  605. sage/rings/power_series_poly.pyx +1317 -0
  606. sage/rings/power_series_ring.py +1441 -0
  607. sage/rings/power_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  608. sage/rings/power_series_ring_element.pxd +12 -0
  609. sage/rings/power_series_ring_element.pyx +3028 -0
  610. sage/rings/puiseux_series_ring.py +487 -0
  611. sage/rings/puiseux_series_ring_element.cpython-314t-aarch64-linux-musl.so +0 -0
  612. sage/rings/puiseux_series_ring_element.pxd +7 -0
  613. sage/rings/puiseux_series_ring_element.pyx +1055 -0
  614. sage/rings/qqbar_decorators.py +167 -0
  615. sage/rings/quotient_ring.py +1598 -0
  616. sage/rings/quotient_ring_element.py +979 -0
  617. sage/rings/rational.cpython-314t-aarch64-linux-musl.so +0 -0
  618. sage/rings/rational.pxd +20 -0
  619. sage/rings/rational.pyx +4284 -0
  620. sage/rings/rational_field.py +1730 -0
  621. sage/rings/real_double.cpython-314t-aarch64-linux-musl.so +0 -0
  622. sage/rings/real_double.pxd +16 -0
  623. sage/rings/real_double.pyx +2218 -0
  624. sage/rings/real_lazy.cpython-314t-aarch64-linux-musl.so +0 -0
  625. sage/rings/real_lazy.pxd +30 -0
  626. sage/rings/real_lazy.pyx +1773 -0
  627. sage/rings/ring.cpython-314t-aarch64-linux-musl.so +0 -0
  628. sage/rings/ring.pxd +30 -0
  629. sage/rings/ring.pyx +850 -0
  630. sage/rings/semirings/all.py +3 -0
  631. sage/rings/semirings/non_negative_integer_semiring.py +107 -0
  632. sage/rings/semirings/tropical_mpolynomial.py +972 -0
  633. sage/rings/semirings/tropical_polynomial.py +997 -0
  634. sage/rings/semirings/tropical_semiring.cpython-314t-aarch64-linux-musl.so +0 -0
  635. sage/rings/semirings/tropical_semiring.pyx +676 -0
  636. sage/rings/semirings/tropical_variety.py +1701 -0
  637. sage/rings/sum_of_squares.cpython-314t-aarch64-linux-musl.so +0 -0
  638. sage/rings/sum_of_squares.pxd +3 -0
  639. sage/rings/sum_of_squares.pyx +336 -0
  640. sage/rings/tests.py +504 -0
  641. sage/schemes/affine/affine_homset.py +508 -0
  642. sage/schemes/affine/affine_morphism.py +1574 -0
  643. sage/schemes/affine/affine_point.py +460 -0
  644. sage/schemes/affine/affine_rational_point.py +308 -0
  645. sage/schemes/affine/affine_space.py +1264 -0
  646. sage/schemes/affine/affine_subscheme.py +592 -0
  647. sage/schemes/affine/all.py +25 -0
  648. sage/schemes/all__sagemath_categories.py +5 -0
  649. sage/schemes/generic/algebraic_scheme.py +2092 -0
  650. sage/schemes/generic/all.py +5 -0
  651. sage/schemes/generic/ambient_space.py +400 -0
  652. sage/schemes/generic/divisor.py +465 -0
  653. sage/schemes/generic/divisor_group.py +313 -0
  654. sage/schemes/generic/glue.py +84 -0
  655. sage/schemes/generic/homset.py +820 -0
  656. sage/schemes/generic/hypersurface.py +234 -0
  657. sage/schemes/generic/morphism.py +2107 -0
  658. sage/schemes/generic/point.py +237 -0
  659. sage/schemes/generic/scheme.py +1190 -0
  660. sage/schemes/generic/spec.py +199 -0
  661. sage/schemes/product_projective/all.py +6 -0
  662. sage/schemes/product_projective/homset.py +236 -0
  663. sage/schemes/product_projective/morphism.py +517 -0
  664. sage/schemes/product_projective/point.py +568 -0
  665. sage/schemes/product_projective/rational_point.py +550 -0
  666. sage/schemes/product_projective/space.py +1301 -0
  667. sage/schemes/product_projective/subscheme.py +466 -0
  668. sage/schemes/projective/all.py +24 -0
  669. sage/schemes/projective/proj_bdd_height.py +453 -0
  670. sage/schemes/projective/projective_homset.py +718 -0
  671. sage/schemes/projective/projective_morphism.py +2792 -0
  672. sage/schemes/projective/projective_point.py +1484 -0
  673. sage/schemes/projective/projective_rational_point.py +569 -0
  674. sage/schemes/projective/projective_space.py +2571 -0
  675. sage/schemes/projective/projective_subscheme.py +1574 -0
  676. sage/sets/all.py +17 -0
  677. sage/sets/cartesian_product.py +376 -0
  678. sage/sets/condition_set.py +525 -0
  679. sage/sets/disjoint_set.cpython-314t-aarch64-linux-musl.so +0 -0
  680. sage/sets/disjoint_set.pxd +36 -0
  681. sage/sets/disjoint_set.pyx +998 -0
  682. sage/sets/disjoint_union_enumerated_sets.py +625 -0
  683. sage/sets/family.cpython-314t-aarch64-linux-musl.so +0 -0
  684. sage/sets/family.pxd +12 -0
  685. sage/sets/family.pyx +1556 -0
  686. sage/sets/finite_enumerated_set.py +406 -0
  687. sage/sets/finite_set_map_cy.cpython-314t-aarch64-linux-musl.so +0 -0
  688. sage/sets/finite_set_map_cy.pxd +34 -0
  689. sage/sets/finite_set_map_cy.pyx +708 -0
  690. sage/sets/finite_set_maps.py +591 -0
  691. sage/sets/image_set.py +448 -0
  692. sage/sets/integer_range.py +829 -0
  693. sage/sets/non_negative_integers.py +241 -0
  694. sage/sets/positive_integers.py +93 -0
  695. sage/sets/primes.py +188 -0
  696. sage/sets/real_set.py +2760 -0
  697. sage/sets/recursively_enumerated_set.cpython-314t-aarch64-linux-musl.so +0 -0
  698. sage/sets/recursively_enumerated_set.pxd +31 -0
  699. sage/sets/recursively_enumerated_set.pyx +2082 -0
  700. sage/sets/set.py +2083 -0
  701. sage/sets/set_from_iterator.py +1021 -0
  702. sage/sets/totally_ordered_finite_set.py +329 -0
  703. sage/symbolic/all__sagemath_categories.py +1 -0
  704. sage/symbolic/function.cpython-314t-aarch64-linux-musl.so +0 -0
  705. sage/symbolic/function.pxd +29 -0
  706. sage/symbolic/function.pyx +1488 -0
  707. sage/symbolic/symbols.py +56 -0
  708. sage/tests/all__sagemath_categories.py +1 -0
  709. sage/tests/cython.cpython-314t-aarch64-linux-musl.so +0 -0
  710. sage/tests/cython.pyx +37 -0
  711. sage/tests/stl_vector.cpython-314t-aarch64-linux-musl.so +0 -0
  712. sage/tests/stl_vector.pyx +171 -0
  713. sage/typeset/all.py +6 -0
  714. sage/typeset/ascii_art.py +295 -0
  715. sage/typeset/character_art.py +789 -0
  716. sage/typeset/character_art_factory.py +572 -0
  717. sage/typeset/symbols.py +334 -0
  718. sage/typeset/unicode_art.py +183 -0
  719. sage/typeset/unicode_characters.py +101 -0
@@ -0,0 +1,1701 @@
1
+ # sage_setup: distribution = sagemath-categories
2
+ # sage.doctest: needs sage.symbolic
3
+ r"""
4
+ Tropical Varieties
5
+
6
+ A tropical variety is a piecewise-linear geometric object derived from
7
+ a classical algebraic variety by using tropical mathematics, where the
8
+ tropical semiring replaces the usual arithmetic operations.
9
+
10
+ AUTHORS:
11
+
12
+ - Verrel Rievaldo Wijaya (2024-06): initial version
13
+
14
+ REFERENCES:
15
+
16
+ - [Bru2014]_
17
+ - [Mac2015]_
18
+ - [Fil2017]_
19
+ """
20
+
21
+ # ****************************************************************************
22
+ # Copyright (C) 2024 Verrel Rievaldo Wijaya <verrelrievaldo@gmail.com>
23
+ #
24
+ # This program is free software: you can redistribute it and/or modify
25
+ # it under the terms of the GNU General Public License as published by
26
+ # the Free Software Foundation, either version 2 of the License, or
27
+ # (at your option) any later version.
28
+ # https://www.gnu.org/licenses/
29
+ # ****************************************************************************
30
+
31
+ from sage.rings.infinity import infinity
32
+ from sage.rings.rational_field import QQ
33
+ from sage.structure.sage_object import SageObject
34
+ from sage.structure.unique_representation import UniqueRepresentation
35
+
36
+
37
+ class TropicalVariety(UniqueRepresentation, SageObject):
38
+ r"""
39
+ A tropical variety in `\RR^n`.
40
+
41
+ A tropical variety is defined as a corner locus of tropical polynomial
42
+ function. This means it consist of all points in `\RR^n` for which
43
+ the minimum (maximum) of the function is attained at least twice.
44
+
45
+ We represent the tropical variety as a list of lists, where the
46
+ inner list consist of three parts. The first one is a parametric
47
+ equations for tropical roots. The second one is the condition
48
+ for parameters. The third one is the order of the corresponding
49
+ component.
50
+
51
+ INPUT:
52
+
53
+ - ``poly`` -- a :class:`TropicalMPolynomial`
54
+
55
+ ALGORITHM:
56
+
57
+ We need to determine a corner locus of this tropical polynomial
58
+ function, which is all points `(x_1, x_2, \ldots, x_n)` for which
59
+ the maximum (minimum) is obtained at least twice. First, we convert
60
+ each monomial to its corresponding linear function. Then for each two
61
+ monomials of polynomial, we find the points where their values are
62
+ equal. Since we attempt to solve the equality of two equations in `n`
63
+ variables, the solution set will be described by `n-1` parameters.
64
+
65
+ Next, we need to check if the value of previous two monomials at the
66
+ points in solution set is really the maximum (minimum) of function.
67
+ We do this by solving the inequality of the previous monomial with all
68
+ other monomials in the polynomial after substituting the parameter.
69
+ This will give us the condition of parameters. Each of this condition
70
+ is then combined by union operator. If this final condition is not an
71
+ empty set, then it represent one component of tropical root. Then we
72
+ calculate the weight of this particular component by the maximum of
73
+ gcd of the numbers `|i-k|` and `|j-l|` for all pairs `(i,j)` and
74
+ `(k,l)` such that the value of on this component is given by the
75
+ corresponding monomials.
76
+
77
+ EXAMPLES:
78
+
79
+ We construct a tropical variety in `\RR^2`, where it is called a
80
+ tropical curve::
81
+
82
+ sage: T = TropicalSemiring(QQ, use_min=False)
83
+ sage: R.<x,y> = PolynomialRing(T)
84
+ sage: p1 = R(1)*x + x*y + R(0); p1
85
+ 0*x*y + 1*x + 0
86
+ sage: tv = p1.tropical_variety(); tv
87
+ Tropical curve of 0*x*y + 1*x + 0
88
+ sage: tv.components()
89
+ [[(t1, 1), [t1 >= -1], 1], [(-1, t1), [t1 <= 1], 1], [(-t1, t1), [t1 >= 1], 1]]
90
+ sage: tv.vertices()
91
+ {(-1, 1)}
92
+ sage: tv.plot() # needs sage.plot
93
+ Graphics object consisting of 3 graphics primitives
94
+
95
+ .. PLOT::
96
+ :width: 300 px
97
+
98
+ T = TropicalSemiring(QQ, use_min=False)
99
+ R = PolynomialRing(T, ('x,y'))
100
+ x, y = R.gen(), R.gen(1)
101
+ p1 = R(1)*x + x*y + R(0)
102
+ sphinx_plot(p1.tropical_variety().plot())
103
+
104
+ A slightly different result will be obtained if we use min-plus algebra
105
+ for the base tropical semiring::
106
+
107
+ sage: T = TropicalSemiring(QQ, use_min=True)
108
+ sage: R.<x,y> = PolynomialRing(T)
109
+ sage: p1 = R(1)*x + x*y + R(0)
110
+ sage: tv = p1.tropical_variety(); tv
111
+ Tropical curve of 0*x*y + 1*x + 0
112
+ sage: tv.components()
113
+ [[(t1, 1), [t1 <= -1], 1], [(-1, t1), [t1 >= 1], 1], [(-t1, t1), [t1 <= 1], 1]]
114
+ sage: tv.plot() # needs sage.plot
115
+ Graphics object consisting of 3 graphics primitives
116
+
117
+ .. PLOT::
118
+ :width: 300 px
119
+
120
+ T = TropicalSemiring(QQ, use_min=True)
121
+ R = PolynomialRing(T, ('x,y'))
122
+ x, y = R.gen(), R.gen(1)
123
+ p1 = R(1)*x + x*y + R(0)
124
+ sphinx_plot(p1.tropical_variety().plot())
125
+
126
+ Tropical variety can consist of multiple components with varying orders::
127
+
128
+ sage: T = TropicalSemiring(QQ, use_min=False)
129
+ sage: R.<x,y> = PolynomialRing(T)
130
+ sage: p1 = R(7) + T(4)*x + y + R(4)*x*y + R(3)*y^2 + R(-3)*x^2
131
+ sage: tv = p1.tropical_variety(); tv
132
+ Tropical curve of (-3)*x^2 + 4*x*y + 3*y^2 + 4*x + 0*y + 7
133
+ sage: tv.components()
134
+ [[(3, t1), [t1 <= 0], 1],
135
+ [(-t1 + 3, t1), [0 <= t1, t1 <= 2], 1],
136
+ [(t1, 2), [t1 <= 1], 2],
137
+ [(t1, 0), [3 <= t1, t1 <= 7], 1],
138
+ [(7, t1), [t1 <= 0], 1],
139
+ [(t1 - 1, t1), [2 <= t1], 1],
140
+ [(t1 + 7, t1), [0 <= t1], 1]]
141
+ sage: tv.plot() # needs sage.plot
142
+ Graphics object consisting of 8 graphics primitives
143
+
144
+ .. PLOT::
145
+ :width: 300 px
146
+
147
+ T = TropicalSemiring(QQ, use_min=False)
148
+ R = PolynomialRing(T, ('x,y'))
149
+ x, y = R.gen(), R.gen(1)
150
+ p1 = R(7) + T(4)*x + y + R(4)*x*y + R(3)*y**2 + R(-3)*x**2
151
+ sphinx_plot(p1.tropical_variety().plot())
152
+
153
+ If the tropical polynomial have `n>2` variables, then the result will be
154
+ a tropical hypersurface embedded in a real space `\RR^n`::
155
+
156
+ sage: T = TropicalSemiring(QQ)
157
+ sage: R.<w,x,y,z> = PolynomialRing(T)
158
+ sage: p1 = x*y + R(-1/2)*x*z + R(4)*z^2 + w*x
159
+ sage: tv = p1.tropical_variety(); tv
160
+ Tropical hypersurface of 0*w*x + 0*x*y + (-1/2)*x*z + 4*z^2
161
+ sage: tv.components()
162
+ [[(t1, t2, t3 - 1/2, t3), [t2 - 9/2 <= t3, t3 <= t1 + 1/2, t2 - 5 <= t1], 1],
163
+ [(t1, 2*t2 - t3 + 4, t3, t2), [t3 + 1/2 <= t2, t3 <= t1], 1],
164
+ [(t1, t2, t1, t3), [max(t1 + 1/2, 1/2*t1 + 1/2*t2 - 2) <= t3], 1],
165
+ [(t1, t2 + 9/2, t3, t2), [t2 <= min(t3 + 1/2, t1 + 1/2)], 1],
166
+ [(t1 - 1/2, t2, t3, t1), [t2 - 9/2 <= t1, t1 <= t3 + 1/2, t2 - 5 <= t3], 1],
167
+ [(2*t1 - t2 + 4, t2, t3, t1), [t1 <= min(1/2*t2 + 1/2*t3 - 2, t2 - 9/2)], 1]]
168
+ """
169
+ def __init__(self, poly):
170
+ r"""
171
+ Initialize ``self``.
172
+
173
+ EXAMPLES::
174
+
175
+ sage: T = TropicalSemiring(QQ)
176
+ sage: R.<x,y> = PolynomialRing(T)
177
+ sage: tv = (x+y).tropical_variety()
178
+ sage: TestSuite(tv).run()
179
+
180
+ TESTS::
181
+
182
+ sage: from sage.rings.semirings.tropical_variety import TropicalVariety
183
+ sage: R.<x,y> = QQ[]
184
+ sage: p1 = x + y
185
+ sage: TropicalVariety(p1)
186
+ Traceback (most recent call last):
187
+ ...
188
+ ValueError: x + y is not a multivariate tropical polynomial
189
+ """
190
+ import operator
191
+ from itertools import combinations
192
+
193
+ from sage.arith.misc import gcd
194
+ from sage.rings.semirings.tropical_mpolynomial import TropicalMPolynomial
195
+ from sage.symbolic.relation import solve
196
+ from sage.symbolic.ring import SR
197
+
198
+ if not isinstance(poly, TropicalMPolynomial):
199
+ raise ValueError(f"{poly} is not a multivariate tropical polynomial")
200
+
201
+ self._poly = poly
202
+ self._hypersurface = []
203
+ tropical_roots = []
204
+ variables = [SR.var(name)
205
+ for name in poly.parent().variable_names()]
206
+
207
+ # Convert each term to its linear function
208
+ linear_eq = {}
209
+ pd = poly.monomial_coefficients()
210
+ for key in pd:
211
+ eq = sum(variables[i] * e for i, e in enumerate(key))
212
+ eq += pd[key].lift()
213
+ linear_eq[key] = eq
214
+ temp_keys = []
215
+ temp_order = []
216
+
217
+ # Checking for all possible combinations of two terms
218
+ for keys in combinations(pd, 2):
219
+ sol = solve(linear_eq[keys[0]] == linear_eq[keys[1]], variables)
220
+
221
+ # Parametric solution of the chosen two terms
222
+ final_sol = [s.right() for s in sol[0]]
223
+ xy_interval = []
224
+ xy_interval.append(tuple(final_sol))
225
+
226
+ # Comparing with other terms
227
+ min_max = linear_eq[keys[0]]
228
+ for i, v in enumerate(variables):
229
+ min_max = min_max.subs(**{str(v): final_sol[i]})
230
+ all_sol_compare = []
231
+ no_solution = False
232
+ for compare in pd:
233
+ if compare not in keys:
234
+ temp_compare = linear_eq[compare]
235
+ for i, v in enumerate(variables):
236
+ temp_compare = temp_compare.subs(**{str(v): final_sol[i]})
237
+ if min_max == temp_compare:
238
+ sol_compare = [[]]
239
+ elif poly.parent().base()._use_min:
240
+ sol_compare = solve(min_max < temp_compare, variables)
241
+ else:
242
+ sol_compare = solve(min_max > temp_compare, variables)
243
+ if sol_compare:
244
+ if isinstance(sol_compare[0], list):
245
+ if sol_compare[0]:
246
+ all_sol_compare.append(sol_compare[0][0])
247
+ else: # solution is unbounded on one side
248
+ all_sol_compare.append(sol_compare[0])
249
+ else:
250
+ no_solution = True
251
+ break
252
+
253
+ # Solve the condition for parameter
254
+ if not no_solution:
255
+ parameter = set()
256
+ for sol in all_sol_compare:
257
+ parameter = parameter.union(set(sol.variables()))
258
+ parameter_solution = solve(all_sol_compare, list(parameter))
259
+ if parameter_solution:
260
+ xy_interval.append(parameter_solution[0])
261
+ tropical_roots.append(xy_interval)
262
+ # Calculate the order
263
+ index_diff = [abs(ai - bi)
264
+ for ai, bi in zip(keys[0], keys[1])]
265
+ order = gcd(index_diff)
266
+ temp_order.append(order)
267
+ temp_keys.append(keys)
268
+
269
+ # Changing all the operator's symbol to <= or >=
270
+ self._keys = []
271
+ components = []
272
+ dim_param = 0
273
+ if tropical_roots:
274
+ dim_param = len(tropical_roots[0][0]) - 1
275
+ vars = [SR.var(f't{i}') for i in range(1, dim_param + 1)]
276
+ for arg in tropical_roots:
277
+ subs_dict = {}
278
+ index_vars = 0
279
+ new_eq = []
280
+ for eq in arg[0]:
281
+ var_eq = eq.variables()
282
+ for var in var_eq:
283
+ if var not in subs_dict:
284
+ subs_dict[var] = vars[index_vars]
285
+ index_vars += 1
286
+ new_eq.append(eq.subs(subs_dict))
287
+ new_eq = tuple(new_eq)
288
+ arg.remove(arg[0])
289
+ arg.insert(0, new_eq)
290
+ if not arg[1] or not isinstance(arg[1], list):
291
+ arg[1] = []
292
+ for var in vars:
293
+ expr1 = -infinity < var
294
+ expr2 = var < infinity
295
+ arg[1].append(expr1)
296
+ arg[1].append(expr2)
297
+ else:
298
+ params = arg[1]
299
+ arg.remove(params)
300
+ new_param = []
301
+ for param in params:
302
+ lhs = param.lhs().subs(subs_dict)
303
+ rhs = param.rhs().subs(subs_dict)
304
+ if param.operator() == operator.gt:
305
+ expr = lhs >= rhs
306
+ else:
307
+ expr = lhs <= rhs
308
+ new_param.append(expr)
309
+ arg.insert(1, new_param)
310
+ components.append(arg)
311
+
312
+ # Determine the order of each component
313
+ self._vars = vars
314
+ final_order = []
315
+ for i, component in enumerate(components):
316
+ if component not in self._hypersurface:
317
+ self._hypersurface.append(component)
318
+ final_order.append(temp_order[i])
319
+ self._keys.append(temp_keys[i])
320
+ else:
321
+ index = self._hypersurface.index(component)
322
+ if temp_order[i] > final_order[index]:
323
+ final_order[index] = temp_order[i]
324
+ self._keys[index] = temp_keys[i]
325
+ for i in range(len(self._hypersurface)):
326
+ self._hypersurface[i].append(final_order[i])
327
+
328
+ def dimension(self):
329
+ """
330
+ Return the dimension of ``self``.
331
+
332
+ EXAMPLES::
333
+
334
+ sage: T = TropicalSemiring(QQ)
335
+ sage: R.<a,x,y,z> = PolynomialRing(T)
336
+ sage: p1 = x*y + R(-1)*x*z
337
+ sage: p1.tropical_variety().dimension()
338
+ 4
339
+ """
340
+ return self._poly.parent().ngens()
341
+
342
+ def number_of_components(self):
343
+ """
344
+ Return the number of components that make up ``self``.
345
+
346
+ EXAMPLES::
347
+
348
+ sage: T = TropicalSemiring(QQ)
349
+ sage: R.<a,x,y,z> = PolynomialRing(T)
350
+ sage: p1 = x*y*a + x*z + y^2 + a*x + y + z
351
+ sage: p1.tropical_variety().number_of_components()
352
+ 13
353
+ """
354
+ from sage.rings.integer_ring import ZZ
355
+ return ZZ(len(self._hypersurface))
356
+
357
+ def _repr_(self):
358
+ """
359
+ Return a string representation of ``self``.
360
+
361
+ EXAMPLES::
362
+
363
+ sage: T = TropicalSemiring(QQ)
364
+ sage: R.<w,x,y,z> = PolynomialRing(T)
365
+ sage: (w).tropical_variety()
366
+ Tropical hypersurface of 0*w
367
+ """
368
+ return f"Tropical hypersurface of {self._poly}"
369
+
370
+ def _latex_(self):
371
+ r"""
372
+ Return a latex representation of ``self``.
373
+
374
+ EXAMPLES::
375
+
376
+ sage: T = TropicalSemiring(QQ)
377
+ sage: R.<w,x,y,z> = PolynomialRing(T)
378
+ sage: tv = (R(1)*w^2 + x*y*z + R(-1)).tropical_variety()
379
+ sage: latex(tv)
380
+ TV\left(0 x y z + 1 w^{2} + \left(-1\right)\right)
381
+ """
382
+ return f"TV\\left({self._poly._latex_()}\\right)"
383
+
384
+ def components(self):
385
+ """
386
+ Return all components of ``self``.
387
+
388
+ EXAMPLES::
389
+
390
+ sage: T = TropicalSemiring(QQ)
391
+ sage: R.<a,x,y,z> = PolynomialRing(T)
392
+ sage: tv = (a+x+y+z).tropical_variety()
393
+ sage: tv.components()
394
+ [[(t1, t1, t2, t3), [t1 <= min(t3, t2)], 1],
395
+ [(t1, t2, t1, t3), [t1 <= t3, t1 <= t2], 1],
396
+ [(t1, t2, t3, t1), [t1 <= min(t3, t2)], 1],
397
+ [(t1, t2, t2, t3), [t2 <= t3, t2 <= t1], 1],
398
+ [(t1, t2, t3, t2), [t2 <= min(t3, t1)], 1],
399
+ [(t1, t2, t3, t3), [t3 <= min(t1, t2)], 1]]
400
+ """
401
+ return self._hypersurface
402
+
403
+ def _components_intersection(self):
404
+ r"""
405
+ Return the intersection of three or more components of ``self``.
406
+
407
+ For a tropical variety in `\RR^n`, the intersection is characterized
408
+ by a linear equation in `\RR^{n-1}`. Specifically, this becomes a
409
+ vertex for tropical curve and an edges for tropical surface.
410
+
411
+ OUTPUT:
412
+
413
+ A dictionary where the keys represent component indices and the
414
+ values are lists of tuples. Each tuple contains a parametric
415
+ equation of points and the corresponding parameter's condition.
416
+
417
+ EXAMPLES:
418
+
419
+ In two dimension, it will provide vertices that are incident with
420
+ each component::
421
+
422
+ sage: T = TropicalSemiring(QQ)
423
+ sage: R.<x,y> = PolynomialRing(T)
424
+ sage: p1 = R(2)*x^2 + x*y + R(2)*y^2 + x + R(-1)*y + R(3)
425
+ sage: tv = p1.tropical_variety()
426
+ sage: tv._components_intersection()
427
+ {0: [((-2, 0), {})],
428
+ 1: [((-2, 0), {})],
429
+ 2: [((-1, -3), {})],
430
+ 3: [((-2, 0), {}), ((-1, 0), {})],
431
+ 4: [((-1, -3), {}), ((-1, 0), {})],
432
+ 5: [((-1, -3), {})],
433
+ 6: [((-1, 0), {}), ((3, 4), {})],
434
+ 7: [((3, 4), {})],
435
+ 8: [((3, 4), {})]}
436
+
437
+ In three dimensions, it will provide all parametric equations of
438
+ lines that lie within each component::
439
+
440
+ sage: T = TropicalSemiring(QQ)
441
+ sage: R.<x,y,z> = PolynomialRing(T)
442
+ sage: p1 = x + y + z + x^2
443
+ sage: tv = p1.tropical_variety()
444
+ sage: tv._components_intersection()
445
+ {0: [((t2, t2, t2), {0 <= t2}), ((0, 0, t2), {0 <= t2})],
446
+ 1: [((0, t2, 0), {0 <= t2}), ((t2, t2, t2), {0 <= t2})],
447
+ 2: [((0, t1, 0), {0 <= t1}), ((0, 0, t2), {0 <= t2})],
448
+ 3: [((t1, t1, t1), {0 <= t1}), ((t1, 2*t1, 2*t1), {t1 <= 0})],
449
+ 4: [((1/2*t2, t2, t2), {t2 <= 0}), ((0, 0, t2), {0 <= t2})],
450
+ 5: [((0, t2, 0), {0 <= t2}), ((1/2*t2, t2, t2), {t2 <= 0})]}
451
+ """
452
+ import operator
453
+
454
+ from sage.functions.min_max import max_symbolic, min_symbolic
455
+ from sage.sets.set import Set
456
+ from sage.symbolic.relation import solve
457
+
458
+ def update_result(result):
459
+ sol_param = solve(new_expr, vars)
460
+ sol_param_sim = set()
461
+ for sol in sol_param:
462
+ if sol == []:
463
+ for v in vars:
464
+ if v != var:
465
+ sol_param_sim.add(v < infinity)
466
+ elif isinstance(sol, list):
467
+ for eqn in sol:
468
+ if eqn.operator() == operator.eq:
469
+ if not eqn.rhs().is_numeric():
470
+ eqn_var = eqn.rhs().variables()
471
+ param_var = [v for v in eqn_var if v in vars]
472
+ if not param_var:
473
+ v = eqn.lhs()
474
+ if v != var:
475
+ sol_param_sim.add(v < infinity)
476
+ elif eqn.operator() == operator.lt:
477
+ sol_param_sim.add(eqn.lhs() <= eqn.rhs())
478
+ elif eqn.operator() == operator.gt:
479
+ sol_param_sim.add(eqn.lhs() >= eqn.rhs())
480
+ else:
481
+ sol_param_sim.add(sol)
482
+
483
+ # Checking there are no conditions with the same variables
484
+ # that use the <= and >= operators simultaneously
485
+ unique_sol_param = set()
486
+ temp = list(sol_param_sim)
487
+ op_temp = {i: set(temp[i].operands()) for i in range(len(temp))}
488
+ for s_value in op_temp.values():
489
+ match_keys = [k for k, v in op_temp.items() if v == s_value]
490
+ if len(match_keys) == 1:
491
+ for i in match_keys:
492
+ unique_sol_param.add(temp[i])
493
+
494
+ if (unique_sol_param) or (self.dimension() == 2):
495
+ if not unique_sol_param:
496
+ unique_sol_param = Set()
497
+ if index not in result:
498
+ result[index] = [(tuple(points), unique_sol_param)]
499
+ else:
500
+ result[index].append((tuple(points), unique_sol_param))
501
+
502
+ result = {}
503
+ vars = self._vars
504
+ for index, comp in enumerate(self._hypersurface):
505
+ for expr in comp[1]:
506
+ left = expr.lhs()
507
+ right = expr.rhs()
508
+ # If the lhs contains a min or max operator
509
+ if (left.operator() == max_symbolic) or (left.operator() == min_symbolic):
510
+ for operand in expr.lhs().operands():
511
+ points = list(comp[0])
512
+ new_expr = [e.subs(**{str(right): operand}) for e in comp[1]]
513
+ for i, p in enumerate(points):
514
+ new_eq = p.subs(**{str(right): operand})
515
+ points[i] = new_eq
516
+ update_result(result)
517
+ # If the rhs contains a min or max operator
518
+ elif (right.operator() == max_symbolic) or (right.operator() == min_symbolic):
519
+ for operand in expr.rhs().operands():
520
+ points = list(comp[0])
521
+ new_expr = [e.subs(**{str(left): operand}) for e in comp[1]]
522
+ for i, p in enumerate(points):
523
+ new_eq = p.subs(**{str(left): operand})
524
+ points[i] = new_eq
525
+ update_result(result)
526
+ else:
527
+ var = expr.variables()[0]
528
+ points = list(comp[0])
529
+ subs_expr = solve(left == right, var)[0].rhs()
530
+ new_expr = [e.subs(**{str(var): subs_expr}) for e in comp[1]]
531
+ for i, p in enumerate(points):
532
+ new_eq = p.subs(**{str(var): subs_expr})
533
+ points[i] = new_eq
534
+ update_result(result)
535
+ return result
536
+
537
+ def weight_vectors(self):
538
+ r"""
539
+ Return the weight vectors for each unique intersection of
540
+ components of ``self``.
541
+
542
+ Weight vectors are a list of vectors associated with each
543
+ unique intersection of the components of tropical variety.
544
+ Each vector is a normal vector to a component with respect
545
+ to the unique intersection lying within that component.
546
+
547
+ Assume ``self`` is a `n`-dimensional tropical variety.
548
+ Suppose `L` is an intersection lying within the components
549
+ `S_1, \ldots, S_k` with respective weights `w_1, \ldots, w_k`.
550
+ This `L` is a linear structure in `\RR^{n-1}` and has `n-1`
551
+ direction vectors `d_1,d_2,\ldots, d_{n-1}`. Each component
552
+ `S_1, \ldots, S_k` has a normal vector `n_1, \ldots, n_k`.
553
+ Then, we scale each normal vector to an integer vector such
554
+ that the greatest common divisor of its elements is 1.
555
+
556
+ The weight vector of a component `S_i` with respect to `L`
557
+ can be found by calculating the cross product between direction
558
+ vectors of `L` and normal vector `n_i`.These vectors will
559
+ satisfy the balancing condition `\sum_{i=1}^k w_k v_k = 0`.
560
+
561
+ OUTPUT:
562
+
563
+ A tuple of three dictionaries. The first dictionary contains
564
+ equations representing the intersections. The second dictionary
565
+ contains indices of components that contains the intersection.
566
+ The third dictionary contains lists of vectors.
567
+
568
+ EXAMPLES:
569
+
570
+ Weight vectors of tropical surface::
571
+
572
+ sage: T = TropicalSemiring(QQ)
573
+ sage: R.<x,y,z> = PolynomialRing(T)
574
+ sage: p = x^2 + R(-1)*y + z + R(1)
575
+ sage: tv = p.tropical_variety()
576
+ sage: tv.weight_vectors()
577
+ ({0: ((1/2*u2, u2 + 1, u2), {u2 <= 1}),
578
+ 1: ((1/2, 2, u2), {1 <= u2}),
579
+ 2: ((1/2, u2, 1), {2 <= u2}),
580
+ 3: ((u1, 2, 1), {(1/2) <= u1})},
581
+ {0: [0, 1, 3], 1: [0, 2, 4], 2: [1, 2, 5], 3: [3, 4, 5]},
582
+ {0: [(1, 2, -5/2), (1, -5/2, 2), (-2, 1/2, 1/2)],
583
+ 1: [(-1, -2, 0), (0, 2, 0), (1, 0, 0)],
584
+ 2: [(1, 0, 2), (0, 0, -2), (-1, 0, 0)],
585
+ 3: [(0, 1, 1), (0, 0, -1), (0, -1, 0)]})
586
+
587
+ TESTS:
588
+
589
+ Checking the balance condition of weight vectors::
590
+
591
+ sage: T = TropicalSemiring(QQ)
592
+ sage: R.<a,b,c,d> = PolynomialRing(T)
593
+ sage: f = R.random_element()
594
+ sage: vec = f.tropical_variety().weight_vectors()[2].values()
595
+ sage: all(a == vector([0,0,0,0]) for a in [sum(lst) for lst in vec]) # not tested (:issue:`39663`)
596
+ True
597
+ """
598
+ from itertools import combinations
599
+
600
+ from sage.arith.misc import gcd
601
+ from sage.calculus.functional import diff
602
+ from sage.matrix.constructor import matrix
603
+ from sage.modules.free_module_element import vector, zero_vector
604
+ from sage.symbolic.relation import solve
605
+ from sage.symbolic.ring import SR
606
+
607
+ dim = self.dimension()
608
+ t = SR.var('t')
609
+ t_vars = [SR.var(f't{i}') for i in range(dim)]
610
+ u_vars = [SR.var(f'u{i}') for i in range(dim)]
611
+ convert_tu = dict(zip(t_vars, u_vars))
612
+ CI = self._components_intersection()
613
+ unique_line = set()
614
+ index_line = {}
615
+ line_comps = {}
616
+ index = 0
617
+
618
+ # Find the unique intersection between multiple components and
619
+ # the indices of the components containing this intersection.
620
+ for i, lines in CI.items():
621
+ for line in lines:
622
+ eqn = line[0]
623
+ is_unique = True
624
+ for uniq in unique_line:
625
+ subs_index = -1
626
+ for j in range(dim):
627
+ if eqn[j] != uniq[j]:
628
+ subs_index = j
629
+ break
630
+ if subs_index == -1:
631
+ new_line = eqn
632
+ is_unique = False
633
+ break
634
+ subs_dict = {}
635
+ while len(subs_dict) != dim-2 and subs_index < dim:
636
+ eq1 = eqn[subs_index].subs(subs_dict)
637
+ vib = None
638
+ for unk in eq1.variables():
639
+ if unk not in subs_dict:
640
+ if unk in t_vars:
641
+ vib = unk
642
+ break
643
+ if vib:
644
+ eq1 = eq1.subs(**{str(vib): t})
645
+ eq2 = uniq[subs_index]
646
+ temp_sol = solve(eq1 == eq2, t)
647
+ if temp_sol:
648
+ temp_sol = temp_sol[0].rhs()
649
+ if not temp_sol.is_numeric():
650
+ subs_dict[vib] = temp_sol
651
+ subs_index += 1
652
+ if subs_dict:
653
+ new_line = []
654
+ for l in eqn:
655
+ for key, value in subs_dict.items():
656
+ l = l.subs(key == value)
657
+ new_line.append(l)
658
+ if tuple(new_line) in unique_line:
659
+ is_unique = False
660
+ break
661
+ if is_unique:
662
+ new_eqn = tuple([eq.subs(convert_tu) for eq in eqn])
663
+ cdns = line[1]
664
+ new_cdn = {cdn.subs(convert_tu) for cdn in cdns}
665
+ unique_line.add(new_eqn)
666
+ index_line[index] = (new_eqn, new_cdn)
667
+ line_comps[index] = [i]
668
+ index += 1
669
+ else:
670
+ match_key = [k for k, v in index_line.items() if v[0] == tuple(new_line)][0]
671
+ line_comps[match_key].append(i)
672
+
673
+ WV = {i: [] for i in range(len(line_comps)) if len(line_comps[i]) > 1}
674
+ for k in WV:
675
+ # Calculate direction vector of the line
676
+ dir_vecs = []
677
+ line = index_line[k][0]
678
+ all_var = set()
679
+ for l in line:
680
+ for v in l.variables():
681
+ all_var.add(v)
682
+ for vpar in all_var:
683
+ par_drv = [QQ(diff(l, vpar)) for l in line]
684
+ par_drv = vector(par_drv)
685
+ dir_vecs.append(par_drv)
686
+
687
+ # Calculate the outgoing normal vector of each surface in the
688
+ # direction of the line
689
+ for i in line_comps[k]:
690
+ surface = self._hypersurface[i][0]
691
+ drv_vectors = []
692
+ for vpar in self._vars:
693
+ temp_vec = [QQ(diff(s, vpar)) for s in surface]
694
+ temp_vec = vector(temp_vec)
695
+ drv_vectors.append(temp_vec)
696
+ temp = [t_vars]
697
+ temp.extend(drv_vectors)
698
+ vec_matrix = matrix(SR, temp)
699
+ normal_vec = vec_matrix.det()
700
+ temp_nor = [QQ(diff(normal_vec, tvar)) for tvar in t_vars]
701
+ normal_vec = vector(temp_nor)
702
+ normal_vec *= 1/gcd(normal_vec)
703
+
704
+ # Calculate the weight vector
705
+ temp_final = [t_vars]
706
+ temp_final.extend(dir_vecs)
707
+ temp_final.append(normal_vec)
708
+ vec_matrix = matrix(SR, temp_final)
709
+ weight_vec = vec_matrix.det()
710
+ temp_weight = [QQ(diff(weight_vec, tvar)) for tvar in t_vars]
711
+ weight_vec = vector(temp_weight)
712
+ order = self._hypersurface[i][2]
713
+ weight_vec *= order
714
+ WV[k].append(weight_vec)
715
+
716
+ balance = False
717
+ for i in range(1, len(WV[k])+1):
718
+ for j in combinations(range(len(WV[k])), i):
719
+ test_vectors = list(WV[k])
720
+ for idx in j:
721
+ test_vectors[idx] = -test_vectors[idx]
722
+ if sum(test_vectors) == zero_vector(QQ, dim):
723
+ WV[k] = test_vectors
724
+ balance = True
725
+ break
726
+ if balance:
727
+ break
728
+
729
+ return index_line, line_comps, WV
730
+
731
+
732
+ class TropicalSurface(TropicalVariety):
733
+ r"""
734
+ A tropical surface in `\RR^3`.
735
+
736
+ The tropical surface consists of planar regions and facets, which we
737
+ can call cells. These cells are connected in such a way that they form
738
+ a piecewise linear structure embedded in three-dimensional space. These
739
+ cells meet along edges, where the balancing condition is satisfied.
740
+ This balancing condition ensures that the sum of the outgoing normal
741
+ vectors at each edge is zero, reflecting the equilibrium.
742
+
743
+ EXAMPLES::
744
+
745
+ sage: T = TropicalSemiring(QQ, use_min=False)
746
+ sage: R.<x,y,z> = PolynomialRing(T)
747
+ sage: p1 = x + y + z + R(0)
748
+ sage: tv = p1.tropical_variety(); tv
749
+ Tropical surface of 0*x + 0*y + 0*z + 0
750
+ sage: tv.components()
751
+ [[(t1, t1, t2), [t2 <= t1, 0 <= t1], 1],
752
+ [(t1, t2, t1), [max(0, t2) <= t1], 1],
753
+ [(0, t1, t2), [t2 <= 0, t1 <= 0], 1],
754
+ [(t1, t2, t2), [max(0, t1) <= t2], 1],
755
+ [(t1, 0, t2), [t2 <= 0, t1 <= 0], 1],
756
+ [(t1, t2, 0), [t1 <= 0, t2 <= 0], 1]]
757
+ """
758
+ def _axes(self):
759
+ r"""
760
+ Set the default axes for ``self``.
761
+
762
+ This default axes is used for the 3d plot. The axes is centered
763
+ around where the intersection of the components occurred so it
764
+ gives a nice visual representation for the interactions between
765
+ different components of the surface. Additionally, it enhances
766
+ the visibility and interpretation of how the components align
767
+ and interact in three-dimensional space.
768
+
769
+ OUTPUT:
770
+
771
+ A list of three lists, where the first inner list represent value
772
+ of x-axis, the second inner list represent value of y-axis, and
773
+ the third inner list represent value of z-axis. If there are
774
+ either no components or only one component, the axis will be set
775
+ to `[[-1, 1], [-1, 1], [-1, 1]]`.
776
+
777
+ EXAMPLES::
778
+
779
+ sage: T = TropicalSemiring(QQ)
780
+ sage: R.<x,y,z> = PolynomialRing(T)
781
+ sage: p1 = x
782
+ sage: p1.tropical_variety()._axes()
783
+ [[-1, 1], [-1, 1], [-1, 1]]
784
+ sage: p2 = x + y + z + x^2 + R(1)
785
+ sage: p2.tropical_variety()._axes()
786
+ [[-1, 2], [-1, 2], [-1, 2]]
787
+ """
788
+ from sage.arith.srange import srange
789
+ from sage.symbolic.relation import solve
790
+
791
+ if not self._hypersurface:
792
+ return [[-1, 1], [-1, 1], [-1, 1]]
793
+ elif len(self._hypersurface) == 1:
794
+ bound = 1
795
+ for eqn in self._hypersurface[0][0]:
796
+ for op in eqn.operands():
797
+ if op.is_numeric():
798
+ bound = max(op, bound)
799
+ return [[-bound, bound]] * 3
800
+
801
+ u_set = set()
802
+ v_set = set()
803
+ for comp in self._hypersurface:
804
+ list_expr = []
805
+ temp_u = set()
806
+ temp_v = set()
807
+ for expr in comp[1]:
808
+ if expr.lhs().is_numeric():
809
+ if bool(expr.rhs() == self._vars[0]):
810
+ temp_u.add(expr.lhs())
811
+ else:
812
+ temp_v.add(expr.lhs())
813
+ elif expr.rhs().is_numeric():
814
+ if bool(expr.lhs() == self._vars[0]):
815
+ temp_u.add(expr.rhs())
816
+ else:
817
+ temp_v.add(expr.rhs())
818
+ else:
819
+ list_expr.append(expr)
820
+ if not temp_u:
821
+ temp_u.add(0)
822
+ if not temp_v:
823
+ temp_v.add(0)
824
+ for expr in list_expr:
825
+ for u in temp_u:
826
+ sol = solve(expr.subs(**{str(self._vars[0]): u}), self._vars[1])
827
+ if not sol:
828
+ temp_v.add(0)
829
+ elif not sol[0]:
830
+ temp_v.add(0)
831
+ else:
832
+ temp_v.add(sol[0][0].rhs())
833
+ for v in temp_v:
834
+ sol = solve(expr.subs(**{str(self._vars[1]): v}), self._vars[0])
835
+ if not sol:
836
+ temp_u.add(0)
837
+ elif not sol[0]:
838
+ temp_u.add(0)
839
+ else:
840
+ temp_u.add(sol[0][0].rhs())
841
+ u_set = u_set.union(temp_u)
842
+ v_set = v_set.union(temp_v)
843
+ axes = [[min(u_set)-1, max(u_set)+1], [min(v_set)-1, max(v_set)+1]]
844
+
845
+ # Calculate the z-axis
846
+ step = 10
847
+ du = (axes[0][1]-axes[0][0]) / step
848
+ dv = (axes[1][1]-axes[1][0]) / step
849
+ u_range = srange(axes[0][0], axes[0][1]+du, du)
850
+ v_range = srange(axes[1][0], axes[1][1]+dv, dv)
851
+ zmin, zmax = None, None
852
+ for comp in self._hypersurface:
853
+ for u in u_range:
854
+ for v in v_range:
855
+ checkpoint = True
856
+ for exp in comp[1]:
857
+ final_exp = exp.subs(**{str(self._vars[0]): u, str(self._vars[1]): v})
858
+ if not final_exp:
859
+ checkpoint = False
860
+ break
861
+ if checkpoint:
862
+ z = comp[0][2].subs(**{str(self._vars[0]): u, str(self._vars[1]): v})
863
+ if (zmin is None) and (zmax is None):
864
+ zmin = z
865
+ zmax = z
866
+ else:
867
+ zmin = min(z, zmin)
868
+ zmax = max(z, zmax)
869
+ axes.append([zmin, zmax])
870
+ return axes
871
+
872
+ def _polygon_vertices(self):
873
+ r"""
874
+ Return the vertices of the polygon for each components of ``self``
875
+ to be used for plotting.
876
+
877
+ OUTPUT:
878
+
879
+ A dictionary where the keys represent component indices and the
880
+ values are a set of points in three dimensional space.
881
+
882
+ EXAMPLES:
883
+
884
+ A tropical surface with only one component::
885
+
886
+ sage: T = TropicalSemiring(QQ)
887
+ sage: R.<x,y,z> = PolynomialRing(T)
888
+ sage: p1 = x + z
889
+ sage: tv1 = p1.tropical_variety()
890
+ sage: tv1._polygon_vertices()
891
+ {0: {(-1, -1, -1), (-1, 1, -1), (1, -1, 1), (1, 1, 1)}}
892
+
893
+ A tropical surface with multiple components::
894
+
895
+ sage: p2 = x^2 + x + y + z + R(1)
896
+ sage: tv2 = p2.tropical_variety()
897
+ sage: tv2._polygon_vertices() # long time
898
+ {0: {(0, 0, 0), (0, 0, 2), (1, 1, 1), (2, 2, 2)},
899
+ 1: {(0, 0, 0), (0, 2, 0), (1, 1, 1), (2, 2, 2)},
900
+ 2: {(0, 0, 0), (0, 0, 2), (0, 2, 0), (0, 2, 2)},
901
+ 3: {(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2)},
902
+ 4: {(-1/2, -1, -1), (0, 0, 0), (1, 1, 1), (2, -1, -1), (2, 1, 1)},
903
+ 5: {(-1/2, -1, -1), (-1/2, -1, 2), (0, 0, 0), (0, 0, 2)},
904
+ 6: {(1, 1, 1), (1, 1, 2), (2, 1, 1), (2, 1, 2)},
905
+ 7: {(-1/2, -1, -1), (-1/2, 2, -1), (0, 0, 0), (0, 2, 0)},
906
+ 8: {(1, 1, 1), (1, 2, 1), (2, 1, 1), (2, 2, 1)}}
907
+ """
908
+ from sage.sets.real_set import RealSet
909
+ from sage.symbolic.relation import solve
910
+
911
+ poly_verts = {i: set() for i in range(self.number_of_components())}
912
+ axes = self._axes()
913
+ comps = self.components()
914
+ vars = self._vars
915
+ comps_int = self._components_intersection()
916
+
917
+ # Find the inside vertices (intersection of components)
918
+ for index, lines in comps_int.items():
919
+ for line in lines:
920
+ v = list(line[1])[0].variables()[0]
921
+ for param in line[1]:
922
+ left = param.lhs()
923
+ right = param.rhs()
924
+ if left.is_numeric():
925
+ vertex = [QQ(e.subs(**{str(v): left})) for e in line[0]]
926
+ poly_verts[index].add(tuple(vertex))
927
+ elif right.is_numeric():
928
+ vertex = [QQ(e.subs(**{str(v): right})) for e in line[0]]
929
+ poly_verts[index].add(tuple(vertex))
930
+
931
+ def find_edge_vertices(i):
932
+ j = (i+1) % 2
933
+ if i == 0: # interval for t1
934
+ interval = interval1
935
+ else: # interval for t2
936
+ interval = interval2
937
+ for p in [interval.inf(), interval.sup()]:
938
+ new_param = [e.subs(**{str(vars[i]): p}) for e in comps[index][1]]
939
+ sol = solve(new_param, vars[j])
940
+ if sol:
941
+ interval_param = RealSet()
942
+ for s in sol:
943
+ if s != []:
944
+ # Handle cases where 's' is not a list (s = r1 < +Infinity),
945
+ # or if 's' is a list, ensure that its elements define a real
946
+ # interval (catch invalid cases like s = [t1 == r100]).
947
+ try:
948
+ interval_param += RealSet(s[0])
949
+ except (IndexError, ValueError):
950
+ interval_param += RealSet(-infinity, infinity)
951
+ else:
952
+ interval_param += RealSet(-infinity, infinity)
953
+ interval_param = interval_param.intersection(interval2)
954
+ if is_doublevar:
955
+ int1 = RealSet()
956
+ for s1 in sol1:
957
+ subs1 = solve(s1[0].subs(**{str(vars[i]): p}), vars[j])
958
+ try:
959
+ int1 += RealSet(subs1[0])
960
+ except TypeError:
961
+ int1 += RealSet(subs1[0][0])
962
+ int2 = RealSet()
963
+ for s2 in sol2:
964
+ subs2 = solve(s2[0].subs(**{str(vars[i]): p}), vars[j])
965
+ try:
966
+ int2 += RealSet(subs2[0])
967
+ except TypeError:
968
+ int2 += RealSet(subs2[0][0])
969
+ final_int = int1.intersection(int2)
970
+ interval_param = interval_param.intersection(final_int)
971
+ if interval_param:
972
+ vertex1 = [QQ(e.subs(**{str(vars[i]): p, str(vars[j]): interval_param.inf()})) for e in comps[index][0]]
973
+ vertex2 = [QQ(e.subs(**{str(vars[i]): p, str(vars[j]): interval_param.sup()})) for e in comps[index][0]]
974
+ poly_verts[index].add(tuple(vertex1))
975
+ poly_verts[index].add(tuple(vertex2))
976
+
977
+ # Find the interval of parameter for outer vertex
978
+ for index in range(len(comps)):
979
+ interval1 = RealSet(-infinity, infinity) # represent t1
980
+ interval2 = RealSet(-infinity, infinity) # represent t2
981
+ is_doublevar = False
982
+ for i, point in enumerate(comps[index][0]):
983
+ pv = point.variables()
984
+ if len(pv) == 1:
985
+ temp1 = RealSet(solve(point >= axes[i][0], pv[0])[0][0])
986
+ temp2 = RealSet(solve(point <= axes[i][1], pv[0])[0][0])
987
+ temp = temp1.intersection(temp2)
988
+ if pv[0] == vars[0]:
989
+ interval1 = interval1.intersection(temp)
990
+ else:
991
+ interval2 = interval2.intersection(temp)
992
+ elif len(pv) == 2:
993
+ sol1 = solve(point >= axes[i][0], pv)
994
+ sol2 = solve(point <= axes[i][1], pv)
995
+ is_doublevar = True
996
+
997
+ # Find the edge vertices (those that touch the axes)
998
+ find_edge_vertices(0) # t1 fixed
999
+ find_edge_vertices(1) # t2 fixed
1000
+ return poly_verts
1001
+
1002
+ def plot(self, color='random'):
1003
+ """
1004
+ Return the plot of ``self`` by constructing a polyhedron from
1005
+ vertices in ``self.polygon_vertices()``.
1006
+
1007
+ INPUT:
1008
+
1009
+ - ``color`` -- string or tuple that represent a color (default:
1010
+ ``random``); ``random`` means each polygon will be assigned
1011
+ a different color. If instead a specific ``color`` is provided,
1012
+ then all polygon will be given the same color.
1013
+
1014
+ OUTPUT: Graphics3d Object
1015
+
1016
+ EXAMPLES:
1017
+
1018
+ A tropical surface that consist of only one cell::
1019
+
1020
+ sage: T = TropicalSemiring(QQ)
1021
+ sage: R.<x,y,z> = PolynomialRing(T)
1022
+ sage: p1 = x + z
1023
+ sage: tv = p1.tropical_variety()
1024
+ sage: tv.plot() # needs sage.plot
1025
+ Graphics3d Object
1026
+
1027
+ .. PLOT::
1028
+ :width: 300 px
1029
+
1030
+ T = TropicalSemiring(QQ)
1031
+ R = PolynomialRing(T, ('x,y,z'))
1032
+ x, y, z = R.gen(), R.gen(1), R.gen(2)
1033
+ p1 = x + z
1034
+ sphinx_plot(p1.tropical_variety().plot())
1035
+
1036
+ A tropical surface with multiple cells that exhibit complex and
1037
+ intriguing geometric structures::
1038
+
1039
+ sage: p2 = x^2 + x + y + z + R(1)
1040
+ sage: tv = p2.tropical_variety()
1041
+ sage: tv.plot() # long time # needs sage.plot
1042
+ Graphics3d Object
1043
+
1044
+ .. PLOT::
1045
+ :width: 300 px
1046
+
1047
+ T = TropicalSemiring(QQ)
1048
+ R = PolynomialRing(T, ('x,y,z'))
1049
+ x, y, z = R.gen(), R.gen(1), R.gen(2)
1050
+ p2 = x**2 + x + y + z + R(1)
1051
+ sphinx_plot(p2.tropical_variety().plot())
1052
+ """
1053
+ from random import random
1054
+
1055
+ from sage.geometry.polyhedron.constructor import Polyhedron
1056
+ from sage.plot.graphics import Graphics
1057
+
1058
+ if color == 'random':
1059
+ colors = []
1060
+ for _ in range(self.number_of_components()):
1061
+ color = (random(), random(), random())
1062
+ colors.append(color)
1063
+ elif isinstance(color, str):
1064
+ colors = [color] * self.number_of_components()
1065
+ else:
1066
+ colors = color
1067
+
1068
+ combined_plot = Graphics()
1069
+ for i, vertex in self._polygon_vertices().items():
1070
+ points = list(vertex)
1071
+ plot = Polyhedron(vertices=points).plot(color=colors[i])
1072
+ combined_plot += plot
1073
+ return combined_plot
1074
+
1075
+ def _repr_(self):
1076
+ """
1077
+ Return a string representation of ``self``.
1078
+
1079
+ EXAMPLES::
1080
+
1081
+ sage: T = TropicalSemiring(QQ)
1082
+ sage: R.<x,y,z> = PolynomialRing(T)
1083
+ sage: (x^4+z^2).tropical_variety()
1084
+ Tropical surface of 0*x^4 + 0*z^2
1085
+ """
1086
+ return f"Tropical surface of {self._poly}"
1087
+
1088
+
1089
+ class TropicalCurve(TropicalVariety):
1090
+ r"""
1091
+ A tropical curve in `\RR^2`.
1092
+
1093
+ The tropical curve consists of line segments and half-lines, which we
1094
+ call edges. These edges are connected in such a way that they form a
1095
+ piecewise linear graph embedded in the plane. These edges meet at
1096
+ a vertices, where the balancing condition is satisfied. This balancing
1097
+ condition ensures that the sum of the outgoing slopes at each vertex
1098
+ is zero, reflecting the equilibrium.
1099
+
1100
+ EXAMPLES:
1101
+
1102
+ We define some tropical curves::
1103
+
1104
+ sage: T = TropicalSemiring(QQ, use_min=False)
1105
+ sage: R.<x,y> = PolynomialRing(T)
1106
+ sage: p1 = x + y + R(0)
1107
+ sage: tv1 = p1.tropical_variety(); tv1
1108
+ Tropical curve of 0*x + 0*y + 0
1109
+ sage: tv1.components()
1110
+ [[(t1, t1), [t1 >= 0], 1], [(0, t1), [t1 <= 0], 1], [(t1, 0), [t1 <= 0], 1]]
1111
+ sage: tv1.plot() # needs sage.plot
1112
+ Graphics object consisting of 3 graphics primitives
1113
+
1114
+ .. PLOT::
1115
+ :width: 300 px
1116
+
1117
+ T = TropicalSemiring(QQ, use_min=False)
1118
+ R = PolynomialRing(T, ('x,y'))
1119
+ x, y = R.gen(), R.gen(1)
1120
+ p1 = x + y + R(0)
1121
+ sphinx_plot(p1.tropical_variety().plot())
1122
+
1123
+ ::
1124
+
1125
+ sage: p2 = R(-2)*x^2 + R(-1)*x + R(1/2)*y + R(1/6)
1126
+ sage: tv2 = p2.tropical_variety()
1127
+ sage: tv2.components()
1128
+ [[(1/2*t1 + 5/4, t1), [(-1/3) <= t1], 1],
1129
+ [(13/12, t1), [t1 <= (-1/3)], 2],
1130
+ [(t1, -1/3), [t1 <= (13/12)], 1]]
1131
+ sage: tv2.plot() # needs sage.plot
1132
+ Graphics object consisting of 4 graphics primitives
1133
+
1134
+ .. PLOT::
1135
+ :width: 300 px
1136
+
1137
+ T = TropicalSemiring(QQ, use_min=False)
1138
+ R = PolynomialRing(T, ('x,y'))
1139
+ x, y = R.gen(), R.gen(1)
1140
+ p2 = R(-2)*x**2 + R(-1)*x + R(1/2)*y + R(1/6)
1141
+ sphinx_plot(p2.tropical_variety().plot())
1142
+
1143
+ When two tropical polynomials are multiplied, the tropical curve of
1144
+ the resulting polynomial is the union of the tropical curves of the
1145
+ original polynomials::
1146
+
1147
+ sage: p3 = p1 * p2; p3
1148
+ (-2)*x^3 + (-2)*x^2*y + (-1)*x^2 + 1/2*x*y + 1/2*y^2 + 1/6*x + 1/2*y + 1/6
1149
+ sage: tv3 = p3.tropical_variety()
1150
+ sage: tv3.plot() # needs sage.plot
1151
+ Graphics object consisting of 11 graphics primitives
1152
+
1153
+ .. PLOT::
1154
+ :width: 300 px
1155
+
1156
+ T = TropicalSemiring(QQ, use_min=False)
1157
+ R = PolynomialRing(T, ('x,y'))
1158
+ x, y = R.gen(), R.gen(1)
1159
+ p1 = x + y + R(0)
1160
+ p2 = R(-2)*x**2 + R(-1)*x + R(1/2)*y + R(1/6)
1161
+ p3 = p1 * p2
1162
+ sphinx_plot(p3.tropical_variety().plot())
1163
+ """
1164
+ def _axes(self):
1165
+ """
1166
+ Set the default axes for ``self``.
1167
+
1168
+ This default axes is used for plot of tropical curve and also the
1169
+ 3d plot of tropical polynomial function. The axes is chosen by first
1170
+ find all vertices of this tropical curve. Then we choose the minimum
1171
+ and maximum of all x-component in this vertices to be the x-axis.
1172
+ The same apply to the y-axis.
1173
+
1174
+ OUTPUT:
1175
+
1176
+ A list of two lists, where the first inner list represent value of
1177
+ x-axis and the second inner list represent value of y-axis.
1178
+
1179
+ EXAMPLES::
1180
+
1181
+ sage: T = TropicalSemiring(QQ)
1182
+ sage: R.<x,y> = PolynomialRing(T)
1183
+ sage: p1 = x^2
1184
+ sage: p1.tropical_variety()._axes()
1185
+ [[-1, 1], [-1, 1]]
1186
+ sage: p2 = R(12)*x*y + R(-2)*y^2 + R(16)*y + R(25)
1187
+ sage: p2.tropical_variety()._axes()
1188
+ [[-3/2, 1/2], [25/2, 29/2]]
1189
+ """
1190
+ if self.number_of_components() == 0:
1191
+ return [[-1, 1], [-1, 1]]
1192
+ if self.number_of_components() <= 2:
1193
+ bound = 1
1194
+ for comps in self._hypersurface:
1195
+ eqns = comps[0]
1196
+ temp_operands = []
1197
+ for eq in eqns:
1198
+ if not eq.operator():
1199
+ temp_operands.append(eq)
1200
+ else:
1201
+ temp_operands += eq.operands()
1202
+ for op in temp_operands:
1203
+ if op.is_numeric():
1204
+ bound = max(abs(op), bound)
1205
+ return [[-bound, bound]] * 2
1206
+
1207
+ verts = self.vertices()
1208
+ xmin = xmax = list(verts)[0][0]
1209
+ for vertex in verts:
1210
+ if vertex[0] < xmin:
1211
+ xmin = vertex[0]
1212
+ elif vertex[0] > xmax:
1213
+ xmax = vertex[0]
1214
+ ymin = ymax = list(verts)[0][1]
1215
+ for vertex in verts:
1216
+ if vertex[1] < ymin:
1217
+ ymin = vertex[1]
1218
+ elif vertex[1] > ymax:
1219
+ ymax = vertex[1]
1220
+ return [[xmin-1, xmax+1], [ymin-1, ymax+1]]
1221
+
1222
+ def vertices(self):
1223
+ r"""
1224
+ Return all vertices of ``self``, which is the point where three or
1225
+ more edges intersect.
1226
+
1227
+ OUTPUT: a set of `(x,y)` points
1228
+
1229
+ EXAMPLES::
1230
+
1231
+ sage: T = TropicalSemiring(QQ)
1232
+ sage: R.<x,y> = PolynomialRing(T)
1233
+ sage: p1 = x + y
1234
+ sage: p1.tropical_variety().vertices()
1235
+ set()
1236
+ sage: p2 = R(-2)*x^2 + R(-1)*x + R(1/2)*y + R(1/6)
1237
+ sage: p2.tropical_variety().vertices()
1238
+ {(1, -1/2), (7/6, -1/3)}
1239
+ """
1240
+ if len(self._hypersurface) < 3:
1241
+ return set()
1242
+ return set(self._vertices_components().keys())
1243
+
1244
+ def _vertices_components(self):
1245
+ """
1246
+ Return the index of components adjacent to each vertex of ``self``.
1247
+
1248
+ OUTPUT:
1249
+
1250
+ A dictionary where the keys represent the vertices, and the
1251
+ values are lists of tuples. Each tuple consists of the index
1252
+ of an adjacent edge (component) `e_i` and a number indicating
1253
+ the directionality of `e_i` relative to the vertex. The number
1254
+ is either -1 or 1.
1255
+
1256
+ EXAMPLES::
1257
+
1258
+ sage: T = TropicalSemiring(QQ)
1259
+ sage: R.<x,y> = PolynomialRing(T)
1260
+ sage: p1 = R(0) + x + y + x*y + x^2*y + x*y^2
1261
+ sage: p1.tropical_variety()._vertices_components()
1262
+ {(0, 0): [(0, 1), (1, 1), (2, 1), (3, -1), (4, -1)]}
1263
+ sage: p2 = R(2)*x^2 + x*y + R(2)*y^2 + x + R(-1)*y + R(3)
1264
+ sage: p2.tropical_variety()._vertices_components()
1265
+ {(-2, 0): [(0, -1), (1, 1), (3, 1)],
1266
+ (-1, -3): [(2, -1), (4, 1), (5, 1)],
1267
+ (-1, 0): [(3, -1), (4, -1), (6, 1)],
1268
+ (3, 4): [(6, -1), (7, 1), (8, 1)]}
1269
+ """
1270
+ comp_vert = {}
1271
+ if len(self._hypersurface) >= 3:
1272
+ for i, component in enumerate(self._hypersurface):
1273
+ parametric_function = component[0]
1274
+ v = component[1][0].variables()[0]
1275
+ interval = self._parameter_intervals()[i]
1276
+ lower = interval[0].lower()
1277
+ upper = interval[0].upper()
1278
+ if lower != -infinity:
1279
+ x = parametric_function[0].subs(**{str(v): lower})
1280
+ y = parametric_function[1].subs(**{str(v): lower})
1281
+ if (x, y) not in comp_vert:
1282
+ comp_vert[(x, y)] = [(i, 1)]
1283
+ else:
1284
+ comp_vert[(x, y)].append((i, 1))
1285
+ if upper != infinity:
1286
+ x = parametric_function[0].subs(**{str(v): upper})
1287
+ y = parametric_function[1].subs(**{str(v): upper})
1288
+ if (x, y) not in comp_vert:
1289
+ comp_vert[(x, y)] = [(i, -1)]
1290
+ else:
1291
+ comp_vert[(x, y)].append((i, -1))
1292
+ return comp_vert
1293
+
1294
+ def weight_vectors(self):
1295
+ r"""
1296
+ Return the weight vectors for all vertices of ``self``.
1297
+
1298
+ Weight vectors are a list of vectors associated with each vertex
1299
+ of the curve. Each vector corresponds to an edge emanating from
1300
+ that vertex and points in the direction of the edge.
1301
+
1302
+ Suppose `v` is a vertex adjacent to the edges `e_1, \ldots, e_k`
1303
+ with respective weights `w_1, \ldots, w_k`. Every edge `e_i` is
1304
+ contained in a line (component) defined by an equation. Therefore,
1305
+ there exists a unique integer vector `v_i = (\alpha, \beta)` in
1306
+ the direction of `e_i` such that `\gcd(\alpha, \beta)=1`. Then,
1307
+ each vertex `v` yield the vectors `w_1 v_1, \ldots, w_k v_k`.
1308
+ These vectors will satisfy the following balancing condition:
1309
+ `\sum_{i=1}^k w_i v_i = 0`.
1310
+
1311
+ OUTPUT:
1312
+
1313
+ A dictionary where the keys represent the vertices, and the values
1314
+ are lists of vectors.
1315
+
1316
+ EXAMPLES::
1317
+
1318
+ sage: T = TropicalSemiring(QQ)
1319
+ sage: R.<x,y> = PolynomialRing(T)
1320
+ sage: p1 = R(-2)*x^2 + R(-1)*x + R(1/2)*y + R(1/6)
1321
+ sage: p1.tropical_variety().weight_vectors()
1322
+ {(1, -1/2): [(0, 1), (-1, -2), (1, 1)],
1323
+ (7/6, -1/3): [(-1, -1), (0, 1), (1, 0)]}
1324
+
1325
+ sage: p2 = R(2)*x^2 + x*y + R(2)*y^2 + x + R(-1)*y + R(3)
1326
+ sage: p2.tropical_variety().weight_vectors()
1327
+ {(-2, 0): [(-1, -1), (0, 1), (1, 0)],
1328
+ (-1, -3): [(-1, -1), (0, 1), (1, 0)],
1329
+ (-1, 0): [(-1, 0), (0, -1), (1, 1)],
1330
+ (3, 4): [(-1, -1), (0, 1), (1, 0)]}
1331
+ """
1332
+ from sage.arith.misc import gcd
1333
+ from sage.calculus.functional import diff
1334
+ from sage.modules.free_module_element import vector
1335
+
1336
+ if not self._vertices_components():
1337
+ return {}
1338
+
1339
+ # Calculate the base vector in the direction of each edge
1340
+ temp_vectors = []
1341
+ par = self._hypersurface[0][1][0].variables()[0]
1342
+ for comp in self._hypersurface:
1343
+ dx = diff(comp[0][0], par)
1344
+ dy = diff(comp[0][1], par)
1345
+ multiplier = gcd(QQ(dx), QQ(dy))
1346
+ temp_vectors.append(vector([dx/multiplier, dy/multiplier]))
1347
+
1348
+ # Calculate the weight vectors of each vertex
1349
+ cov = self._vertices_components()
1350
+ result = {}
1351
+ for vertex in cov:
1352
+ vectors = []
1353
+ for comp in cov[vertex]:
1354
+ weight = self._hypersurface[comp[0]][2]
1355
+ vectors.append(weight*comp[1]*temp_vectors[comp[0]])
1356
+ result[vertex] = vectors
1357
+ return result
1358
+
1359
+ def is_smooth(self):
1360
+ r"""
1361
+ Return ``True`` if ``self`` is smooth and ``False`` otherwise.
1362
+
1363
+ Suppose `C` is a tropical curve of degree `d`. A tropical curve
1364
+ `C` is smooth if the dual subdivision of `C` consists of `d^2`
1365
+ triangles each having unit area `1/2`. This is equivalent with
1366
+ `C` having `d^2` vertices. These vertices are necessarily
1367
+ trivalent (has three adjacent edges).
1368
+
1369
+ EXAMPLES::
1370
+
1371
+ sage: T = TropicalSemiring(QQ)
1372
+ sage: R.<x,y> = PolynomialRing(T)
1373
+ sage: p1 = x^2 + x + R(1)
1374
+ sage: p1.tropical_variety().is_smooth()
1375
+ False
1376
+ sage: p2 = R(2)*x^2 + x*y + R(2)*y^2 + x + R(-1)*y + R(3)
1377
+ sage: p2.tropical_variety().is_smooth()
1378
+ True
1379
+ """
1380
+ return len(self.vertices()) == self._poly.degree() ** 2
1381
+
1382
+ def is_simple(self):
1383
+ r"""
1384
+ Return ``True`` if ``self`` is simple and ``False`` otherwise.
1385
+
1386
+ A tropical curve `C` is called simple if each vertex is either
1387
+ trivalent or is locally the intersection of two line segments.
1388
+ Equivalently, `C` is simple if the corresponding subdivision
1389
+ consists only of triangles and parallelograms.
1390
+
1391
+ EXAMPLES::
1392
+
1393
+ sage: T = TropicalSemiring(QQ)
1394
+ sage: R.<x,y> = PolynomialRing(T)
1395
+ sage: p1 = R(0) + x + y + x*y + x^2*y + x*y^2
1396
+ sage: p1.tropical_variety().is_simple()
1397
+ False
1398
+ sage: p2 = R(2)*x^2 + x*y + R(2)*y^2 + x + R(-1)*y + R(3)
1399
+ sage: p2.tropical_variety().is_simple()
1400
+ True
1401
+ """
1402
+ vov = self.weight_vectors()
1403
+ for vertex in self.vertices():
1404
+ if len(vov[vertex]) > 4:
1405
+ return False
1406
+ if len(vov[vertex]) == 4:
1407
+ if any(-v not in vov[vertex] for v in vov[vertex]):
1408
+ return False
1409
+ return True
1410
+
1411
+ def genus(self):
1412
+ r"""
1413
+ Return the genus of ``self``.
1414
+
1415
+ Let `t(C)` be the number of trivalent vertices, and let `r(C)` be
1416
+ the number of unbounded edges of `C`. The genus of simple tropical
1417
+ curve `C` is defined by the formula:
1418
+
1419
+ .. MATH::
1420
+
1421
+ g(C) = \frac{1}{2}t(C) - \frac{1}{2}r(C) + 1.
1422
+
1423
+ EXAMPLES::
1424
+
1425
+ sage: T = TropicalSemiring(QQ)
1426
+ sage: R.<x,y> = PolynomialRing(T)
1427
+ sage: p1 = x^2 + y^2 + x*y
1428
+ sage: p1.tropical_variety().genus()
1429
+ 1
1430
+ sage: p2 = R(2)*x^2 + x*y + R(2)*y^2 + x + R(-1)*y + R(3)
1431
+ sage: p2.tropical_variety().genus()
1432
+ 0
1433
+
1434
+ TESTS::
1435
+
1436
+ sage: T = TropicalSemiring(QQ)
1437
+ sage: R.<x,y> = PolynomialRing(T)
1438
+ sage: p1 = R(0) + y + x^2*y + x*y^2
1439
+ sage: p1.tropical_variety().genus()
1440
+ Traceback (most recent call last):
1441
+ ...
1442
+ ValueError: Tropical curve of 0*x^2*y + 0*x*y^2 + 0*y + 0 is not simple
1443
+ """
1444
+ if not self.is_simple():
1445
+ raise ValueError(f"{self} is not simple")
1446
+ trivalent = 0 # number of trivalent vertices
1447
+ for vectors in self.weight_vectors().values():
1448
+ if len(vectors) == 3:
1449
+ trivalent += 1
1450
+ unbounded = 0 # number of unbounded edges
1451
+ for component in self._hypersurface:
1452
+ if len(component[1]) == 1:
1453
+ unbounded += 1
1454
+ return trivalent//2 - unbounded//2 + 1
1455
+
1456
+ def contribution(self):
1457
+ r"""
1458
+ Return the contribution of ``self``.
1459
+
1460
+ The contribution of a simple curve `C` is defined as the product
1461
+ of the normalized areas of all triangles in the corresponding
1462
+ dual subdivision. We just multiply positive integers attached to
1463
+ the trivalent vertices. The contribution of a trivalent vertex
1464
+ equals `w_1w_2|\det(v_1,v_2)|`, with `w_i` are the weights of
1465
+ the adjacent edges and `v_i` are their weight vectors. That
1466
+ formula is independent of the choice made because of the
1467
+ balancing condition `w_1v_1+w_2v_2+w_3v_3=0`.
1468
+
1469
+ EXAMPLES::
1470
+
1471
+ sage: T = TropicalSemiring(QQ)
1472
+ sage: R.<x,y> = PolynomialRing(T)
1473
+ sage: p1 = R(2)*x^2 + x*y + R(2)*y^2 + x + R(-1)*y + R(3)
1474
+ sage: p1.tropical_variety().contribution()
1475
+ 1
1476
+ sage: p2 = R(-1/3)*x^2 + R(1)*x*y + R(1)*y^2 + R(-1/3)*x + R(1/3)
1477
+ sage: p2.tropical_variety().contribution()
1478
+ 16
1479
+
1480
+ TESTS::
1481
+
1482
+ sage: T = TropicalSemiring(QQ)
1483
+ sage: R.<x,y> = PolynomialRing(T)
1484
+ sage: p1 = R(0) + x + x^2*y + x*y^2
1485
+ sage: p1.tropical_variety().contribution()
1486
+ Traceback (most recent call last):
1487
+ ...
1488
+ ValueError: Tropical curve of 0*x^2*y + 0*x*y^2 + 0*x + 0 is not simple
1489
+ """
1490
+ if not self.is_simple():
1491
+ raise ValueError(f"{self} is not simple")
1492
+ result = 1
1493
+ voc = self._vertices_components()
1494
+ vov = self.weight_vectors()
1495
+ for vertex in vov:
1496
+ if len(vov[vertex]) == 3:
1497
+ u1 = vov[vertex][0]
1498
+ u2 = vov[vertex][1]
1499
+ index1 = voc[vertex][0][0]
1500
+ index2 = voc[vertex][1][0]
1501
+ w1 = self._hypersurface[index1][2]
1502
+ w2 = self._hypersurface[index2][2]
1503
+ det = u1[0]*u2[1] - u1[1]*u2[0]
1504
+ result *= w1 * w2 * abs(det)
1505
+ return result
1506
+
1507
+ def _parameter_intervals(self):
1508
+ r"""
1509
+ Return the intervals of each component's parameter of ``self``.
1510
+
1511
+ OUTPUT: a list of ``RealSet``
1512
+
1513
+ EXAMPLES::
1514
+
1515
+ sage: T = TropicalSemiring(QQ)
1516
+ sage: R.<x,y> = PolynomialRing(T)
1517
+ sage: p1 = y + y^2
1518
+ sage: p1.tropical_variety()._parameter_intervals()
1519
+ [(-oo, +oo)]
1520
+ sage: p2 = x^2 + R(-1)*x*y + R(-1)*x + R(1/3)
1521
+ sage: p2.tropical_variety()._parameter_intervals()
1522
+ [(-oo, 0], [0, +oo), [-1, 4/3], (-oo, 0], [0, +oo)]
1523
+ """
1524
+ from sage.sets.real_set import RealSet
1525
+
1526
+ intervals = []
1527
+ R = self._poly.parent().base().base_ring()
1528
+ for component in self._hypersurface:
1529
+ if len(component[1]) == 1:
1530
+ interval = RealSet(component[1][0])
1531
+ else:
1532
+ lower = component[1][0].left()
1533
+ upper = component[1][1].right()
1534
+ if lower == -infinity:
1535
+ interval = RealSet(-infinity, infinity)
1536
+ else:
1537
+ interval = RealSet([R(lower), R(upper)])
1538
+ intervals.append(interval)
1539
+ return intervals
1540
+
1541
+ def plot(self):
1542
+ """
1543
+ Return the plot of ``self``.
1544
+
1545
+ Generates a visual representation of the tropical curve in cartesian
1546
+ coordinates. The plot shows piecewise-linear segments representing
1547
+ each components. The axes are centered around the vertices.
1548
+
1549
+ OUTPUT:
1550
+
1551
+ A Graphics object. The weight of the component will be written if it
1552
+ is greater or equal than 2. The weight is written near the vertex.
1553
+
1554
+ EXAMPLES:
1555
+
1556
+ A polynomial with only two terms will give one straight line::
1557
+
1558
+ sage: T = TropicalSemiring(QQ)
1559
+ sage: R.<x,y> = PolynomialRing(T)
1560
+ sage: (y+R(1)).tropical_variety().components()
1561
+ [[(t1, 1), [-Infinity < t1, t1 < +Infinity], 1]]
1562
+ sage: (y+R(1)).tropical_variety().plot() # needs sage.plot
1563
+ Graphics object consisting of 1 graphics primitive
1564
+
1565
+ .. PLOT::
1566
+ :width: 300 px
1567
+
1568
+ T = TropicalSemiring(QQ)
1569
+ R = PolynomialRing(T, ('x,y'))
1570
+ x, y = R.gen(), R.gen(1)
1571
+ sphinx_plot((y+R(1)).tropical_variety().plot())
1572
+
1573
+ An intriguing and fascinating tropical curve can be obtained with
1574
+ a more complex tropical polynomial::
1575
+
1576
+ sage: p1 = R(1) + R(2)*x + R(3)*y + R(6)*x*y + R(10)*x*y^2
1577
+ sage: p1.tropical_variety().components()
1578
+ [[(-1, t1), [-2 <= t1], 1],
1579
+ [(t1, -2), [-1 <= t1], 1],
1580
+ [(t1 + 1, t1), [-4 <= t1, t1 <= -2], 1],
1581
+ [(t1, -4), [t1 <= -3], 2],
1582
+ [(-t1 - 7, t1), [t1 <= -4], 1]]
1583
+ sage: p1.tropical_variety().plot() # needs sage.plot
1584
+ Graphics object consisting of 6 graphics primitives
1585
+
1586
+ .. PLOT::
1587
+ :width: 300 px
1588
+
1589
+ T = TropicalSemiring(QQ)
1590
+ R = PolynomialRing(T, ('x,y'))
1591
+ x, y = R.gen(), R.gen(1)
1592
+ p1 = R(1) + R(2)*x + R(3)*y + R(6)*x*y + R(10)*x*y**2
1593
+ sphinx_plot(p1.tropical_variety().plot())
1594
+
1595
+ Another tropical polynomial with numerous components, resulting
1596
+ in a more intricate structure::
1597
+
1598
+ sage: p2 = (x^6 + R(4)*x^4*y^2 + R(2)*x^3*y^3 + R(3)*x^2*y^4
1599
+ ....: + x*y^5 + R(7)*x^2 + R(5)*x*y + R(3)*y^2 + R(2)*x
1600
+ ....: + y + R(10))
1601
+ sage: p2.tropical_variety().plot() # long time # needs sage.plot
1602
+ Graphics object consisting of 11 graphics primitives
1603
+
1604
+ .. PLOT::
1605
+ :width: 300 px
1606
+
1607
+ T = TropicalSemiring(QQ)
1608
+ R = PolynomialRing(T, ('x,y'))
1609
+ x, y = R.gen(), R.gen(1)
1610
+ p2 = (x**6 + R(4)*x**4*y**2 + R(2)*x**3*y**3 + R(3)*x**2*y**4
1611
+ + x*y**5 + R(7)*x**2 + R(5)*x*y + R(3)*y**2 + R(2)*x
1612
+ + y + R(10))
1613
+ sphinx_plot(p2.tropical_variety().plot())
1614
+
1615
+ ::
1616
+
1617
+ sage: p3 = (R(8) + R(4)*x + R(2)*y + R(1)*x^2 + x*y + R(1)*y^2
1618
+ ....: + R(2)*x^3 + x^2*y + x*y^2 + R(4)*y^3 + R(8)*x^4
1619
+ ....: + R(4)*x^3*y + x^2*y^2 + R(2)*x*y^3 + y^4)
1620
+ sage: p3.tropical_variety().plot() # long time
1621
+ Graphics object consisting of 23 graphics primitives
1622
+
1623
+ .. PLOT::
1624
+ :width: 300 px
1625
+
1626
+ T = TropicalSemiring(QQ)
1627
+ R = PolynomialRing(T, ('x,y'))
1628
+ x, y = R.gen(), R.gen(1)
1629
+ p3 = (R(8) + R(4)*x + R(2)*y + R(1)*x**2 + x*y + R(1)*y**2
1630
+ + R(2)*x**3 + x**2*y + x*y**2 + R(4)*y**3 + R(8)*x**4
1631
+ + R(4)*x**3*y + x**2*y**2 + R(2)*x*y**3 + y**4)
1632
+ sphinx_plot(p3.tropical_variety().plot())
1633
+ """
1634
+ from sage.plot.graphics import Graphics
1635
+ from sage.plot.plot import parametric_plot, plot
1636
+ from sage.plot.text import text
1637
+
1638
+ if not self._hypersurface:
1639
+ return plot(lambda x: float('nan'), {-1, 1})
1640
+
1641
+ combined_plot = Graphics()
1642
+ large_int = 100
1643
+ intervals = self._parameter_intervals()
1644
+ for i, component in enumerate(self._hypersurface):
1645
+ var = component[1][0].variables()[0]
1646
+ parametric_function = component[0]
1647
+ order = component[2]
1648
+ interval = intervals[i]
1649
+ if interval[0].lower() == -infinity:
1650
+ lower = interval[0].upper() - large_int
1651
+ upper = interval[0].upper()
1652
+ midpoint = upper - 0.5
1653
+ elif interval[0].upper() == infinity:
1654
+ lower = interval[0].lower()
1655
+ upper = interval[0].lower() + large_int
1656
+ midpoint = lower + 0.5
1657
+ else:
1658
+ lower = interval[0].lower()
1659
+ upper = interval[0].upper()
1660
+ midpoint = (lower+upper) / 2
1661
+
1662
+ if (lower == infinity) and (upper == infinity):
1663
+ midpoint = 0
1664
+ plot = parametric_plot(parametric_function, (var, -large_int,
1665
+ large_int), color='red')
1666
+ else:
1667
+ plot = parametric_plot(parametric_function, (var, lower, upper),
1668
+ color='red')
1669
+
1670
+ # Add the order if it is greater than or equal to 2
1671
+ if component[2] > 1:
1672
+ point = []
1673
+ for eq in component[0]:
1674
+ value = eq.subs(**{str(var): midpoint})
1675
+ point.append(value)
1676
+ text_order = text(str(order), (point[0], point[1]),
1677
+ fontsize=16, color='black')
1678
+ combined_plot += plot + text_order
1679
+ else:
1680
+ combined_plot += plot
1681
+
1682
+ # Set default axes
1683
+ axes = self._axes()
1684
+ xmin, xmax = axes[0][0], axes[0][1]
1685
+ ymin, ymax = axes[1][0], axes[1][1]
1686
+ combined_plot.set_axes_range(xmin=xmin, xmax=xmax,
1687
+ ymin=ymin, ymax=ymax)
1688
+ return combined_plot
1689
+
1690
+ def _repr_(self):
1691
+ """
1692
+ Return a string representation of ``self``.
1693
+
1694
+ EXAMPLES::
1695
+
1696
+ sage: T = TropicalSemiring(QQ)
1697
+ sage: R.<x,y> = PolynomialRing(T)
1698
+ sage: (x^2+R(0)).tropical_variety()
1699
+ Tropical curve of 0*x^2 + 0
1700
+ """
1701
+ return f"Tropical curve of {self._poly}"