passagemath-standard-no-symbolics 10.6.45__cp313-cp313-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.
Files changed (83) hide show
  1. passagemath_standard_no_symbolics/__init__.py +1 -0
  2. passagemath_standard_no_symbolics-10.6.45.data/scripts/sage-grep +5 -0
  3. passagemath_standard_no_symbolics-10.6.45.data/scripts/sage-grepdoc +5 -0
  4. passagemath_standard_no_symbolics-10.6.45.data/scripts/sage-list-packages +103 -0
  5. passagemath_standard_no_symbolics-10.6.45.dist-info/METADATA +150 -0
  6. passagemath_standard_no_symbolics-10.6.45.dist-info/RECORD +83 -0
  7. passagemath_standard_no_symbolics-10.6.45.dist-info/WHEEL +6 -0
  8. passagemath_standard_no_symbolics-10.6.45.dist-info/top_level.txt +2 -0
  9. sage/all.py +207 -0
  10. sage/all_cmdline.py +36 -0
  11. sage/cli/__init__.py +61 -0
  12. sage/cli/__main__.py +5 -0
  13. sage/cli/eval_cmd.py +45 -0
  14. sage/cli/eval_cmd_test.py +25 -0
  15. sage/cli/interactive_shell_cmd.py +28 -0
  16. sage/cli/notebook_cmd.py +51 -0
  17. sage/cli/notebook_cmd_test.py +39 -0
  18. sage/cli/options.py +26 -0
  19. sage/cli/run_file_cmd.py +50 -0
  20. sage/cli/version_cmd.py +26 -0
  21. sage/databases/all.py +83 -0
  22. sage/databases/cubic_hecke_db.py +1527 -0
  23. sage/dynamics/all.py +31 -0
  24. sage/dynamics/surface_dynamics_deprecation.py +32 -0
  25. sage/ext_data/kenzo/CP2.txt +45 -0
  26. sage/ext_data/kenzo/CP3.txt +349 -0
  27. sage/ext_data/kenzo/CP4.txt +4774 -0
  28. sage/ext_data/kenzo/README.txt +49 -0
  29. sage/ext_data/kenzo/S4.txt +20 -0
  30. sage/ext_data/mwrank/PRIMES +1 -0
  31. sage/ext_data/nbconvert/postprocess.py +48 -0
  32. sage/ext_data/nbconvert/rst_sage.tpl +99 -0
  33. sage/ext_data/nodoctest +0 -0
  34. sage/ext_data/notebook-ipython/kernel.json.in +11 -0
  35. sage/ext_data/notebook-ipython/logo-64x64.png +0 -0
  36. sage/ext_data/notebook-ipython/logo.svg +352 -0
  37. sage/ext_data/valgrind/pyalloc.supp +58 -0
  38. sage/ext_data/valgrind/sage-additional.supp +417 -0
  39. sage/ext_data/valgrind/sage.supp +43 -0
  40. sage/ext_data/valgrind/valgrind-python.supp +480 -0
  41. sage/geometry/all.py +12 -0
  42. sage/groups/matrix_gps/pickling_overrides.py +110 -0
  43. sage/homology/tests.py +66 -0
  44. sage/interacts/algebra.py +20 -0
  45. sage/interacts/all.py +25 -0
  46. sage/interacts/calculus.py +24 -0
  47. sage/interacts/fractals.py +18 -0
  48. sage/interacts/geometry.py +19 -0
  49. sage/interacts/library.py +1950 -0
  50. sage/interacts/library_cython.cpython-313-darwin.so +0 -0
  51. sage/interacts/statistics.py +19 -0
  52. sage/interfaces/axiom.py +1002 -0
  53. sage/interfaces/kash.py +834 -0
  54. sage/interfaces/lie.py +950 -0
  55. sage/interfaces/matlab.py +413 -0
  56. sage/interfaces/mupad.py +686 -0
  57. sage/interfaces/octave.py +858 -0
  58. sage/interfaces/phc.py +943 -0
  59. sage/interfaces/psage.py +189 -0
  60. sage/interfaces/qsieve.py +4 -0
  61. sage/interfaces/r.py +2096 -0
  62. sage/interfaces/read_data.py +46 -0
  63. sage/interfaces/scilab.py +576 -0
  64. sage/interfaces/tests.py +81 -0
  65. sage/libs/all.py +11 -0
  66. sage/libs/cremona/__init__.py +0 -0
  67. sage/libs/mwrank/__init__.py +0 -0
  68. sage/logic/all.py +3 -0
  69. sage/logic/booleval.py +160 -0
  70. sage/logic/boolformula.py +1490 -0
  71. sage/logic/logic.py +856 -0
  72. sage/logic/logicparser.py +696 -0
  73. sage/logic/logictable.py +272 -0
  74. sage/logic/propcalc.py +311 -0
  75. sage/misc/all.py +28 -0
  76. sage/misc/lazy_attribute.pyi +11 -0
  77. sage/rings/all.py +48 -0
  78. sage/rings/commutative_algebra.py +38 -0
  79. sage/rings/finite_rings/all.py +21 -0
  80. sage/rings/numbers_abc.py +58 -0
  81. sage/rings/polynomial/all.py +22 -0
  82. sage/rings/polynomial/convolution.py +421 -0
  83. sage/symbolic/all__sagemath_standard_no_symbolics.py +0 -0
