passagemath-standard-no-symbolics 10.6.31rc3__cp314-cp314-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-standard-no-symbolics might be problematic. Click here for more details.

Files changed (82) hide show
  1. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grep +5 -0
  2. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-grepdoc +5 -0
  3. passagemath_standard_no_symbolics-10.6.31rc3.data/scripts/sage-list-packages +103 -0
  4. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/METADATA +151 -0
  5. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/RECORD +82 -0
  6. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/WHEEL +6 -0
  7. passagemath_standard_no_symbolics-10.6.31rc3.dist-info/top_level.txt +1 -0
  8. sage/all.py +207 -0
  9. sage/all_cmdline.py +36 -0
  10. sage/cli/__init__.py +61 -0
  11. sage/cli/__main__.py +5 -0
  12. sage/cli/eval_cmd.py +45 -0
  13. sage/cli/eval_cmd_test.py +25 -0
  14. sage/cli/interactive_shell_cmd.py +28 -0
  15. sage/cli/notebook_cmd.py +51 -0
  16. sage/cli/notebook_cmd_test.py +39 -0
  17. sage/cli/options.py +26 -0
  18. sage/cli/run_file_cmd.py +50 -0
  19. sage/cli/version_cmd.py +26 -0
  20. sage/databases/all.py +83 -0
  21. sage/databases/cubic_hecke_db.py +1527 -0
  22. sage/dynamics/all.py +31 -0
  23. sage/dynamics/surface_dynamics_deprecation.py +32 -0
  24. sage/ext_data/kenzo/CP2.txt +45 -0
  25. sage/ext_data/kenzo/CP3.txt +349 -0
  26. sage/ext_data/kenzo/CP4.txt +4774 -0
  27. sage/ext_data/kenzo/README.txt +49 -0
  28. sage/ext_data/kenzo/S4.txt +20 -0
  29. sage/ext_data/mwrank/PRIMES +1 -0
  30. sage/ext_data/nbconvert/postprocess.py +48 -0
  31. sage/ext_data/nbconvert/rst_sage.tpl +99 -0
  32. sage/ext_data/nodoctest +0 -0
  33. sage/ext_data/notebook-ipython/kernel.json.in +11 -0
  34. sage/ext_data/notebook-ipython/logo-64x64.png +0 -0
  35. sage/ext_data/notebook-ipython/logo.svg +352 -0
  36. sage/ext_data/valgrind/pyalloc.supp +58 -0
  37. sage/ext_data/valgrind/sage-additional.supp +417 -0
  38. sage/ext_data/valgrind/sage.supp +43 -0
  39. sage/ext_data/valgrind/valgrind-python.supp +480 -0
  40. sage/geometry/all.py +12 -0
  41. sage/groups/matrix_gps/pickling_overrides.py +110 -0
  42. sage/homology/tests.py +66 -0
  43. sage/interacts/algebra.py +20 -0
  44. sage/interacts/all.py +25 -0
  45. sage/interacts/calculus.py +24 -0
  46. sage/interacts/fractals.py +18 -0
  47. sage/interacts/geometry.py +19 -0
  48. sage/interacts/library.py +1950 -0
  49. sage/interacts/library_cython.cpython-314-darwin.so +0 -0
  50. sage/interacts/statistics.py +19 -0
  51. sage/interfaces/axiom.py +1002 -0
  52. sage/interfaces/kash.py +834 -0
  53. sage/interfaces/lie.py +950 -0
  54. sage/interfaces/matlab.py +413 -0
  55. sage/interfaces/mupad.py +686 -0
  56. sage/interfaces/octave.py +858 -0
  57. sage/interfaces/phc.py +943 -0
  58. sage/interfaces/psage.py +189 -0
  59. sage/interfaces/qsieve.py +4 -0
  60. sage/interfaces/r.py +2096 -0
  61. sage/interfaces/read_data.py +46 -0
  62. sage/interfaces/scilab.py +576 -0
  63. sage/interfaces/tests.py +81 -0
  64. sage/libs/all.py +11 -0
  65. sage/libs/cremona/__init__.py +0 -0
  66. sage/libs/mwrank/__init__.py +0 -0
  67. sage/logic/all.py +3 -0
  68. sage/logic/booleval.py +160 -0
  69. sage/logic/boolformula.py +1490 -0
  70. sage/logic/logic.py +856 -0
  71. sage/logic/logicparser.py +696 -0
  72. sage/logic/logictable.py +272 -0
  73. sage/logic/propcalc.py +311 -0
  74. sage/misc/all.py +28 -0
  75. sage/misc/lazy_attribute.pyi +11 -0
  76. sage/rings/all.py +48 -0
  77. sage/rings/commutative_algebra.py +38 -0
  78. sage/rings/finite_rings/all.py +21 -0
  79. sage/rings/numbers_abc.py +58 -0
  80. sage/rings/polynomial/all.py +22 -0
  81. sage/rings/polynomial/convolution.py +421 -0
  82. sage/symbolic/all__sagemath_standard_no_symbolics.py +0 -0