sage/logic/logic.py ADDED
@@ -0,0 +1,856 @@
1
+ r"""
2
+ Symbolic Logic Expressions
3
+
4
+ An expression is created from a string that consists of the
5
+ operators ``!``, ``&``, ``|``, ``->``, ``<->``, which correspond to the
6
+ logical functions not, and, or, if then, if and only if, respectively.
7
+ Variable names must start with a letter and contain only
8
+ alpha-numerics and the underscore character.
9
+
10
+ AUTHORS:
11
+
12
+ - Chris Gorecki (2007): initial version
13
+
14
+ - William Stein (2007-08-31): integration into Sage 2.8.4
15
+
16
+ - Paul Scurek (2013-08-03): updated docstring formatting
17
+ """
18
+ # ****************************************************************************
19
+ # Copyright (C) 2007 Chris Gorecki <chris.k.gorecki@gmail.com>
20
+ # Copyright (C) 2007 William Stein <wstein@gmail.com>
21
+ # Copyright (C) 2013 Paul Scurek <scurek86@gmail.com>
22
+ #
23
+ # Distributed under the terms of the GNU General Public License (GPL)
24
+ # as published by the Free Software Foundation; either version 2 of
25
+ # the License, or (at your option) any later version.
26
+ # https://www.gnu.org/licenses/
27
+ # ****************************************************************************
28
+
29
+ import string
30
+
31
+ # constants
32
+ tok_list = ['OPAREN', 'CPAREN', 'AND', 'OR', 'NOT', 'IFTHEN', 'IFF']
33
+ bin_list = ['AND', 'OR', 'IFTHEN', 'IFF']
34
+ operators = '()&|!<->'
35
+ # variables
36
+ vars = {}
37
+ vars_order = []
38
+
39
+
40
+ class SymbolicLogic:
41
+ """
42
+ EXAMPLES:
43
+
44
+ This example illustrates how to create a boolean formula and print
45
+ its table::
46
+
47
+ sage: log = SymbolicLogic()
48
+ sage: s = log.statement("a&b|!(c|a)")
49
+ sage: t = log.truthtable(s)
50
+ sage: log.print_table(t)
51
+ a | b | c | value |
52
+ --------------------------------
53
+ False | False | False | True |
54
+ False | False | True | False |
55
+ False | True | False | True |
56
+ False | True | True | False |
57
+ True | False | False | False |
58
+ True | False | True | False |
59
+ True | True | False | True |
60
+ True | True | True | True |
61
+ """
62
+ def statement(self, s):
63
+ r"""
64
+ Return a token list to be used by other functions in the class.
65
+
66
+ INPUT:
67
+
68
+ - ``s`` -- string containing the logic expression to be manipulated
69
+
70
+ - ``global vars`` -- dictionary with variable names as keys and the
71
+ variables' current boolean values as dictionary values
72
+
73
+ - ``global vars_order`` -- list of the variables in the order
74
+ that they are found
75
+
76
+ OUTPUT: list of length three containing the following in this order:
77
+
78
+ 1. a list of tokens
79
+ 2. a dictionary of variable/value pairs
80
+ 3. a list of the variables in the order they were found
81
+
82
+ EXAMPLES:
83
+
84
+ This example illustrates the creation of a statement::
85
+
86
+ sage: log = SymbolicLogic()
87
+ sage: s = log.statement("a&b|!(c|a)")
88
+ sage: s2 = log.statement("!((!(a&b)))")
89
+
90
+ It is an error to use invalid variable names::
91
+
92
+ sage: s = log.statement("3fe & @q")
93
+ Invalid variable name: 3fe
94
+ Invalid variable name: @q
95
+
96
+ It is also an error to use invalid syntax::
97
+
98
+ sage: s = log.statement("a&&b")
99
+ Malformed Statement
100
+ sage: s = log.statement("a&((b)")
101
+ Malformed Statement
102
+ """
103
+ global vars, vars_order
104
+ toks, vars, vars_order = ['OPAREN'], {}, []
105
+ tokenize(s, toks)
106
+ statement = [toks, vars, vars_order]
107
+ try: # verify the syntax
108
+ eval(toks)
109
+ except (KeyError, RuntimeError):
110
+ print('Malformed Statement')
111
+ return []
112
+ return statement
113
+
114
+ def truthtable(self, statement, start=0, end=-1):
115
+ r"""
116
+ Return a truth table.
117
+
118
+ INPUT:
119
+
120
+ - ``statement`` -- list; it contains the tokens and the two global
121
+ variables vars and vars_order
122
+
123
+ - ``start`` -- integer (default: 0); this represents the row of
124
+ the truth table from which to start
125
+
126
+ - ``end`` -- integer (default: -1); this represents the last row
127
+ of the truth table to be created
128
+
129
+ OUTPUT:
130
+
131
+ The truth table as a 2d array with the creating formula tacked
132
+ to the front.
133
+
134
+ EXAMPLES:
135
+
136
+ This example illustrates the creation of a statement::
137
+
138
+ sage: log = SymbolicLogic()
139
+ sage: s = log.statement("a&b|!(c|a)")
140
+ sage: t = log.truthtable(s) #creates the whole truth table
141
+
142
+ We can now create truthtable of rows 1 to 5::
143
+
144
+ sage: s2 = log.truthtable(s, 1, 5); s2
145
+ [[['OPAREN',
146
+ 'a',
147
+ 'AND',
148
+ 'b',
149
+ 'OR',
150
+ 'NOT',
151
+ 'OPAREN',
152
+ 'c',
153
+ 'OR',
154
+ 'a',
155
+ 'CPAREN',
156
+ 'CPAREN'],
157
+ {'a': 'True', 'b': 'False', 'c': 'False'},
158
+ ['a', 'b', 'c']],
159
+ ['False', 'False', 'True', 'False'],
160
+ ['False', 'True', 'False', 'True'],
161
+ ['False', 'True', 'True', 'False'],
162
+ ['True', 'False', 'False', 'False']]
163
+
164
+ .. NOTE::
165
+
166
+ When sent with no start or end parameters this is an
167
+ exponential time function requiring `O(2^n)` time, where
168
+ `n` is the number of variables in the logic expression
169
+
170
+ TESTS:
171
+
172
+ Verify that :issue:`32676` is fixed::
173
+
174
+ sage: s = log.statement("a&b|!(c|a)")
175
+ sage: copy_s2 = copy(s[2])
176
+ sage: t = log.truthtable(s)
177
+ sage: s[2] == copy_s2
178
+ True
179
+ """
180
+ global vars, vars_order
181
+ toks, vars, vars_order = statement
182
+ if end == -1:
183
+ end = 2 ** len(vars)
184
+ table = [statement]
185
+ keys = vars_order
186
+ for i in range(start, end):
187
+ j = 0
188
+ row = []
189
+ for key in reversed(keys):
190
+ bit = get_bit(i, j)
191
+ vars[key] = bit
192
+ j += 1
193
+ row.insert(0, bit)
194
+ row.append(eval(toks))
195
+ table.append(row)
196
+ return table
197
+
198
+ def print_table(self, table):
199
+ r"""
200
+ Return a truthtable corresponding to the given statement.
201
+
202
+ INPUT:
203
+
204
+ - ``table`` -- object created by :meth:`truthtable()` method; it
205
+ contains the variable values and the evaluation of the statement
206
+
207
+ OUTPUT: a formatted version of the truth table
208
+
209
+ EXAMPLES:
210
+
211
+ This example illustrates the creation of a statement and
212
+ its truth table::
213
+
214
+ sage: log = SymbolicLogic()
215
+ sage: s = log.statement("a&b|!(c|a)")
216
+ sage: t = log.truthtable(s) #creates the whole truth table
217
+ sage: log.print_table(t)
218
+ a | b | c | value |
219
+ --------------------------------
220
+ False | False | False | True |
221
+ False | False | True | False |
222
+ False | True | False | True |
223
+ False | True | True | False |
224
+ True | False | False | False |
225
+ True | False | True | False |
226
+ True | True | False | True |
227
+ True | True | True | True |
228
+
229
+ We can also print a shortened table::
230
+
231
+ sage: t = log.truthtable(s, 1, 5)
232
+ sage: log.print_table(t)
233
+ a | b | c | value |
234
+ --------------------------------
235
+ False | False | True | False |
236
+ False | True | False | True |
237
+ False | True | True | False |
238
+ True | False | False | False |
239
+
240
+ TESTS:
241
+
242
+ Verify that :issue:`32676` is fixed::
243
+
244
+ sage: table = log.truthtable(log.statement("A->B"))
245
+ sage: table_copy = table.copy()
246
+ sage: log.print_table(table)
247
+ ...
248
+ sage: table_copy == table
249
+ True
250
+ """
251
+ statement = table[0]
252
+ table = table[1:]
253
+ vars_order = statement[2].copy()
254
+ vars_len = []
255
+ line = s = ""
256
+ vars_order.append('value')
257
+ for var in vars_order:
258
+ vars_len.append(len(var))
259
+ s = var + ' '
260
+ while len(s) < len('False '):
261
+ s += ' '
262
+ s += '| '
263
+ line += s
264
+ print(line)
265
+ print(len(line) * '-')
266
+ for row in table:
267
+ line = s = ""
268
+ i = 0
269
+ for e in row:
270
+ j = 2 if e == 'True' else 1
271
+ s = e + ' ' * j
272
+ if i < len(vars_len):
273
+ while len(s) <= vars_len[i]:
274
+ s += ' '
275
+ s += '| '
276
+ line += s
277
+ i += 1
278
+ print(line)
279
+ print("")
280
+
281
+ def combine(self, statement1, statement2):
282
+ r"""
283
+ Return a new statement which contains the
284
+ two statements or'd together.
285
+
286
+ INPUT:
287
+
288
+ - ``statement1`` -- the first statement
289
+ - ``statement2`` -- the second statement
290
+
291
+ OUTPUT: a new statement which or'd the given statements together
292
+
293
+ EXAMPLES::
294
+
295
+ sage: log = SymbolicLogic()
296
+ sage: s1 = log.statement("(a&b)")
297
+ sage: s2 = log.statement("b")
298
+ sage: log.combine(s1,s2)
299
+ [['OPAREN',
300
+ 'OPAREN',
301
+ 'OPAREN',
302
+ 'a',
303
+ 'AND',
304
+ 'b',
305
+ 'CPAREN',
306
+ 'CPAREN',
307
+ 'OR',
308
+ 'OPAREN',
309
+ 'b',
310
+ 'CPAREN',
311
+ 'CPAREN'],
312
+ {'a': 'False', 'b': 'False'},
313
+ ['a', 'b', 'b']]
314
+ """
315
+ toks = ['OPAREN'] + statement1[0] + ['OR'] + statement2[0] + ['CPAREN']
316
+ variables = dict(statement1[1])
317
+ variables.update(statement2[1])
318
+ var_order = statement1[2] + statement2[2]
319
+ return [toks, variables, var_order]
320
+
321
+ # TODO: implement the simplify function which calls
322
+ # a c++ implementation of the ESPRESSO algorithm
323
+ # to simplify the truthtable: probably Minilog
324
+ def simplify(self, table):
325
+ """
326
+ Call a C++ implementation of the ESPRESSO algorithm to simplify the
327
+ given truth table.
328
+
329
+ .. TODO::
330
+
331
+ Implement this method.
332
+
333
+ EXAMPLES::
334
+
335
+ sage: log = SymbolicLogic()
336
+ sage: s = log.statement("a&b|!(c|a)")
337
+ sage: t = log.truthtable(s)
338
+ sage: log.simplify(t)
339
+ Traceback (most recent call last):
340
+ ...
341
+ NotImplementedError
342
+ """
343
+ raise NotImplementedError
344
+
345
+ def prove(self, statement):
346
+ """
347
+ A function to test to see if the statement is a tautology or
348
+ contradiction by calling a C++ library.
349
+
350
+ .. TODO::
351
+
352
+ Implement this method.
353
+
354
+ EXAMPLES::
355
+
356
+ sage: log = SymbolicLogic()
357
+ sage: s = log.statement("a&b|!(c|a)")
358
+ sage: log.prove(s)
359
+ Traceback (most recent call last):
360
+ ...
361
+ NotImplementedError
362
+ """
363
+ raise NotImplementedError
364
+
365
+
366
+ def get_bit(x, c):
367
+ r"""
368
+ Determine if bit ``c`` of the number ``x`` is 1.
369
+
370
+ INPUT:
371
+
372
+ - ``x`` -- integer; this is the number from which to take the bit
373
+
374
+ - ``c`` -- integer; this is the bit number to be taken
375
+
376
+ OUTPUT: a boolean value to be determined as follows:
377
+
378
+ - ``True`` if bit ``c`` of ``x`` is 1.
379
+
380
+ - ``False`` if bit ``c`` of ``x`` is not 1.
381
+
382
+ .. NOTE::
383
+
384
+ This function is for internal use by the :class:`SymbolicLogic` class.
385
+
386
+ EXAMPLES::
387
+
388
+ sage: from sage.logic.logic import get_bit
389
+ sage: get_bit(int(2), int(1))
390
+ 'True'
391
+ sage: get_bit(int(8), int(0))
392
+ 'False'
393
+ """
394
+ bits = []
395
+ while x > 0:
396
+ b = 'False' if x % 2 == 0 else 'True'
397
+ x = x // 2
398
+ bits.append(b)
399
+ if c > len(bits) - 1:
400
+ return 'False'
401
+ else:
402
+ return bits[c]
403
+
404
+
405
+ def eval(toks):
406
+ r"""
407
+ Evaluate the expression contained in ``toks``.
408
+
409
+ INPUT:
410
+
411
+ - ``toks`` -- list of tokens; this represents a boolean expression
412
+
413
+ OUTPUT: a boolean value to be determined as follows:
414
+
415
+ - ``True`` if expression evaluates to ``True``.
416
+
417
+ - ``False`` if expression evaluates to ``False``.
418
+
419
+ .. NOTE::
420
+
421
+ This function is for internal use by the :class:`SymbolicLogic` class.
422
+ The evaluations rely on setting the values of the variables in the
423
+ global dictionary vars.
424
+
425
+ TESTS::
426
+
427
+ sage: log = SymbolicLogic()
428
+ sage: s = log.statement("a&b|!(c|a)")
429
+ sage: sage.logic.logic.eval(s[0])
430
+ 'True'
431
+ """
432
+ stack = []
433
+ for tok in toks:
434
+ stack.append(tok)
435
+ if tok == 'CPAREN':
436
+ lrtoks = []
437
+ while tok != 'OPAREN':
438
+ tok = stack.pop()
439
+ lrtoks.insert(0, tok)
440
+ stack.append(eval_ltor_toks(lrtoks[1:-1]))
441
+ if len(stack) > 1:
442
+ raise RuntimeError
443
+ return stack[0]
444
+
445
+
446
+ def eval_ltor_toks(lrtoks):
447
+ r"""
448
+ Evaluates the expression contained in ``lrtoks``.
449
+
450
+ INPUT:
451
+
452
+ - ``lrtoks`` -- list of tokens; this represents a part of a boolean
453
+ formula that contains no inner parentheses
454
+
455
+ OUTPUT: a boolean value to be determined as follows:
456
+
457
+ - ``True`` if expression evaluates to ``True``.
458
+
459
+ - ``False`` if expression evaluates to ``False``.
460
+
461
+ .. NOTE::
462
+
463
+ This function is for internal use by the :class:`SymbolicLogic` class.
464
+ The evaluations rely on setting the values of the variables in the
465
+ global dictionary vars.
466
+
467
+ TESTS::
468
+
469
+ sage: log = SymbolicLogic()
470
+ sage: s = log.statement("a&b|!c")
471
+ sage: ltor = s[0][1:-1]; ltor
472
+ ['a', 'AND', 'b', 'OR', 'NOT', 'c']
473
+ sage: sage.logic.logic.eval_ltor_toks(ltor)
474
+ 'True'
475
+ """
476
+ reduce_monos(lrtoks) # monotonic ! operators go first
477
+ reduce_bins(lrtoks) # then the binary operators
478
+ if len(lrtoks) > 1:
479
+ raise RuntimeError
480
+ return lrtoks[0]
481
+
482
+
483
+ def reduce_bins(lrtoks):
484
+ r"""
485
+ Evaluate ``lrtoks`` to a single boolean value.
486
+
487
+ INPUT:
488
+
489
+ - ``lrtoks`` -- list of tokens; this represents a part of a boolean
490
+ formula that contains no inner parentheses or monotonic operators
491
+
492
+ OUTPUT:
493
+
494
+ ``None``; the pointer to lrtoks is now a list containing
495
+ ``True`` or ``False``.
496
+
497
+ .. NOTE::
498
+
499
+ This function is for internal use by the :class:`SymbolicLogic` class.
500
+
501
+ TESTS::
502
+
503
+ sage: log = SymbolicLogic()
504
+ sage: s = log.statement("a&b|c")
505
+ sage: lrtoks = s[0][1:-1]; lrtoks
506
+ ['a', 'AND', 'b', 'OR', 'c']
507
+ sage: sage.logic.logic.reduce_bins(lrtoks); lrtoks
508
+ ['False']
509
+ """
510
+ i = 0
511
+ while i < len(lrtoks):
512
+ if lrtoks[i] in bin_list:
513
+ args = [lrtoks[i - 1], lrtoks[i], lrtoks[i + 1]]
514
+ lrtoks[i - 1] = eval_bin_op(args)
515
+ del lrtoks[i]
516
+ del lrtoks[i]
517
+ reduce_bins(lrtoks)
518
+ i += 1
519
+
520
+
521
+ def reduce_monos(lrtoks):
522
+ r"""
523
+ Replace monotonic operator/variable pairs with a boolean value.
524
+
525
+ INPUT:
526
+
527
+ - ``lrtoks`` -- list of tokens; this represents a part of a boolean
528
+ expression that contains now inner parentheses
529
+
530
+ OUTPUT:
531
+
532
+ ``None``; the pointer to ``lrtoks`` is now a list containing
533
+ monotonic operators.
534
+
535
+ .. NOTE::
536
+
537
+ This function is for internal use by the :class:`SymbolicLogic` class.
538
+
539
+ TESTS::
540
+
541
+ sage: log = SymbolicLogic()
542
+ sage: s = log.statement("!a&!b")
543
+ sage: lrtoks = s[0][1:-1]; lrtoks
544
+ ['NOT', 'a', 'AND', 'NOT', 'b']
545
+ sage: sage.logic.logic.reduce_monos(lrtoks); lrtoks
546
+ ['True', 'AND', 'True']
547
+ """
548
+ i = 0
549
+ while i < len(lrtoks):
550
+ if lrtoks[i] == 'NOT':
551
+ args = [lrtoks[i], lrtoks[i + 1]]
552
+ lrtoks[i] = eval_mon_op(args)
553
+ del lrtoks[i + 1]
554
+ i += 1
555
+
556
+
557
+ def eval_mon_op(args):
558
+ r"""
559
+ Return a boolean value based on the truth table of the operator
560
+ in ``args``.
561
+
562
+ INPUT:
563
+
564
+ - ``args`` -- list of length 2; this contains the token 'NOT' and
565
+ then a variable name
566
+
567
+ OUTPUT: a boolean value to be determined as follows:
568
+
569
+ - ``True`` if the variable in ``args`` is ``False``.
570
+
571
+ - ``False`` if the variable in ``args`` is ``True``.
572
+
573
+ .. NOTE::
574
+
575
+ This function is for internal use by the :class:`SymbolicLogic` class.
576
+
577
+ TESTS::
578
+
579
+ sage: log = SymbolicLogic()
580
+ sage: s = log.statement("!(a&b)|!a"); s
581
+ [['OPAREN', 'NOT', 'OPAREN', 'a', 'AND', 'b', 'CPAREN', 'OR',
582
+ 'NOT', 'a', 'CPAREN'],
583
+ {'a': 'False', 'b': 'False'},
584
+ ['a', 'b']]
585
+ sage: sage.logic.logic.eval_mon_op(['NOT', 'a'])
586
+ 'True'
587
+ """
588
+ val = vars[args[1]] if args[1] != 'True' and args[1] != 'False' else args[1]
589
+
590
+ return 'False' if val == 'True' else 'True'
591
+
592
+
593
+ def eval_bin_op(args):
594
+ r"""
595
+ Return a boolean value based on the truth table of the operator
596
+ in ``args``.
597
+
598
+ INPUT:
599
+
600
+ - ``args`` -- list of length 3; this contains a variable name,
601
+ then a binary operator, and then a variable name, in that order
602
+
603
+ OUTPUT:
604
+
605
+ A boolean value; this is the evaluation of the operator based on the
606
+ truth values of the variables.
607
+
608
+ .. NOTE::
609
+
610
+ This function is for internal use by the :class:`SymbolicLogic` class.
611
+
612
+ TESTS::
613
+
614
+ sage: log = SymbolicLogic()
615
+ sage: s = log.statement("!(a&b)"); s
616
+ [['OPAREN', 'NOT', 'OPAREN', 'a', 'AND', 'b', 'CPAREN', 'CPAREN'],
617
+ {'a': 'False', 'b': 'False'},
618
+ ['a', 'b']]
619
+ sage: sage.logic.logic.eval_bin_op(['a', 'AND', 'b'])
620
+ 'False'
621
+ """
622
+ if args[0] == 'False':
623
+ lval = 'False'
624
+ elif args[0] == 'True':
625
+ lval = 'True'
626
+ else:
627
+ lval = vars[args[0]]
628
+
629
+ if args[2] == 'False':
630
+ rval = 'False'
631
+ elif args[2] == 'True':
632
+ rval = 'True'
633
+ else:
634
+ rval = vars[args[2]]
635
+
636
+ if args[1] == 'AND':
637
+ return eval_and_op(lval, rval)
638
+ elif args[1] == 'OR':
639
+ return eval_or_op(lval, rval)
640
+ elif args[1] == 'IFTHEN':
641
+ return eval_ifthen_op(lval, rval)
642
+ elif args[1] == 'IFF':
643
+ return eval_iff_op(lval, rval)
644
+
645
+
646
+ def eval_and_op(lval, rval):
647
+ r"""
648
+ Apply the 'and' operator to ``lval`` and ``rval``.
649
+
650
+ INPUT:
651
+
652
+ - ``lval`` -- string; this represents the value of the variable
653
+ appearing to the left of the 'and' operator
654
+
655
+ - ``rval`` -- string; this represents the value of the variable
656
+ appearing to the right of the 'and' operator
657
+
658
+ OUTPUT: the result of applying 'and' to ``lval`` and ``rval`` as a string
659
+
660
+ .. NOTE::
661
+
662
+ This function is for internal use by the :class:`SymbolicLogic` class.
663
+
664
+ TESTS::
665
+
666
+ sage: sage.logic.logic.eval_and_op('False', 'False')
667
+ 'False'
668
+ sage: sage.logic.logic.eval_and_op('False', 'True')
669
+ 'False'
670
+ sage: sage.logic.logic.eval_and_op('True', 'False')
671
+ 'False'
672
+ sage: sage.logic.logic.eval_and_op('True', 'True')
673
+ 'True'
674
+ """
675
+ return 'True' if (lval == 'True' == rval) else 'False'
676
+
677
+
678
+ def eval_or_op(lval, rval):
679
+ r"""
680
+ Apply the 'or' operator to ``lval`` and ``rval``.
681
+
682
+ INPUT:
683
+
684
+ - ``lval`` -- string; this represents the value of the variable
685
+ appearing to the left of the 'or' operator
686
+
687
+ - ``rval`` -- string; this represents the value of the variable
688
+ appearing to the right of the 'or' operator
689
+
690
+ OUTPUT: string representing the result of applying 'or' to ``lval`` and ``rval``
691
+
692
+ .. NOTE::
693
+
694
+ This function is for internal use by the :class:`SymbolicLogic` class.
695
+
696
+ TESTS::
697
+
698
+ sage: sage.logic.logic.eval_or_op('False', 'False')
699
+ 'False'
700
+ sage: sage.logic.logic.eval_or_op('False', 'True')
701
+ 'True'
702
+ sage: sage.logic.logic.eval_or_op('True', 'False')
703
+ 'True'
704
+ sage: sage.logic.logic.eval_or_op('True', 'True')
705
+ 'True'
706
+ """
707
+ return 'True' if (lval == 'True' or rval == 'True') else 'False'
708
+
709
+
710
+ def eval_ifthen_op(lval, rval):
711
+ r"""
712
+ Apply the 'if then' operator to ``lval`` and ``rval``.
713
+
714
+ INPUT:
715
+
716
+ - ``lval`` -- string; this represents the value of the variable
717
+ appearing to the left of the 'if then' operator
718
+
719
+ - ``rval`` -- string; this represents the value of the variable
720
+ appearing to the right of the 'if then' operator
721
+
722
+ OUTPUT:
723
+
724
+ A string representing the result of applying 'if then' to
725
+ ``lval`` and ``rval``.
726
+
727
+ .. NOTE::
728
+
729
+ This function is for internal use by the :class:`SymbolicLogic` class.
730
+
731
+ TESTS::
732
+
733
+ sage: sage.logic.logic.eval_ifthen_op('False', 'False')
734
+ 'True'
735
+ sage: sage.logic.logic.eval_ifthen_op('False', 'True')
736
+ 'True'
737
+ sage: sage.logic.logic.eval_ifthen_op('True', 'False')
738
+ 'False'
739
+ sage: sage.logic.logic.eval_ifthen_op('True', 'True')
740
+ 'True'
741
+ """
742
+ return 'False' if (lval == 'True' and rval == 'False') else 'True'
743
+
744
+
745
+ def eval_iff_op(lval, rval):
746
+ r"""
747
+ Apply the 'if and only if' operator to ``lval`` and ``rval``.
748
+
749
+ INPUT:
750
+
751
+ - ``lval`` -- string; this represents the value of the variable
752
+ appearing to the left of the 'if and only if' operator
753
+
754
+ - ``rval`` -- string; this represents the value of the variable
755
+ appearing to the right of the 'if and only if' operator
756
+
757
+ OUTPUT:
758
+
759
+ A string representing the result of applying 'if and only if'
760
+ to ``lval`` and ``rval``.
761
+
762
+ .. NOTE::
763
+
764
+ This function is for internal use by the :class:`SymbolicLogic` class.
765
+
766
+ TESTS::
767
+
768
+ sage: sage.logic.logic.eval_iff_op('False', 'False')
769
+ 'True'
770
+ sage: sage.logic.logic.eval_iff_op('False', 'True')
771
+ 'False'
772
+ sage: sage.logic.logic.eval_iff_op('True', 'False')
773
+ 'False'
774
+ sage: sage.logic.logic.eval_iff_op('True', 'True')
775
+ 'True'
776
+ """
777
+ return 'True' if (lval == rval) else 'False'
778
+
779
+
780
+ def tokenize(s, toks):
781
+ r"""
782
+ Tokenize ``s`` and place the tokens of ``s`` in ``toks``.
783
+
784
+ INPUT:
785
+
786
+ - ``s`` -- string; this contains a boolean expression
787
+
788
+ - ``toks`` -- list; this will be populated with the tokens of ``s``
789
+
790
+ OUTPUT: none; the tokens of ``s`` are placed in ``toks``
791
+
792
+ .. NOTE::
793
+
794
+ This function is for internal use by the :class:`SymbolicLogic` class.
795
+
796
+ EXAMPLES::
797
+
798
+ sage: from sage.logic.logic import tokenize
799
+ sage: toks = []
800
+ sage: tokenize("(a&b)|c", toks)
801
+ sage: toks
802
+ ['OPAREN', 'a', 'AND', 'b', 'CPAREN', 'OR', 'c', 'CPAREN']
803
+ """
804
+ i = 0
805
+ while i < len(s):
806
+ tok = ""
807
+ skip = valid = 1
808
+ if s[i] == '(':
809
+ tok = tok_list[0]
810
+ elif s[i] == ')':
811
+ tok = tok_list[1]
812
+ elif s[i] == '&':
813
+ tok = tok_list[2]
814
+ elif s[i] == '|':
815
+ tok = tok_list[3]
816
+ elif s[i] == '!':
817
+ tok = tok_list[4]
818
+ elif s[i:i + 2] == '->':
819
+ tok = tok_list[5]
820
+ skip = 2
821
+ elif s[i:i + 3] == '<->':
822
+ tok = tok_list[6]
823
+ skip = 3
824
+
825
+ if tok:
826
+ toks.append(tok)
827
+ i += skip
828
+ continue
829
+ else:
830
+ # token is a variable name
831
+ if s[i] == ' ':
832
+ i += 1
833
+ continue
834
+
835
+ while i < len(s) and s[i] not in operators and s[i] != ' ':
836
+ tok += s[i]
837
+ i += 1
838
+
839
+ if tok:
840
+ if tok[0] not in string.ascii_letters:
841
+ valid = 0
842
+ for c in tok:
843
+ if not (c in string.ascii_letters
844
+ or c in string.digits or c == '_'):
845
+ valid = 0
846
+
847
+ if valid == 1:
848
+ toks.append(tok)
849
+ vars[tok] = 'False'
850
+ if tok not in vars_order:
851
+ vars_order.append(tok)
852
+ else:
853
+ print('Invalid variable name: ', tok)
854
+ toks = []
855
+
856
+ toks.append('CPAREN')