sage/interfaces/phc.py ADDED
@@ -0,0 +1,943 @@
1
+ r"""
2
+ Interface to PHC.
3
+
4
+ PHC computes numerical information about systems of polynomials over
5
+ the complex numbers.
6
+
7
+ PHC implements polynomial homotopy methods to exploit structure in
8
+ order to better approximate all isolated solutions. The package also
9
+ includes extra tools to handle positive dimensional solution
10
+ components.
11
+
12
+ AUTHORS:
13
+
14
+ - PHC was written by J. Verschelde, R. Cools, and many others (?)
15
+
16
+ - William Stein and Kelly ?? -- first version of interface to PHC
17
+
18
+ - Marshall Hampton -- second version of interface to PHC
19
+
20
+ - Marshall Hampton and Alex Jokela -- third version, path tracking
21
+ """
22
+
23
+ # ****************************************************************************
24
+ # Copyright (C) 2006 William Stein <wstein@gmail.com>
25
+ # Copyright (C) 2008 Marshall Hampton <hamptonio@gmail.com>
26
+ #
27
+ # Distributed under the terms of the GNU General Public License (GPL)
28
+ # as published by the Free Software Foundation; either version 2 of
29
+ # the License, or (at your option) any later version.
30
+ # https://www.gnu.org/licenses/
31
+ # ****************************************************************************
32
+
33
+ import os
34
+ import re
35
+ import pexpect
36
+ from random import random
37
+
38
+ from sage.misc.temporary_file import tmp_filename
39
+ from sage.rings.real_mpfr import RR
40
+ from sage.rings.cc import CC
41
+ from sage.rings.integer import Integer
42
+ from sage.misc.lazy_import import lazy_import
43
+ lazy_import("sage.plot.line", "line")
44
+ lazy_import("sage.plot.point", "point")
45
+
46
+
47
+ def get_solution_dicts(output_file_contents, input_ring, get_failures=True):
48
+ """
49
+ Return a list of dictionaries of variable:value (key:value)
50
+ pairs. Only used internally; see the solution_dict function in
51
+ the PHC_Object class definition for details.
52
+
53
+ INPUT:
54
+
55
+ - ``output_file_contents`` -- phc solution output as a string
56
+ - ``input_ring`` -- a PolynomialRing that variable names can be coerced into
57
+
58
+ OUTPUT: list of dictionaries of solutions
59
+
60
+ EXAMPLES::
61
+
62
+ sage: from sage.interfaces.phc import *
63
+ sage: R2.<x1,x2> = PolynomialRing(QQ,2)
64
+ sage: test_sys = [(x1-1)^5-x2, (x2-1)^5-1]
65
+ sage: sol = phc.blackbox(test_sys, R2) # optional -- phc
66
+ sage: test = get_solution_dicts(sol.output_file_contents,R2) # optional -- phc
67
+ sage: str(sum([q[x1].real() for q in test]))[0:4] # optional -- phc
68
+ '25.0'
69
+ """
70
+ output_list = output_file_contents.splitlines()
71
+ solution_dicts = []
72
+ for solution_line in range(len(output_list) - 1, -1, -1):
73
+ if output_list[solution_line].find('THE SOLUTIONS') == 0:
74
+ break
75
+ try:
76
+ var_number = int(output_list[solution_line + 2].split(' ')[1])
77
+ # sol_number = int(output_list[solution_line+2].split(' ')[0])
78
+ except IndexError:
79
+ var_number = int(output_list[solution_line + 1].split(' ')[1])
80
+ # sol_number = int(output_list[solution_line+1].split(' ')[0])
81
+ for i in range(solution_line + 1, len(output_list)):
82
+ if output_list[i].count('the solution for t') == 1:
83
+ if output_list[i - 3].count('success') > 0 or get_failures:
84
+ temp_dict = {}
85
+ for j in range(1, var_number + 1):
86
+ rawsplit = output_list[i + j].split(': ')[1].split(' ')
87
+ for extras in range(rawsplit.count('')):
88
+ rawsplit.remove('')
89
+ temp_var = output_list[i + j].split(': ')[0].replace(' ', '')
90
+ temp_dict[input_ring(temp_var)] = CC(rawsplit[0],
91
+ rawsplit[1])
92
+ solution_dicts.append(temp_dict)
93
+ return solution_dicts
94
+
95
+
96
+ def get_classified_solution_dicts(output_file_contents, input_ring, get_failures=True):
97
+ """
98
+ Return a dictionary of lists of dictionaries of variable:value (key:value)
99
+ pairs. Only used internally; see the classified_solution_dict function in
100
+ the PHC_Object class definition for details.
101
+
102
+ INPUT:
103
+
104
+ - ``output_file_contents`` -- phc solution output as a string
105
+ - ``input_ring`` -- a PolynomialRing that variable names can be coerced into
106
+
107
+ OUTPUT: a dictionary of lists if dictionaries of solutions, classifies by type
108
+
109
+ EXAMPLES::
110
+
111
+ sage: from sage.interfaces.phc import *
112
+ sage: R2.<x1,x2> = PolynomialRing(QQ,2)
113
+ sage: test_sys = [(x1-2)^5-x2, (x2-1)^5-1]
114
+ sage: sol = phc.blackbox(test_sys, R2) # optional -- phc
115
+ sage: sol_classes = get_classified_solution_dicts(sol.output_file_contents,R2) # optional -- phc
116
+ sage: len(sol_classes['real']) # optional -- phc
117
+ 1
118
+ """
119
+ output_list = output_file_contents.splitlines()
120
+ solution_dicts = {}
121
+ solution_types = ['complex', 'real', 'failure']
122
+ for sol_type in solution_types:
123
+ solution_dicts[sol_type] = []
124
+ for solution_line in range(len(output_list) - 1, -1, -1):
125
+ if output_list[solution_line].find('THE SOLUTIONS') == 0:
126
+ break
127
+ var_number = int(output_list[solution_line + 2].split(' ')[1])
128
+ # sol_number = int(output_list[solution_line+2].split(' ')[0])
129
+ for i in range(solution_line + 1, len(output_list)):
130
+ if output_list[i].count('the solution for t') == 1:
131
+ phc_type = output_list[i + var_number + 1].split(' = ')[-1]
132
+ if phc_type.find('complex') != -1:
133
+ phc_type = 'complex'
134
+ elif phc_type.find('real') != -1:
135
+ phc_type = 'real'
136
+ else:
137
+ phc_type = 'failure'
138
+ temp_dict = {}
139
+ for j in range(1, var_number + 1):
140
+ rawsplit = output_list[i + j].split(': ')[1].split(' ')
141
+ for extras in range(rawsplit.count('')):
142
+ rawsplit.remove('')
143
+ temp_var = output_list[i + j].split(': ')[0].replace(' ', '')
144
+ if phc_type == 'real':
145
+ temp_dict[input_ring(temp_var)] = RR(rawsplit[0])
146
+ else:
147
+ temp_dict[input_ring(temp_var)] = CC(rawsplit[0],
148
+ rawsplit[1])
149
+ solution_dicts[phc_type].append(temp_dict)
150
+ return solution_dicts
151
+
152
+
153
+ def get_variable_list(output_file_contents):
154
+ """
155
+ Return the variables, as strings, in the order in which PHCpack has processed them.
156
+
157
+ EXAMPLES::
158
+
159
+ sage: from sage.interfaces.phc import *
160
+ sage: R2.<x1,x2> = PolynomialRing(QQ,2)
161
+ sage: test_sys = [(x1-2)^5-x2, (x2-1)^5-1]
162
+ sage: sol = phc.blackbox(test_sys, R2) # optional -- phc
163
+ sage: get_variable_list(sol.output_file_contents) # optional -- phc
164
+ ['x1', 'x2']
165
+ """
166
+ output_list = output_file_contents.splitlines()
167
+ for solution_line in range(len(output_list) - 1, -1, -1):
168
+ if output_list[solution_line].find('THE SOLUTIONS') == 0:
169
+ break
170
+ var_number = int(output_list[solution_line + 2].split(' ')[1])
171
+ varlist = []
172
+ for var_ind in range(var_number):
173
+ var = output_list[solution_line + 8 + var_ind].split(' ')[1]
174
+ varlist.append(var)
175
+ return varlist
176
+
177
+
178
+ class PHC_Object:
179
+
180
+ def __init__(self, output_file_contents, input_ring):
181
+ """
182
+ A container for data from the PHCpack program - lists of float
183
+ solutions, etc. Currently the file contents are kept as a string;
184
+ for really large outputs this would be bad.
185
+
186
+ INPUT:
187
+
188
+ - ``output_file_contents`` -- the string output of PHCpack
189
+ - ``input_ring`` -- for coercion of the variables into the desired ring
190
+
191
+ EXAMPLES::
192
+
193
+ sage: from sage.interfaces.phc import phc
194
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
195
+ sage: start_sys = [(x-1)^2+(y-1)-1, x^2+y^2-1]
196
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
197
+ sage: str(sum([x[0] for x in sol.solutions()]).real())[0:3] # optional -- phc
198
+ '2.0'
199
+ """
200
+ self.output_file_contents = output_file_contents
201
+ self.input_ring = input_ring
202
+
203
+ def save_as_start(self, start_filename=None, sol_filter=''):
204
+ """
205
+ Save a solution as a phcpack start file. The usual output is
206
+ just as a string, but it can be saved to a file as well. Even
207
+ if saved to a file, it still returns the output string.
208
+
209
+ EXAMPLES::
210
+
211
+ sage: from sage.interfaces.phc import phc
212
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
213
+ sage: start_sys = [x^3-y^2,y^5-1]
214
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
215
+ sage: start_save = sol.save_as_start() # optional -- phc
216
+ sage: end_sys = [x^7-2,y^5-x^2] # optional -- phc
217
+ sage: sol = phc.start_from(start_save, end_sys, R2) # optional -- phc
218
+ sage: len(sol.solutions()) # optional -- phc
219
+ 15
220
+ """
221
+ start_data = ''
222
+ output_list = self.output_file_contents.splitlines()
223
+ for a_line in output_list:
224
+ if a_line.find('ROOT COUNTS') != -1 or a_line.find('START SOLUTIONS') != -1:
225
+ break
226
+ else:
227
+ start_data += a_line + '\n'
228
+ for index in range(len(output_list) - 1, 0, -1):
229
+ a_line = output_list[index]
230
+ if a_line.find('THE SOLUTIONS') != -1:
231
+ found_solutions = index
232
+ break
233
+ start_data += output_list[found_solutions] + '\n\n'
234
+ try:
235
+ var_number = int(output_list[found_solutions + 1].split(' ')[1])
236
+ except Exception:
237
+ # bad error handling
238
+ var_number = int(output_list[found_solutions + 2].split(' ')[1])
239
+ sol_count = 0
240
+ sol_data = ''
241
+ for i in range(found_solutions + 2, len(output_list)):
242
+ if output_list[i].count('the solution for t') == 1 and output_list[i + 1 + var_number].find(sol_filter) != -1:
243
+ phc_type = output_list[i + var_number + 1].split(' = ')[-1]
244
+ if phc_type.find('no solution') == -1:
245
+ sol_count += 1
246
+ for ind2 in range(i - 3, i + var_number + 2):
247
+ sol_data += output_list[ind2] + '\n'
248
+ jan_bar = '=' * 75 + '\n'
249
+ sol_data += jan_bar
250
+ start_data += str(sol_count) + ' ' + str(var_number) + '\n'
251
+ start_data += jan_bar + sol_data
252
+ if start_filename is not None:
253
+ with open(start_filename, 'w') as start_file:
254
+ start_file.write(start_data)
255
+ return start_data
256
+
257
+ def classified_solution_dicts(self):
258
+ """
259
+ Return a dictionary of lists of dictionaries of solutions.
260
+
261
+ Its not as crazy as it sounds; the keys are the types of solutions as
262
+ classified by phcpack: regular vs. singular, complex vs. real
263
+
264
+ INPUT:
265
+
266
+ - None
267
+
268
+ OUTPUT: a dictionary of lists of dictionaries of solutions
269
+
270
+ EXAMPLES::
271
+
272
+ sage: from sage.interfaces.phc import phc
273
+ sage: R.<x,y> = PolynomialRing(CC,2)
274
+ sage: p_sys = [x^10-y,y^2-1]
275
+ sage: sol = phc.blackbox(p_sys,R) # optional -- phc
276
+ sage: classifieds = sol.classified_solution_dicts() # optional -- phc
277
+ sage: str(sum([q[y] for q in classifieds['real']]))[0:3] # optional -- phc
278
+ '2.0'
279
+ """
280
+ try:
281
+ return self.__classified_sols
282
+ except AttributeError:
283
+ pass
284
+ classified_sols = get_classified_solution_dicts(self.output_file_contents, self.input_ring)
285
+ self.__classified_sols = classified_sols
286
+ return classified_sols
287
+
288
+ def solution_dicts(self, get_failures=False):
289
+ """
290
+ Return a list of solutions in dictionary form: variable:value.
291
+
292
+ INPUT:
293
+
294
+ - ``self`` -- for access to self_out_file_contents, the string
295
+ of raw PHCpack output
296
+ - ``get_failures`` -- boolean (default: ``False``); the default
297
+ is to not process failed homotopies. These either lie on
298
+ positive-dimensional components or at infinity.
299
+
300
+ OUTPUT:
301
+
302
+ - solution_dicts: a list of dictionaries. Each dictionary
303
+ element is of the form variable:value, where the variable
304
+ is an element of the input_ring, and the value is in
305
+ ComplexField.
306
+
307
+ EXAMPLES::
308
+
309
+ sage: from sage.interfaces.phc import *
310
+ sage: R.<x,y,z> = PolynomialRing(QQ,3)
311
+ sage: fs = [x^2-1,y^2-x,z^2-y]
312
+ sage: sol = phc.blackbox(fs,R) # optional -- phc
313
+ sage: s_list = sol.solution_dicts() # optional -- phc
314
+ sage: s_list.sort() # optional -- phc
315
+ sage: s_list[0] # optional -- phc
316
+ {y: 1.00000000000000, z: -1.00000000000000, x: 1.00000000000000}
317
+ """
318
+ try:
319
+ return self.__solution_dicts
320
+ except AttributeError:
321
+ pass
322
+ solution_dicts = get_solution_dicts(self.output_file_contents, self.input_ring, get_failures=get_failures)
323
+ self.__solution_dicts = solution_dicts
324
+ return solution_dicts
325
+
326
+ def solutions(self, get_failures=False):
327
+ """
328
+ Return a list of solutions in the ComplexField.
329
+
330
+ Use the variable_list function to get the order of variables used by
331
+ PHCpack, which is usually different than the term order of the
332
+ input_ring.
333
+
334
+ INPUT:
335
+
336
+ - ``self`` -- for access to self_out_file_contents, the string
337
+ of raw PHCpack output
338
+ - ``get_failures`` -- boolean (default: ``False``); the default
339
+ is to not process failed homotopies. These either lie on
340
+ positive-dimensional components or at infinity.
341
+
342
+ OUTPUT: solutions: a list of lists of ComplexField-valued solutions
343
+
344
+ EXAMPLES::
345
+
346
+ sage: from sage.interfaces.phc import *
347
+ sage: R2.<x1,x2> = PolynomialRing(QQ,2)
348
+ sage: test_sys = [x1^5-x1*x2^2-1, x2^5-x1*x2-1]
349
+ sage: sol = phc.blackbox(test_sys, R2) # optional -- phc
350
+ sage: len(sol.solutions()) # optional -- phc
351
+ 25
352
+ """
353
+ try:
354
+ return self.__solutions
355
+ except AttributeError:
356
+ pass
357
+ solution_dicts = get_solution_dicts(self.output_file_contents, self.input_ring, get_failures=get_failures)
358
+ self.__solution_dicts = solution_dicts
359
+ solutions = [sol_dict.values() for sol_dict in solution_dicts]
360
+ self.__solutions = solutions
361
+ return solutions
362
+
363
+ def variable_list(self):
364
+ """
365
+ Return the variables, as strings, in the order in which
366
+ PHCpack has processed them.
367
+
368
+ EXAMPLES::
369
+
370
+ sage: from sage.interfaces.phc import *
371
+ sage: R2.<x1,x2> = PolynomialRing(QQ,2)
372
+ sage: test_sys = [x1^5-x1*x2^2-1, x2^5-x1*x2-1]
373
+ sage: sol = phc.blackbox(test_sys, R2) # optional -- phc
374
+ sage: sol.variable_list() # optional -- phc
375
+ ['x1', 'x2']
376
+ """
377
+ try:
378
+ return self.__var_list
379
+ except AttributeError:
380
+ pass
381
+ var_list = get_variable_list(self.output_file_contents)
382
+ self.__var_list = var_list
383
+ return var_list
384
+
385
+
386
+ class PHC:
387
+ """
388
+ A class to interface with PHCpack, for computing numerical
389
+ homotopies and root counts.
390
+
391
+ EXAMPLES::
392
+
393
+ sage: from sage.interfaces.phc import phc
394
+ sage: R.<x,y> = PolynomialRing(CDF,2)
395
+ sage: testsys = [x^2 + 1, x*y - 1]
396
+ sage: phc.mixed_volume(testsys) # optional -- phc
397
+ 2
398
+ sage: v = phc.blackbox(testsys, R) # optional -- phc
399
+ sage: sols = v.solutions() # optional -- phc
400
+ sage: sols.sort() # optional -- phc
401
+ sage: sols # optional -- phc
402
+ [[-1.00000000000000*I, 1.00000000000000*I], [1.00000000000000*I, -1.00000000000000*I]]
403
+ sage: sol_dict = v.solution_dicts() # optional -- phc
404
+ sage: x_sols_from_dict = [d[x] for d in sol_dict] # optional -- phc
405
+ sage: x_sols_from_dict.sort(); x_sols_from_dict # optional -- phc
406
+ [-1.00000000000000*I, 1.00000000000000*I]
407
+ sage: residuals = [[test_equation.change_ring(CDF).subs(sol) for test_equation in testsys] for sol in v.solution_dicts()] # optional -- phc
408
+ sage: residuals # optional -- phc
409
+ [[0, 0], [0, 0]]
410
+ """
411
+
412
+ def _output_from_command_list(self, command_list, polys, verbose=False):
413
+ """
414
+ A pexpect interface to phcpack, given a command list for
415
+ interactive dialogs. The input file is supplied from the
416
+ polynomial list, output file is also supplied. This is
417
+ only used as a building block for the interface.
418
+
419
+ INPUT:
420
+
421
+ - ``command_list`` -- list of commands to phc
422
+ - ``polys`` -- a polynomial system as a list of polynomials
423
+
424
+ OUTPUT: an output string from phc
425
+
426
+ EXAMPLES::
427
+
428
+ sage: from sage.interfaces.phc import *
429
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
430
+ sage: start_sys = [(x-1)^2+(y-1)-1, x^2+y^2-1] # optional -- phc
431
+ sage: a = phc._output_from_command_list(['phc -m','4','n','n','n'], start_sys) # optional -- phc
432
+ """
433
+ # Get temporary file names (these will be in SAGE_HOME/.sage/tmp/pid)
434
+ input_filename = tmp_filename()
435
+ output_filename = tmp_filename()
436
+
437
+ # Get the input polynomial text
438
+ input = self._input_file(polys)
439
+ if verbose:
440
+ print("Writing the input file to %s" % input_filename)
441
+ with open(input_filename, 'w') as file:
442
+ file.write(input)
443
+
444
+ if verbose:
445
+ print("The following file will be the input polynomial file to phc.")
446
+ print(input)
447
+
448
+ # Create a phc process
449
+ child_phc = pexpect.spawn(command_list[0])
450
+ # feed it the commands
451
+ child_phc.sendline('y')
452
+ child_phc.sendline(input_filename)
453
+ child_phc.sendline(output_filename)
454
+ for command_string in command_list[1:]:
455
+ if verbose:
456
+ print(command_string)
457
+ child_phc.sendline(command_string)
458
+ child_phc.expect('results')
459
+ read_stuff = child_phc.read()
460
+ if verbose:
461
+ print(read_stuff)
462
+ child_phc.close()
463
+ if not os.path.exists(output_filename):
464
+ raise RuntimeError("The output file does not exist; something went wrong running phc.")
465
+
466
+ # Delete the input file
467
+ os.unlink(input_filename)
468
+
469
+ # Return the output filename
470
+ return output_filename
471
+
472
+ def _input_file(self, polys):
473
+ r"""
474
+ This is used internally to implement the PHC interface.
475
+
476
+ INPUT:
477
+
478
+ - ``polys`` -- list of polynomials in a Sage polynomial ring
479
+ over a field that embeds into the complex numbers
480
+
481
+ OUTPUT: a PHC input file (as a text string) that describes these
482
+ polynomials
483
+
484
+ EXAMPLES::
485
+
486
+ sage: from sage.interfaces.phc import *
487
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
488
+ sage: start_sys = [(x-1)^2+(y-1)-1, x^2+y^2-1]
489
+ sage: phc._input_file(start_sys) # optional -- phc
490
+ '2\nx^2 - 2*x + y - 1;\nx^2 + y^2 - 1;\n'
491
+ """
492
+ if not isinstance(polys, (list, tuple)):
493
+ raise TypeError('polys must be a list or tuple')
494
+ s = '%s\n' % len(polys)
495
+ for f in polys:
496
+ s += f._repr_() + ';\n' # note the semicolon *terminators*
497
+ return s
498
+
499
+ def _parse_path_file(self, input_filename, verbose=False):
500
+ """
501
+ Take a phpack output file containing path tracking information
502
+ and parses it into a list of lists of dictionaries - i.e. a
503
+ list of solutions paths, where each solution path is a list of
504
+ dictionaries of variable and homotopy parameter values.
505
+
506
+ INPUT:
507
+
508
+ - ``input_filename`` -- file must have path-tracking information
509
+
510
+ OUTPUT: list of lists of dictionaries, described above
511
+
512
+ EXAMPLES::
513
+
514
+ sage: from sage.interfaces.phc import *
515
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
516
+ sage: start_sys = [x^5-y^2,y^5-1]
517
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
518
+ sage: start_save = sol.save_as_start() # optional -- phc
519
+ sage: end_sys = [x^5-2,y^5-x^2] # optional -- phc
520
+ sage: path_track_filename = phc._path_track_file(start_save, end_sys, R2, c_skew = .001) # optional -- phc
521
+ sage: sol_paths = phc._parse_path_file(path_track_filename) # optional -- phc
522
+ sage: len(sol_paths) # optional -- phc
523
+ 25
524
+ """
525
+ if not os.path.exists(input_filename):
526
+ raise RuntimeError("The file containing output from phc (" + input_filename + ") cannot be found")
527
+
528
+ fh = open(input_filename)
529
+ line_idx = 0
530
+ begin = 0
531
+ count = 0
532
+ solutions_dicts = []
533
+ steps_dicts = []
534
+
535
+ # regular expressions for matching certain output types
536
+ var_cnt_regex = re.compile('^ +([0-9]+)')
537
+ output_regex = re.compile('^OUTPUT INFORMATION DURING')
538
+ t_regex = re.compile(r'(^t +: +(-{0,1}[0-9]+\.[0-9]+E[-+][0-9]+) +(-{0,1}[0-9]+\.[0-9]+E[-+][0-9]+)$)', re.IGNORECASE)
539
+ sols_regex = re.compile(r'(^ *(([a-z]|[0-9])+) +: +(-?[0-9]+\.[0-9]+E[-+][0-9]+) +(-?[0-9]+\.[0-9]+E[-+][0-9]+)$)', re.IGNORECASE)
540
+ complete_regex = re.compile('^TIMING INFORMATION')
541
+
542
+ breakfast = False
543
+ a_line = fh.readline()
544
+ end_test = ''
545
+ while a_line:
546
+ # processing....
547
+ a_line = a_line.replace("\n", '')
548
+ if line_idx == 0:
549
+ m = var_cnt_regex.match(a_line)
550
+ if m:
551
+ count = Integer(m.group(1))
552
+ if count > 0:
553
+ m = output_regex.match(a_line)
554
+ if m:
555
+ begin = 1
556
+ if begin:
557
+ m = t_regex.match(a_line)
558
+ if m:
559
+ # put the t-values into a dict
560
+ # m.group(2) contains the real val
561
+ # m.group(3) contains the imaginary val
562
+ # fh_w.write( "T=> G1(" + m.group(2) + '),G2(' + m.group(3) + ")\n")
563
+ # read off two lines - this should be 'm' and 'the solution for t :'
564
+ a_line = fh.readline()
565
+ end_test = a_line # store this to check for end of solution
566
+ a_line = fh.readline()
567
+ t_val = CC(m.group(2), m.group(3))
568
+ temp_dict = {}
569
+ temp_dict["t"] = t_val
570
+ for i in range(count):
571
+ a_line = fh.readline()
572
+ m = sols_regex.match(a_line)
573
+ if m:
574
+ # m.group(2) contains our var name
575
+ # m.group(4) contains our real val
576
+ # m.group(5) contains our imaginary val
577
+ temp_dict[m.group(2)] = CC(m.group(4),
578
+ m.group(5))
579
+ steps_dicts.append(temp_dict)
580
+ # check if its the end of a solution
581
+ if end_test.find('Length of path') != -1:
582
+ if verbose:
583
+ print("recording sol")
584
+ if steps_dicts != []:
585
+ solutions_dicts.append(steps_dicts)
586
+ steps_dicts = []
587
+ m = complete_regex.match(a_line)
588
+ if m:
589
+ breakfast = True
590
+ if breakfast:
591
+ break
592
+ line_idx += 1
593
+ a_line = fh.readline()
594
+ fh.close()
595
+ return solutions_dicts
596
+
597
+ def _path_track_file(self, start_filename_or_string, polys, input_ring, c_skew=0.001, verbose=False):
598
+ """
599
+ Return the filename which contains path tracking output.
600
+
601
+ EXAMPLES::
602
+
603
+ sage: from sage.interfaces.phc import *
604
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
605
+ sage: start_sys = [x^6-y^2,y^5-1]
606
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
607
+ sage: start_save = sol.save_as_start() # optional -- phc
608
+ sage: end_sys = [x^7-2,y^5-x^2] # optional -- phc
609
+ sage: path_track_filename = phc._path_track_file(start_save, end_sys, R2, c_skew = .001) # optional -- phc
610
+ sage: sol_paths = phc._parse_path_file(path_track_filename) # optional -- phc
611
+ sage: len(sol_paths) # optional -- phc
612
+ 30
613
+ """
614
+ # Probably unnecessarily redundant from the start_from function
615
+ if start_filename_or_string.find('THE SOLUTIONS') != -1:
616
+ start_filename = tmp_filename()
617
+ with open(start_filename, 'w') as start_file:
618
+ start_file.write(start_filename_or_string)
619
+ elif os.path.exists(start_filename_or_string):
620
+ start_filename = start_filename_or_string
621
+ else:
622
+ raise RuntimeError("There is something wrong with your start string or filename")
623
+
624
+ return self._output_from_command_list(['phc', '0', '0', 'A', start_filename, 'y', '1', '0', 'n', 'k', '2', 'a', '1', str(c_skew), '0', '0', '2'], polys, verbose=verbose)
625
+
626
+ def path_track(self, start_sys, end_sys, input_ring, c_skew=.001, saved_start=None):
627
+ """
628
+ This function computes homotopy paths between the solutions of
629
+ ``start_sys`` and ``end_sys``.
630
+
631
+ INPUT:
632
+
633
+ - ``start_sys`` -- a square polynomial system, given as a list of
634
+ polynomials
635
+ - ``end_sys`` -- same type as ``start_sys``
636
+ - ``input_ring`` -- for coercion of the variables into the desired ring
637
+ - ``c_skew`` -- (optional) the imaginary part of homotopy multiplier;
638
+ nonzero values are often necessary to avoid intermediate path
639
+ collisions
640
+ - ``saved_start`` -- (optional) a phc output file; if not given, start
641
+ system solutions are computed via the ``phc.blackbox`` function
642
+
643
+ OUTPUT: list of paths as dictionaries, with the keys variables and
644
+ t-values on the path
645
+
646
+ EXAMPLES::
647
+
648
+ sage: from sage.interfaces.phc import *
649
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
650
+ sage: start_sys = [x^6-y^2,y^5-1]
651
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
652
+ sage: start_save = sol.save_as_start() # optional -- phc
653
+ sage: end_sys = [x^7-2,y^5-x^2] # optional -- phc
654
+ sage: sol_paths = phc.path_track(start_sys, end_sys, R2, saved_start = start_save) # optional -- phc
655
+ sage: len(sol_paths) # optional -- phc
656
+ 30
657
+ """
658
+ if not saved_start:
659
+ sol = phc.blackbox(start_sys, input_ring)
660
+ saved_start = sol.save_as_start()
661
+ path_track_filename = phc._path_track_file(saved_start, end_sys, input_ring=input_ring, c_skew=c_skew)
662
+ sol_paths = phc._parse_path_file(path_track_filename)
663
+ os.unlink(path_track_filename)
664
+ return sol_paths
665
+
666
+ def plot_paths_2d(self, start_sys, end_sys, input_ring, c_skew=.001, endpoints=True, saved_start=None, rand_colors=False):
667
+ """
668
+ Return a graphics object of solution paths in the complex plane.
669
+
670
+ INPUT:
671
+
672
+ - ``start_sys`` -- a square polynomial system, given as a list of
673
+ polynomials
674
+ - ``end_sys`` -- same type as start_sys
675
+ - ``input_ring`` -- for coercion of the variables into the desired ring
676
+ - ``c_skew`` -- (optional) the imaginary part of homotopy multiplier;
677
+ nonzero values are often necessary to avoid intermediate path
678
+ collisions
679
+ - ``endpoints`` -- (optional) whether to draw in the ends of paths as
680
+ points
681
+ - ``saved_start`` -- (optional) a phc output file; if not given, start
682
+ system solutions are computed via the ``phc.blackbox`` function
683
+
684
+ OUTPUT: lines and points of solution paths
685
+
686
+ EXAMPLES::
687
+
688
+ sage: from sage.interfaces.phc import *
689
+ sage: from sage.structure.sage_object import SageObject
690
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
691
+ sage: start_sys = [x^5-y^2,y^5-1]
692
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
693
+ sage: start_save = sol.save_as_start() # optional -- phc
694
+ sage: end_sys = [x^5-25,y^5-x^2] # optional -- phc
695
+ sage: testing = phc.plot_paths_2d(start_sys, end_sys, R2) # optional -- phc
696
+ sage: type(testing) # optional -- phc (normally use plot here)
697
+ <class 'sage.plot.graphics.Graphics'>
698
+ """
699
+ paths = phc.path_track(start_sys, end_sys, input_ring, c_skew=c_skew, saved_start=saved_start)
700
+ path_lines = []
701
+ sol_pts = []
702
+ if rand_colors:
703
+ r_color = {}
704
+ for a_var in input_ring.gens():
705
+ var_name = str(a_var)
706
+ r_color[var_name] = (random(), random(), random())
707
+ for a_sol in paths:
708
+ for a_var in input_ring.gens():
709
+ var_name = str(a_var)
710
+ temp_line = []
711
+ for data in a_sol:
712
+ temp_line.append([data[var_name].real(), data[var_name].imag()])
713
+ if rand_colors:
714
+ path_lines.append(line(temp_line, rgbcolor=r_color[var_name]))
715
+ else:
716
+ path_lines.append(line(temp_line))
717
+ if endpoints:
718
+ sol_pts = []
719
+ for a_sol in paths:
720
+ for a_var in input_ring.gens():
721
+ var_name = str(a_var)
722
+ sol_pts.append(point([a_sol[0][var_name].real(), a_sol[0][var_name].imag()]))
723
+ sol_pts.append(point([a_sol[-1][var_name].real(), a_sol[-1][var_name].imag()]))
724
+ return sum(sol_pts) + sum(path_lines)
725
+ else:
726
+ return sum(path_lines)
727
+
728
+ def mixed_volume(self, polys, verbose=False):
729
+ """
730
+ Compute the mixed volume of the polynomial system given by the input polys.
731
+
732
+ INPUT:
733
+
734
+ - ``polys`` -- list of multivariate polynomials (elements of a multivariate
735
+ polynomial ring).
736
+ - ``verbose`` -- print lots of verbose information about what this function does
737
+
738
+ OUTPUT: the mixed volume
739
+
740
+ EXAMPLES::
741
+
742
+ sage: from sage.interfaces.phc import *
743
+ sage: R2.<x,y,z> = PolynomialRing(QQ,3)
744
+ sage: test_sys = [(x+y+z)^2-1,x^2-x,y^2-1]
745
+ sage: phc.mixed_volume(test_sys) # optional -- phc
746
+ 4
747
+ """
748
+ output_filename = self._output_from_command_list(['phc -m', '4', 'n', 'n', 'n'], polys, verbose=verbose)
749
+
750
+ with open(output_filename) as out:
751
+ out.read()
752
+ # All done
753
+ out_lines = out.split('\n')
754
+ for a_line in out_lines:
755
+ # the two conditions below are necessary because of changes in output format
756
+ if a_line.find('The mixed volume equals :') == 0 or a_line.find('common mixed volume :') == 0:
757
+ if verbose:
758
+ print('found line: ' + a_line)
759
+ mixed_vol = Integer(a_line.split(':')[1])
760
+ break
761
+
762
+ try:
763
+ return mixed_vol
764
+ except NameError:
765
+ raise RuntimeError("Mixed volume not found in output; something went wrong running phc.")
766
+
767
+ def start_from(self, start_filename_or_string, polys, input_ring, path_track_file=None, verbose=False):
768
+ """
769
+ This computes solutions starting from a phcpack solution file.
770
+
771
+ INPUT:
772
+
773
+ - ``start_filename_or_string`` -- the filename for a phcpack start system,
774
+ or the contents of such a file as a string. Variable names must match
775
+ the inputring variables. The value of the homotopy variable t should
776
+ be 1, not 0.
777
+ - ``polys`` -- list of multivariate polynomials (elements of a multivariate
778
+ polynomial ring).
779
+ - input_ring: for coercion of the variables into the desired ring.
780
+ - path_track_file: whether to save path-tracking information
781
+ - ``verbose`` -- print lots of verbose information about what this function does
782
+
783
+ OUTPUT: a solution in the form of a PHCObject
784
+
785
+ EXAMPLES::
786
+
787
+ sage: from sage.interfaces.phc import *
788
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
789
+ sage: start_sys = [x^6-y^2,y^5-1]
790
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
791
+ sage: start_save = sol.save_as_start() # optional -- phc
792
+ sage: end_sys = [x^7-2,y^5-x^2] # optional -- phc
793
+ sage: sol = phc.start_from(start_save, end_sys, R2) # optional -- phc
794
+ sage: len(sol.solutions()) # optional -- phc
795
+ 30
796
+ """
797
+ input_filename = tmp_filename()
798
+ output_filename = tmp_filename()
799
+
800
+ if start_filename_or_string.find('THE SOLUTIONS') != -1:
801
+ start_filename = tmp_filename()
802
+ with open(start_filename, 'w') as start_file:
803
+ start_file.write(start_filename_or_string)
804
+ elif os.path.exists(start_filename_or_string):
805
+ start_filename = start_filename_or_string
806
+ else:
807
+ raise RuntimeError("There is something wrong with your start string or filename")
808
+
809
+ # Get the input polynomial text
810
+ input = self._input_file(polys)
811
+ if verbose:
812
+ print("Writing the input file to %s" % input_filename)
813
+ with open(input_filename, 'w') as f:
814
+ f.write(input)
815
+
816
+ if verbose:
817
+ print("The following file will be the input polynomial file to phc.")
818
+ print(input)
819
+
820
+ # Create a phc process
821
+ child_phc = pexpect.spawn('phc')
822
+ child_phc.sendline('y')
823
+ child_phc.sendline(input_filename)
824
+ child_phc.sendline(output_filename)
825
+ child_phc.sendline('0')
826
+ child_phc.sendline('0')
827
+ child_phc.expect('Nonlinear Reduction')
828
+ child_phc.sendline('A')
829
+ child_phc.sendline(start_filename)
830
+ child_phc.sendline('y')
831
+ child_phc.sendline('1')
832
+ child_phc.sendline('0')
833
+ if verbose:
834
+ phc_dialog = child_phc.read(size=40)
835
+ print(phc_dialog)
836
+ child_phc.sendline('n')
837
+ child_phc.sendline('0')
838
+ if verbose:
839
+ child_phc.expect('CURRENT CONTINUATION')
840
+ phc_dialog = child_phc.read(size=40)
841
+ print(phc_dialog)
842
+ child_phc.sendline('0')
843
+ if path_track_file is None:
844
+ child_phc.sendline('0')
845
+ else:
846
+ child_phc.sendline('2')
847
+ child_phc.expect('results')
848
+ dots = child_phc.read()
849
+ if verbose:
850
+ print("should be . : " + dots)
851
+
852
+ # close down the process:
853
+ child_phc.close()
854
+ if not os.path.exists(output_filename):
855
+ raise RuntimeError("The output file does not exist; something went wrong running phc.")
856
+
857
+ # Read the output produced by PHC
858
+ with open(output_filename) as f:
859
+ out = f.read()
860
+
861
+ # Delete the temporary files
862
+ os.unlink(output_filename)
863
+ os.unlink(input_filename)
864
+
865
+ # All done
866
+ return PHC_Object(out, input_ring)
867
+
868
+ def blackbox(self, polys, input_ring, verbose=False):
869
+ """
870
+ Return as a string the result of running PHC with the given polynomials
871
+ under blackbox mode (the '-b' option).
872
+
873
+ INPUT:
874
+
875
+ - ``polys`` -- list of multivariate polynomials (elements of a multivariate
876
+ polynomial ring).
877
+ - ``input_ring`` -- for coercion of the variables into the desired ring
878
+ - ``verbose`` -- print lots of verbose information about what this function does
879
+
880
+ OUTPUT: a PHC_Object object containing the phcpack output string
881
+
882
+ EXAMPLES::
883
+
884
+ sage: from sage.interfaces.phc import *
885
+ sage: R2.<x,y> = PolynomialRing(QQ,2)
886
+ sage: start_sys = [x^6-y^2,y^5-1]
887
+ sage: sol = phc.blackbox(start_sys, R2) # optional -- phc
888
+ sage: len(sol.solutions()) # optional -- phc
889
+ 30
890
+ """
891
+
892
+ # Get three temporary file names (these will be in SAGE_HOME/.sage/tmp/pid)
893
+ input_filename = tmp_filename()
894
+ output_filename = input_filename + ".phc"
895
+ log_filename = tmp_filename()
896
+
897
+ # Get the input polynomial text
898
+ input = self._input_file(polys)
899
+ if verbose:
900
+ print("Writing the input file to %s" % input_filename)
901
+ with open(input_filename, 'w') as f:
902
+ f.write(input)
903
+
904
+ if verbose:
905
+ print("The following file will be the input polynomial file to phc.")
906
+ print(input)
907
+
908
+ # Create the phc command line>
909
+ cmd = 'phc -b %s %s' % (input_filename, output_filename)
910
+
911
+ if verbose:
912
+ print("The phc command line is:")
913
+ print(cmd)
914
+
915
+ # Do it -- make the system call.
916
+ e = os.system(cmd)
917
+
918
+ # Was there an error?
919
+ if e:
920
+ from sage.misc.sage_ostools import have_program
921
+ if not have_program('phc'):
922
+ print(str(os.system('which phc')) + ' PHC needs to be installed and in your path')
923
+ raise RuntimeError
924
+ # todo -- why? etc.
925
+ with open(log_filename) as f:
926
+ msg = f.read()
927
+ raise RuntimeError(msg + "\nError running phc.")
928
+
929
+ if not os.path.exists(output_filename):
930
+ raise RuntimeError("The output file does not exist; something went wrong running phc.")
931
+
932
+ # Read the output produced by PHC
933
+ with open(output_filename) as f:
934
+ out = f.read()
935
+
936
+ # All done
937
+ return PHC_Object(out, input_ring)
938
+
939
+
940
+ ################################
941
+
942
+ # The unique phc interface instance.
943
+ phc = PHC()