00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 import __
00024 import math
00025 import randomly
00026 import is_
00027 import alphabet
00028 import default
00029 import error
00030 import debug
00031
00032
00033
00034 MAX_VALUE = 20
00035
00036
00037
00038 FRACTIONS_SUMS_TABLE = [([1, 2], 15),
00039 ([1, 3], 15),
00040 ([1, 4], 15),
00041 ([1, 5], 15),
00042 ([1, 6], 15),
00043 ([1, 7], 15),
00044 ([2, 3], 17),
00045 ([2, 5], 10),
00046 ([2, 7], 7),
00047 ([3, 4], 9),
00048 ([3, 5], 7),
00049 ([3, 7], 5),
00050 ([4, 5], 5),
00051 ([4, 7], 3),
00052 ([5, 6], 4),
00053 ([5, 7], 4),
00054 ([6, 7], 3)]
00055
00056 FRACTIONS_SUMS_SCALE_TABLE = [0.02,
00057 0.02,
00058 0.02,
00059 0.01,
00060 0.005,
00061 0.005,
00062 0.21,
00063 0.14,
00064 0.02,
00065 0.21,
00066 0.14,
00067 0.01,
00068 0.16,
00069 0.01,
00070 0.01,
00071 0.005,
00072 0.005]
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 class Printable(object):
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 def make_string(self, markup, **options):
00104 raise error.MethodShouldBeRedefined(self, 'make_string')
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 class NamedExpression(Printable):
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 def __init__(self, integer_or_letter, objct):
00133
00134 if not (is_.a_string(integer_or_letter) \
00135 or is_.an_integer(integer_or_letter)):
00136
00137 raise error.UncompatibleType(integer_or_letter, \
00138 "integer_or_letter")
00139
00140 if not (is_.a_calculable(objct) or objct == None):
00141 raise error.UncompatibleType(objct, "Exponented")
00142
00143 self.name = integer_or_letter
00144 self.right_hand_side = objct.deep_copy()
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 def make_string(self, markup, **options):
00157 global expression_begins
00158
00159 if is_.an_integer(self.name):
00160 i = self.name
00161 if i < len(alphabet.UPPERCASE):
00162 final_name = alphabet.UPPERCASE[i]
00163 else:
00164 nb_letters = len(alphabet.UPPERCASE)
00165 final_name = alphabet.UPPERCASE[i -
00166 nb_letters
00167 *
00168 int(i/nb_letters)
00169 ] \
00170 + markup['opening_subscript'] \
00171 + str(int(i/nb_letters)) \
00172 + markup['closing_subscript']
00173
00174 elif is_.a_string(self.name):
00175 final_name = self.name
00176
00177 expression_begins = True
00178
00179 return final_name \
00180 + markup['equal'] \
00181 + self.right_hand_side.make_string(markup,
00182 force_expression_begins=True,
00183 **options)
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 def auto_expansion_and_reduction(self, markup, **options):
00197 global expression_begins
00198 aux_expr = self.right_hand_side
00199 result = ""
00200
00201
00202
00203
00204
00205
00206 while aux_expr != None:
00207 result += markup['opening_expression'] \
00208 + NamedExpression(self.name,
00209 aux_expr).make_string(markup) \
00210 + markup['closing_expression'] \
00211 + markup['newline'] \
00212 + "\n"
00213
00214
00215
00216 aux_expr = aux_expr.expand_and_reduce_next_step()
00217
00218 return result
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 class Equality(Printable):
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 def __init__(self, objcts, **options):
00245
00246 if not (isinstance(objcts, list)):
00247 raise error.UncompatibleType(objcts, \
00248 "should be a LIST (of two Exponenteds at least)")
00249
00250 if not len(objcts) >= 2:
00251 raise error.UncompatibleType(objcts, \
00252 "should be a list of TWO Exponenteds AT LEAST")
00253
00254 for i in xrange(len(objcts)):
00255 if not isinstance(objcts[i], calc.Exponented):
00256 raise error.UncompatibleType(objcts[i], \
00257 "should be a Exponented")
00258
00259 if 'equal_signs' in options:
00260 if not type(options['equal_signs']) == list:
00261 raise error.UncompatibleType(options['equal_signs'], \
00262 "should be a list")
00263 if not len(options['equal_signs']) == len(objcts) - 1:
00264 raise error.UncompatibleType(options['equal_signs'], \
00265 "should contain " \
00266 + str(len(objcts) - 1) \
00267 + " elements.")
00268
00269 for i in xrange(len(options['equal_signs'])):
00270 if not (options['equal_signs'][i] == '=' \
00271 or options['equal_signs'][i] == 'neq'):
00272
00273 raise error.UncompatibleType(options['equal_signs'][i], \
00274 " should be '=' or 'neq'")
00275
00276
00277 self.elements = []
00278 self.equal_signs = []
00279
00280 for i in xrange(len(objcts)):
00281 self.elements.append(objcts[i].deep_copy())
00282
00283 if 'equal_signs' in options:
00284
00285 if i < len(options['equal_signs']):
00286 sign_to_add = None
00287
00288 if options['equal_signs'][i] == '=':
00289 sign_to_add = 'equal'
00290 else:
00291 sign_to_add = 'not_equal'
00292
00293 self.equal_signs.append(sign_to_add)
00294
00295 else:
00296 self.equal_signs.append('equal')
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 def make_string(self, markup, **options):
00309 global expression_begins
00310
00311
00312 expression_begins = True
00313
00314 result = ''
00315
00316 if 'force_expression_markers' in options\
00317 and options['force_expression_markers'] == 'yes':
00318
00319 result += markup['opening_expression']
00320
00321
00322 result += self.elements[0].make_string(markup,
00323 force_expression_begins=True,
00324 **options)
00325
00326 for i in xrange(len(self.elements) - 1):
00327 result += markup[self.equal_signs[i]] \
00328 + self.elements[i+1].make_string(markup,
00329 force_expression_begins=True,
00330 **options)
00331
00332 if 'force_expression_markers' in options\
00333 and options['force_expression_markers'] == 'yes':
00334
00335 result += markup['closing_expression']
00336
00337 return result
00338
00339
00340
00341
00342
00343
00344
00345
00346 def __getitem__(self, i):
00347 return self.elements[i]
00348
00349
00350 def __setitem__(self, i, data):
00351 if not isinstance(data, Exponented):
00352 raise error.UncompatibleType(data, "should be a Exponented")
00353
00354 self.elements[i] = data.deep_copy()
00355
00356
00357
00358
00359
00360
00361
00362
00363 def __len__(self):
00364 return len(self.elements)
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 class Equation(Printable):
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 def __init__(self, arg, **options):
00389 self.name = default.EQUATION_NAME
00390 self.number = ''
00391 self.left_hand_side = None
00392 self.right_hand_side = None
00393 self.variable_letter = default.MONOMIAL_LETTER
00394
00395
00396 if 'name' in options and is_.a_string(options['name']):
00397 self.name = options['name']
00398
00399 if 'number' in options and is_.an_integer(options['number']):
00400 self.number = options['number']
00401
00402
00403 if 'variable_letter_name' in options \
00404 and is_.a_string(options['variable_letter_name']):
00405
00406 self.variable_letter = options['variable_letter_name'][0]
00407
00408
00409 if type(arg) == tuple and len(arg) == 2:
00410
00411
00412
00413 if is_.a_calculable(arg[0]) and is_.a_calculable(arg[1]):
00414 if isinstance(arg[0], calc.Sum):
00415
00416
00417
00418
00419 self.left_hand_side = arg[0]
00420 else:
00421 self.left_hand_side = calc.Sum(arg[0])
00422
00423 if isinstance(arg[1], calc.Sum):
00424
00425
00426
00427
00428 self.right_hand_side = arg[1]
00429 else:
00430 self.right_hand_side = calc.Sum(arg[1])
00431
00432
00433
00434 elif arg[0] == __.RANDOMLY:
00435 if arg[1] == 'basic_addition':
00436 self.left_hand_side = calc.Polynomial([
00437 calc.Monomial(('+',
00438 1,
00439 1)),
00440 calc.Monomial((randomly.sign(),
00441 randomly.integer(1,
00442 MAX_VALUE),
00443 0))
00444 ])
00445
00446 self.right_hand_side = calc.Sum(calc.Item((randomly.sign(),
00447 randomly.integer(1,
00448 MAX_VALUE)
00449 ))
00450 )
00451
00452
00453 self.left_hand_side.term[0].set_letter(
00454 self.variable_letter)
00455
00456
00457 elif arg[1] == 'basic_addition_r':
00458 self.right_hand_side = calc.Polynomial([
00459 calc.Monomial(('+',
00460 1,
00461 1)),
00462 calc.Monomial((randomly.sign(),
00463 randomly.integer(1,
00464 MAX_VALUE),
00465 0))
00466 ])
00467
00468 self.left_hand_side = calc.Sum(calc.Item((randomly.sign(),
00469 randomly.integer(1,
00470 MAX_VALUE)
00471 ))
00472 )
00473
00474
00475 self.right_hand_side.term[0].set_letter(
00476 self.variable_letter)
00477 elif arg[1] == 'any_basic_addition':
00478 cst_list = list()
00479 m1 = calc.Monomial((randomly.sign(plus_signs_ratio=0.8),
00480 1,
00481 1))
00482
00483 m1.set_letter(self.variable_letter)
00484
00485 m2 = calc.Monomial((randomly.sign(),
00486 randomly.integer(1,MAX_VALUE),
00487 0))
00488
00489 m3 = calc.Monomial((randomly.sign(),
00490 randomly.integer(1,MAX_VALUE),
00491 0))
00492
00493 cst_list.append(m2)
00494 cst_list.append(m3)
00495
00496 drawn_to_be_with_x = randomly.pop(cst_list)
00497
00498 polyn_list = list()
00499 polyn_list.append(m1)
00500 polyn_list.append(drawn_to_be_with_x)
00501
00502 polyn = calc.Polynomial([randomly.pop(polyn_list),
00503 randomly.pop(polyn_list)])
00504 sides = list()
00505 sides.append(polyn)
00506 sides.append(calc.Sum(randomly.pop(cst_list)))
00507
00508 self.left_hand_side = randomly.pop(sides)
00509 self.right_hand_side = randomly.pop(sides)
00510
00511 elif arg[1] == 'basic_multiplication':
00512 self.left_hand_side = calc.Sum(
00513 calc.Monomial(( \
00514 randomly.sign(plus_signs_ratio=0.75),
00515 randomly.integer(2, MAX_VALUE),
00516 1))
00517 )
00518
00519
00520 self.right_hand_side = calc.Sum(
00521 calc.Item(( \
00522 randomly.sign(plus_signs_ratio=0.75),
00523 randomly.integer(1, MAX_VALUE),
00524 1))
00525 )
00526
00527
00528 self.left_hand_side.term[0].\
00529 set_letter(self.variable_letter)
00530
00531 elif arg[1] == 'basic_multiplication_r':
00532 self.right_hand_side = calc.Sum(
00533 calc.Monomial(( \
00534 randomly.sign(plus_signs_ratio=0.75),
00535 randomly.integer(2, MAX_VALUE),
00536 1))
00537 )
00538
00539
00540 self.left_hand_side = calc.Sum(
00541 calc.Item(( \
00542 randomly.sign(plus_signs_ratio=0.75),
00543 randomly.integer(1, MAX_VALUE),
00544 1))
00545 )
00546
00547
00548 self.right_hand_side.term[0].\
00549 set_letter(self.variable_letter)
00550
00551 elif arg[1] == 'any_basic_multiplication':
00552 m1 = calc.Monomial((randomly.sign(plus_signs_ratio=0.75),
00553 randomly.integer(2, MAX_VALUE),
00554 1))
00555 m1.set_letter(self.variable_letter)
00556
00557 m2 = calc.Item((randomly.sign(plus_signs_ratio=0.75),
00558 randomly.integer(1, MAX_VALUE),
00559 1))
00560
00561 items_list = list()
00562 items_list.append(calc.Sum(m1))
00563 items_list.append(calc.Sum(m2))
00564
00565 self.left_hand_side = randomly.pop(items_list)
00566 self.right_hand_side = randomly.pop(items_list)
00567
00568 elif arg[1] == 'any_basic':
00569 if randomly.heads_or_tails():
00570 m1 = calc.Monomial((randomly.sign(plus_signs_ratio= \
00571 0.75),
00572 randomly.integer(2, MAX_VALUE),
00573 1))
00574 m1.set_letter(self.variable_letter)
00575
00576 m2 = calc.Item((randomly.sign(plus_signs_ratio=0.75),
00577 randomly.integer(1, MAX_VALUE),
00578 1))
00579
00580 items_list = list()
00581 items_list.append(calc.Sum(m1))
00582 items_list.append(calc.Sum(m2))
00583
00584 self.left_hand_side = randomly.pop(items_list)
00585 self.right_hand_side = randomly.pop(items_list)
00586 else:
00587 cst_list = list()
00588 m1 = calc.Monomial((randomly.sign(plus_signs_ratio= \
00589 0.8),
00590 1,
00591 1))
00592 m1.set_letter(self.variable_letter)
00593
00594 m2 = calc.Monomial((randomly.sign(),
00595 randomly.integer(1,MAX_VALUE),
00596 0))
00597 m3 = calc.Monomial((randomly.sign(),
00598 randomly.integer(1,MAX_VALUE),
00599 0))
00600
00601 cst_list.append(m2)
00602 cst_list.append(m3)
00603
00604 drawn_to_be_with_x = randomly.pop(cst_list)
00605
00606 polyn_list = list()
00607 polyn_list.append(m1)
00608 polyn_list.append(drawn_to_be_with_x)
00609
00610 polyn = calc.Polynomial([randomly.pop(polyn_list),
00611 randomly.pop(polyn_list)])
00612 sides = list()
00613 sides.append(polyn)
00614 sides.append(calc.Sum(randomly.pop(cst_list)))
00615
00616 self.left_hand_side = randomly.pop(sides)
00617 self.right_hand_side = randomly.pop(sides)
00618
00619 elif arg[1] == 'classic' \
00620 or arg[1] == 'classic_r' \
00621 or arg[1] == 'classic_x_twice' \
00622 or arg[1] == 'any_classic':
00623
00624
00625
00626
00627
00628
00629 box = list()
00630 ax = calc.Monomial((randomly.sign(plus_signs_ratio=0.65),
00631 randomly.integer(1,MAX_VALUE),
00632 1))
00633 ax.set_letter(self.variable_letter)
00634
00635 b = calc.Monomial((randomly.sign(),
00636 randomly.integer(1,MAX_VALUE),
00637 0))
00638 cx = calc.Monomial((randomly.sign(plus_signs_ratio=0.65),
00639 randomly.integer(1,MAX_VALUE),
00640 1))
00641 cx.set_letter(self.variable_letter)
00642
00643 d = calc.Monomial((randomly.sign(),
00644 randomly.integer(1,MAX_VALUE),
00645 0))
00646
00647 box.append(ax)
00648 box.append(b)
00649
00650 polyn1 = calc.Polynomial([randomly.pop(box),
00651 randomly.pop(box)])
00652
00653 if arg[1] == 'classic' or arg[1] == 'classic_r':
00654 polyn2 = calc.Polynomial([d])
00655 elif arg[1] == 'classic_x_twice':
00656 if randomly.decimal_0_1() > 0.3:
00657 box = list()
00658 box.append(cx)
00659 box.append(d)
00660 polyn2 = calc.Polynomial([randomly.pop(box),
00661 randomly.pop(box)])
00662 else:
00663 polyn2 = calc.Polynomial([cx])
00664
00665 elif arg[1] == 'any_classic':
00666 box = list()
00667 random_nb = randomly.decimal_0_1()
00668 if random_nb < 0.4:
00669 box.append(cx)
00670 box.append(d)
00671 polyn2 = calc.Polynomial([randomly.pop(box),
00672 randomly.pop(box)])
00673 elif random_nb < 0.7:
00674 polyn2 = calc.Polynomial([d])
00675
00676 else:
00677 polyn2 = calc.Polynomial([cx])
00678
00679 if arg[1] == 'classic':
00680 self.left_hand_side = polyn1
00681 self.right_hand_side = polyn2
00682 elif arg[1] == 'classic_r':
00683 self.left_hand_side = polyn2
00684 self.right_hand_side = polyn1
00685 elif arg[1] == 'classic_x_twice' \
00686 or arg[1] == 'any_classic':
00687 box = list()
00688 box.append(polyn1)
00689 box.append(polyn2)
00690 self.left_hand_side = randomly.pop(box)
00691 self.right_hand_side = randomly.pop(box)
00692
00693 elif arg[1] == 'classic_with_fractions':
00694
00695
00696 randomly_position = randomly.integer(0,
00697 16,
00698 weighted_table=\
00699 FRACTIONS_SUMS_SCALE_TABLE)
00700
00701 chosen_seed_and_generator = FRACTIONS_SUMS_TABLE[\
00702 randomly_position]
00703
00704
00705 seed = randomly.integer(2, chosen_seed_and_generator[1])
00706
00707
00708
00709
00710
00711
00712
00713
00714 if seed * chosen_seed_and_generator[0][0] \
00715 * chosen_seed_and_generator[0][1] >= 75:
00716
00717 seed = randomly.integer(2, chosen_seed_and_generator[1])
00718
00719 lil_box = [0, 1]
00720 gen1 = chosen_seed_and_generator[0][lil_box.pop()]
00721 gen2 = chosen_seed_and_generator[0][lil_box.pop()]
00722
00723 den1 = calc.Item(gen1*seed)
00724 den2 = calc.Item(gen2*seed)
00725
00726 temp1 = randomly.integer(1, 20)
00727 temp2 = randomly.integer(1, 20)
00728
00729 num1 = calc.Item(temp1 / calc.lib.gcd(temp1, gen1*seed))
00730 num2 = calc.Item(temp2 / calc.lib.gcd(temp2, gen2*seed))
00731
00732 f1 = calc.Fraction((randomly.sign(plus_signs_ratio=0.7),
00733 num1,
00734 den1))
00735 f2 = calc.Fraction((randomly.sign(plus_signs_ratio=0.7),
00736 num2,
00737 den2))
00738
00739
00740
00741 box = list()
00742 ax = calc.Monomial((calc.Fraction((randomly.sign(\
00743 plus_signs_ratio=0.7),
00744 calc.Item(randomly.integer(1,
00745 10)),
00746 calc.Item(randomly.integer(2,
00747 10))
00748 )).simplified(),
00749 1))
00750 ax.set_letter(self.variable_letter)
00751
00752 b = calc.Monomial((f1.simplified(), 0))
00753 d = calc.Monomial((f2.simplified(), 0))
00754
00755 box.append(ax)
00756 box.append(b)
00757
00758 self.left_hand_side = calc.Polynomial([randomly.pop(box),
00759 randomly.pop(box)])
00760
00761 self.right_hand_side = calc.Sum([d])
00762
00763
00764 elif arg[1] == 'any_simple_expandable' \
00765 or arg[1] == 'any_double_expandable':
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 if randomly.decimal_0_1() <= 0.8:
00776 aux_expd_1 = calc.Expandable((__.RANDOMLY,
00777 'monom0_polyn1'),
00778 max_coeff=9)
00779 expd_kind = 'monom0_polyn1'
00780
00781 else:
00782 sign = randomly.sign()
00783 aux_expd_1 = calc.Expandable(( \
00784 calc.Monomial((sign,
00785 1,
00786 0)),
00787 calc.Polynomial((__.RANDOMLY,
00788 9,
00789 1,
00790 2))
00791 ))
00792 if sign == '+':
00793 expd_kind = '+(...)'
00794 else:
00795 expd_kind = 'monom0_polyn1'
00796
00797
00798 box_1 = []
00799 box_2 = []
00800
00801 additional_Monomial = calc.Monomial((__.RANDOMLY,
00802 9,
00803 1))
00804 additional_Monomial2 = calc.Monomial((__.RANDOMLY,
00805 9,
00806 1))
00807
00808 if additional_Monomial.degree == 0:
00809 additional_Monomial2.set_degree(1)
00810
00811 box_1.append(aux_expd_1)
00812
00813 if expd_kind == '+(...)' or randomly.decimal_0_1() <= 0.5:
00814 box_1.append(additional_Monomial)
00815
00816 box_2.append(calc.Monomial((__.RANDOMLY, 9, 1)))
00817
00818 if randomly.decimal_0_1() <= 0.25:
00819
00820 box_2.append(additional_Monomial2)
00821
00822 if arg[1] == 'any_double_expandable':
00823 if randomly.decimal_0_1() <= 0.8:
00824 aux_expd_2 = calc.Expandable((__.RANDOMLY,
00825 'monom0_polyn1'),
00826 max_coeff=9)
00827
00828 else:
00829 sign = randomly.sign()
00830 aux_expd_2 = calc.Expandable(( \
00831 calc.Monomial((sign,
00832 1,
00833 0)),
00834 calc.Polynomial((__.RANDOMLY,
00835 9,
00836 1,
00837 2))
00838 ))
00839
00840 if randomly.decimal_0_1() <= 0.5:
00841 box_1.append(aux_expd_2)
00842 else:
00843 box_2.append(aux_expd_2)
00844
00845 boxes = [box_1, box_2]
00846 box_left = randomly.pop(boxes)
00847 box_right = randomly.pop(boxes)
00848
00849 left_list = list()
00850 right_list = list()
00851
00852 for i in xrange(len(box_left)):
00853 left_list.append(randomly.pop(box_left))
00854
00855 for i in xrange(len(box_right)):
00856 right_list.append(randomly.pop(box_right))
00857
00858 self.left_hand_side = calc.Sum(left_list)
00859 self.right_hand_side = calc.Sum(right_list)
00860
00861
00862
00863
00864 else:
00865 raise error.UncompatibleType(arg,
00866 "(Exponented, Exponented)|" \
00867 + "(__.RANDOMLY, <option>)")
00868
00869
00870 elif isinstance(arg, Equation):
00871 self.name = arg.name
00872 self.number = arg.number
00873 self.left_hand_side = arg.left_hand_side.deep_copy()
00874 self.right_hand_side = arg.right_hand_side.deep_copy()
00875 self.variable_letter = arg.variable_letter
00876
00877 else:
00878 raise error.UncompatibleType(arg, "Equation|tuple")
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889 def set_hand_side(self, left_or_right, arg):
00890
00891 if not (left_or_right == "left" or left_or_right == "right"):
00892 raise error.UncompatibleType(left_or_right,
00893 '"left" or "right"')
00894
00895 if is_.a_calculable(arg):
00896 if isinstance(arg, calc.Sum):
00897
00898
00899
00900
00901 if left_or_right == "left":
00902 self.left_hand_side = arg
00903 else:
00904 self.right_hand_side = arg
00905 else:
00906 if left_or_right == "left":
00907 self.left_hand_side = calc.Sum(arg)
00908 else:
00909 self.right_hand_side = calc.Sum(arg)
00910
00911 else:
00912 raise error.UncompatibleType(arg, "Equation|tuple")
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922 def __str__(self):
00923 return "\nEquation : " + str(self.name) \
00924 + " " + str(self.number) \
00925 + "\n Left hand side : " + str(self.left_hand_side) \
00926 + "\n Right hand side : " + str(self.right_hand_side) \
00927 + "\n Variable : " + str(self.variable_letter)
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 def solve_next_step(self, **options):
00940 new_eq = Equation(self)
00941
00942 debug.write("\nEntering [solve_next_step] " \
00943 + "with Equation :\n" \
00944 + str(new_eq) + "\n",
00945 case=debug.solve_next_step)
00946
00947
00948
00949 if isinstance(new_eq.left_hand_side.term[0], calc.Sum) \
00950 and len(new_eq.left_hand_side) == 1:
00951
00952
00953 debug.write("\n[solve_next_step] CASE-0s-left\n",
00954 case=debug.solve_next_step)
00955 new_eq.left_hand_side = new_eq.left_hand_side.term[0]
00956 return new_eq.solve_next_step(**options)
00957
00958 elif isinstance(new_eq.right_hand_side.term[0], calc.Sum) \
00959 and len(new_eq.right_hand_side) == 1:
00960
00961
00962 debug.write("\n[solve_next_step] CASE-0s-right\n",
00963 case=debug.solve_next_step)
00964 new_eq.right_hand_side = new_eq.right_hand_side.term[0]
00965 return new_eq.solve_next_step(**options)
00966
00967 if isinstance(new_eq.left_hand_side.term[0], calc.Product) \
00968 and len(new_eq.left_hand_side) == 1 \
00969 and len(new_eq.left_hand_side.term[0]) == 1:
00970
00971
00972 debug.write("\n[solve_next_step] CASE-0p-left\n",
00973 case=debug.solve_next_step)
00974 new_eq.left_hand_side = \
00975 calc.Sum(new_eq.left_hand_side.term[0].factor[0])
00976 return new_eq.solve_next_step(**options)
00977
00978 elif isinstance(new_eq.right_hand_side.term[0], calc.Product) \
00979 and len(new_eq.right_hand_side) == 1 \
00980 and len(new_eq.right_hand_side.term[0]) == 1:
00981
00982
00983 debug.write("\n[solve_next_step] CASE-0p-right\n",
00984 case=debug.solve_next_step)
00985 new_eq.right_hand_side = \
00986 calc.Sum(new_eq.right_hand_side.term[0].factor[0])
00987 return new_eq.solve_next_step(**options)
00988
00989 next_left_X = new_eq.left_hand_side.expand_and_reduce_next_step()
00990 next_right_X = new_eq.right_hand_side.expand_and_reduce_next_step()
00991
00992
00993
00994 if debug.ENABLED and debug.solve_next_step:
00995 debug.write("\n[solve_next_step] " \
00996 + "'decimal_result' is in options : " \
00997 + str('decimal_result' in options) \
00998 + " len(new_eq.left_hand_side) == " \
00999 + str(len(new_eq.left_hand_side)) \
01000 + "\nnext_left_X is : " \
01001 + str(next_left_X) \
01002 + "\nnew_eq.left_hand_side.term[0].is_literal() : " \
01003 + str(new_eq.left_hand_side.term[0].is_literal()) \
01004 + " len(new_eq.right_hand_side) == " \
01005 + str(len(new_eq.right_hand_side)) \
01006 + "\nisinstance(new_eq.right_hand_side.term[0], " \
01007 + "calc.Fraction)" \
01008 + str(isinstance(new_eq.right_hand_side.term[0],
01009 calc.Fraction)) \
01010 + "\n",
01011 case=debug.solve_next_step)
01012
01013 if 'decimal_result' in options \
01014 and len(new_eq.left_hand_side) == 1 \
01015 and next_left_X == None \
01016 and not new_eq.left_hand_side.term[0].is_numeric() \
01017 and len(new_eq.right_hand_side) == 1 \
01018 and (isinstance(new_eq.right_hand_side.term[0], calc.Fraction) \
01019 or isinstance(new_eq.right_hand_side.term[0], calc.SquareRoot)):
01020
01021
01022 debug.write("\n[solve_next_step] Decimal Result CASE\n",
01023 case=debug.solve_next_step)
01024 new_eq.set_hand_side("right",
01025 new_eq.\
01026 right_hand_side.\
01027 expand_and_reduce_next_step(**options))
01028
01029
01030
01031 elif (next_left_X != None) or (next_right_X != None):
01032
01033
01034 debug.write("\n[solve_next_step] 1st CASE\n",
01035 case=debug.solve_next_step)
01036 if next_left_X != None:
01037
01038 new_eq.set_hand_side("left", next_left_X)
01039
01040 if next_right_X != None:
01041
01042 new_eq.set_hand_side("right", next_right_X)
01043
01044
01045
01046
01047
01048
01049
01050
01051 elif (len(new_eq.left_hand_side) >= 2) \
01052 or (len(new_eq.right_hand_side) >= 2) \
01053 or (len(new_eq.right_hand_side) == 1 \
01054 and not new_eq.right_hand_side.term[0].is_numeric()):
01055
01056
01057 debug.write("\n[solve_next_step] 2d CASE\n",
01058 case=debug.solve_next_step)
01059
01060
01061
01062 debug.write("\néquation en cours : " \
01063 + str(self) + "\n",
01064 case=debug.solve_next_step)
01065
01066 left_collected_terms = new_eq.left_hand_side.get_numeric_terms()
01067 right_collected_terms = new_eq.right_hand_side.get_literal_terms()
01068
01069
01070 if debug.ENABLED and debug.solve_next_step:
01071 debug.write("\nleft content : " \
01072 + str(self.left_hand_side),
01073 case=debug.solve_next_step)
01074 debug.write("\nright content : " \
01075 + str(self.right_hand_side),
01076 case=debug.solve_next_step)
01077
01078 lstring = "\nleft collected terms : "
01079
01080 for t in left_collected_terms:
01081 lstring += str(t)
01082
01083 debug.write(lstring,
01084 case=debug.solve_next_step)
01085
01086 rstring = "\nright collected terms : "
01087
01088 for t in right_collected_terms:
01089 rstring += str(t)
01090
01091 debug.write(rstring + "\n",
01092 case=debug.solve_next_step)
01093
01094
01095
01096
01097 if new_eq.left_hand_side.is_numeric() \
01098 and not new_eq.right_hand_side.is_numeric() \
01099 and len(new_eq.right_hand_side) == 2 \
01100 and len(right_collected_terms) == 1:
01101
01102
01103 debug.write("\nEntered in the Special Case [part of 2d Case]",
01104 case=debug.solve_next_step)
01105 debug.write("\nisinstance(right_collected_terms[0], " \
01106 + "calc.Product) is " \
01107 + str(isinstance(right_collected_terms[0], \
01108 calc.Product)) \
01109 + "\nlen(right_collected_terms[0]) == 2 is " \
01110 + str(len(right_collected_terms[0]) == 2) \
01111 + "\nright_collected_terms[0][0] is " \
01112
01113 + "\nlen(right_collected_terms[0]) == 1 is " \
01114 + str(len(right_collected_terms[0]) == 1) \
01115 + "\nisinstance(right_collected_terms[0], " \
01116 + "calc.Item) is " \
01117 + str(isinstance(right_collected_terms[0], \
01118 calc.Item)),
01119 case=debug.solve_next_step)
01120
01121 if (isinstance(right_collected_terms[0], calc.Product) \
01122 and len(right_collected_terms[0]) == 2 \
01123 and right_collected_terms[0][0].is_positive()) \
01124 or (isinstance(right_collected_terms[0], calc.Product) \
01125 and len(right_collected_terms[0]) == 1) \
01126 or (isinstance(right_collected_terms[0], calc.Item) \
01127 and right_collected_terms[0].is_positive()):
01128
01129
01130 debug.write("\nSpecial Case [part 2]",
01131 case=debug.solve_next_step)
01132
01133 return Equation((new_eq.right_hand_side,
01134 new_eq.left_hand_side)).solve_next_step()
01135
01136
01137
01138
01139
01140 if new_eq.left_hand_side.is_numeric() \
01141 and not new_eq.right_hand_side.is_numeric() \
01142 and len(new_eq.right_hand_side) == 1 \
01143 and isinstance(right_collected_terms[0], calc.Product):
01144
01145
01146 debug.write("\nSpecial Case [part 3]",
01147 case=debug.solve_next_step)
01148
01149 return Equation((new_eq.right_hand_side,
01150 new_eq.left_hand_side)).solve_next_step()
01151
01152
01153
01154
01155
01156
01157 for term in left_collected_terms:
01158
01159
01160
01161 new_eq.left_hand_side.remove(term)
01162 term.set_sign(calc.lib.sign_of_product(['-', term.sign]))
01163 new_eq.set_hand_side("right",
01164 new_eq.right_hand_side.plus(term)
01165 )
01166
01167 debug.write("\nNow, right_hand_side looks like : " \
01168 + str(new_eq.right_hand_side) + "\n",
01169 case=debug.solve_next_step)
01170
01171
01172
01173
01174
01175 for term in right_collected_terms:
01176
01177
01178
01179 new_eq.right_hand_side.remove(term)
01180
01181 term = term.times(calc.Item(-1)).reduce_()
01182 new_eq.set_hand_side("left", new_eq.left_hand_side.plus(term))
01183
01184 new_eq.left_hand_side.reduce_()
01185 new_eq.right_hand_side.reduce_()
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 elif (new_eq.left_hand_side.term[0].is_numeric() \
01197 and (new_eq.right_hand_side.term[0].is_numeric())
01198 ):
01199
01200
01201 debug.write("\n[solve_next_step] 3rd CASE\n",
01202 case=debug.solve_next_step)
01203 if new_eq.left_hand_side.term[0].value == \
01204 new_eq.right_hand_side.term[0].value \
01205 and new_eq.left_hand_side.get_sign() == \
01206 new_eq.right_hand_side.get_sign():
01207
01208 return _( \
01209 "Any value of %(variable_name)s is solution of the equation.") \
01210 % {'variable_name':new_eq.variable_letter}
01211
01212 else:
01213 return _("This equation has no solution.")
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 elif isinstance(new_eq.left_hand_side.term[0], calc.Product):
01224
01225
01226 debug.write("\n[solve_next_step] 4th CASE\n",
01227 case=debug.solve_next_step)
01228
01229
01230
01231 if isinstance(new_eq.right_hand_side.term[0], calc.Monomial):
01232 if isinstance(new_eq.right_hand_side.term[0].factor[0],
01233 calc.Item):
01234
01235 new_eq.right_hand_side.set_term(0,
01236 calc.Item(new_eq.right_hand_side.term[0])
01237 )
01238 elif isinstance(new_eq.right_hand_side.term[0].factor[0],
01239 calc.Fraction):
01240
01241 new_eq.right_hand_side.set_term(0,
01242 calc.Fraction(new_eq.right_hand_side.term[0])
01243 )
01244
01245
01246
01247
01248 coefficient = new_eq.left_hand_side.term[0].factor[0]
01249
01250 if coefficient.is_equivalent_to_a_single_1():
01251 new_eq.set_hand_side("left",
01252 calc.Item(new_eq.left_hand_side.term[0]\
01253 .factor[1]))
01254 return new_eq.solve_next_step(**options)
01255
01256 elif coefficient.is_equivalent_to_a_single_minus_1():
01257 new_eq.left_hand_side.term[0].set_opposite_sign()
01258 new_eq.right_hand_side.term[0].set_opposite_sign()
01259
01260 elif isinstance(coefficient, calc.Item)\
01261 and isinstance(new_eq.right_hand_side.term[0], calc.Item):
01262
01263 new_eq.left_hand_side.term[0].set_factor(0, calc.Item(1))
01264 new_eq.set_hand_side("right",
01265 calc.Fraction(('+',
01266 new_eq.right_hand_side.term[0],
01267 calc.Item(coefficient)
01268 ))
01269 )
01270 new_eq.right_hand_side.term[0].set_down_numerator_s_minus_sign()
01271
01272 else:
01273 new_eq.left_hand_side.term[0].set_factor(0, calc.Item(1))
01274 new_eq.right_hand_side.set_term(0,
01275 calc.Quotient(('+',
01276 new_eq.right_hand_side.term[0],
01277 coefficient
01278 ),
01279 use_divide_symbol = 'yes')
01280 )
01281
01282
01283
01284
01285
01286
01287 elif isinstance(new_eq.left_hand_side.term[0], calc.Item) \
01288 and new_eq.left_hand_side.term[0].is_literal():
01289
01290 if new_eq.left_hand_side.term[0].get_sign() == '-':
01291 new_eq.left_hand_side.term[0].set_opposite_sign()
01292 new_eq.right_hand_side.term[0].set_opposite_sign()
01293 else:
01294
01295 if new_eq.left_hand_side.term[0].exponent == calc.Value(2):
01296
01297 if new_eq.right_hand_side.term[0].is_negative():
01298 return _("This equation has no solution.")
01299
01300 elif new_eq.left_hand_side.is_equivalent_to_a_single_0():
01301 new_eq.left_hand_side.term[0].exponent = calc.Value(1)
01302
01303 else:
01304 temp_sqrt1 = calc.SquareRoot(new_eq.\
01305 right_hand_side.term[0])
01306 temp_sqrt2 = calc.SquareRoot(temp_sqrt1)
01307 temp_sqrt2.set_sign('-')
01308 temp_item = calc.Item(new_eq.left_hand_side.term[0])
01309 temp_item.exponent = calc.Value(1)
01310 new_eq1 = Equation((temp_item,
01311 temp_sqrt1))
01312 new_eq2 = Equation((temp_item,
01313 temp_sqrt2))
01314
01315 if 'pythagorean_mode' in options:
01316 new_eq2 = " " + _("because") + " " \
01317 + temp_item.make_string(\
01318 options['pythagorean_mode'],
01319 force_expression_begins=True) \
01320 + " " + _("is positive.")
01321
01322 return (new_eq1, new_eq2)
01323
01324
01325
01326
01327 else:
01328 return None
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 new_eq.set_hand_side("left",
01339 new_eq.left_hand_side.throw_away_the_neutrals()
01340 )
01341 new_eq.set_hand_side("right",
01342 new_eq.right_hand_side.throw_away_the_neutrals()
01343 )
01344
01345
01346
01347
01348
01349
01350
01351
01352 debug.write("\nLeaving [solve_next_step] " \
01353 + "with Equation :\n" \
01354 + str(new_eq) + "\n",
01355 case=debug.solve_next_step)
01356 return new_eq
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368 def make_string(self, markup, **options):
01369 global expression_begins
01370
01371 beginning = ''
01372
01373 if 'display_name' in options:
01374 if self.number == '':
01375 beginning = markup['opening_bracket'] \
01376 + self.name \
01377 + markup['closing_bracket'] \
01378 + markup['colon'] \
01379 + markup['space']
01380 else:
01381 beginning = markup['opening_bracket'] \
01382 + self.name \
01383 + markup['opening_subscript'] \
01384 + str(self.number) \
01385 + markup['closing_subscript'] \
01386 + markup['closing_bracket'] \
01387 + markup['colon'] \
01388 + markup['space']
01389
01390 left = self.left_hand_side.make_string(markup,
01391 force_expression_begins=True)
01392
01393 right = self.right_hand_side.make_string(markup,
01394 force_expression_begins=True)
01395
01396 egal_sign = markup['equal']
01397
01398 if self.left_hand_side.contains_a_rounded_number() \
01399 or self.right_hand_side.contains_a_rounded_number():
01400
01401 egal_sign = markup['simeq']
01402
01403 return beginning \
01404 + left \
01405 + egal_sign \
01406 + right
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418 def auto_resolution(self, markup, **options):
01419 global expression_begins
01420
01421
01422 result = ""
01423
01424 if not 'dont_display_equations_name' in options:
01425 if self.number == '':
01426 result = markup['opening_expression'] \
01427 + markup['opening_bracket'] \
01428 + self.name \
01429 + markup['closing_bracket'] \
01430 + markup['colon'] \
01431 + markup['space'] \
01432 + markup['closing_expression']
01433 else:
01434 result = markup['opening_expression'] \
01435 + markup['opening_bracket'] \
01436 + self.name \
01437 + markup['opening_subscript'] \
01438 + str(self.number) \
01439 + markup['closing_subscript'] \
01440 + markup['closing_bracket'] \
01441 + markup['colon'] \
01442 + markup['space'] \
01443 + markup['closing_expression']
01444
01445
01446
01447 eq_aux = Equation(self)
01448 eq_aux1 = None
01449 eq_aux2 = None
01450 equation_did_split_in_two = False
01451 go_on = True
01452
01453 while go_on:
01454 if not equation_did_split_in_two:
01455
01456 next_eq_aux = eq_aux.solve_next_step(**options)
01457
01458 if next_eq_aux == None and 'unit' in options:
01459 result += markup['opening_math'] \
01460 + eq_aux.make_string(markup) \
01461 + " " + str(options['unit']) \
01462 + markup['closing_math']
01463 else:
01464 result += markup['opening_math'] \
01465 + eq_aux.make_string(markup) \
01466 + markup['closing_math']
01467
01468 if next_eq_aux == None or type(next_eq_aux) == str \
01469 or isinstance(next_eq_aux, tuple):
01470
01471 eq_aux = next_eq_aux
01472 else:
01473 eq_aux = Equation(next_eq_aux)
01474
01475 if isinstance(eq_aux, tuple):
01476 (eq_aux1, eq_aux2) = eq_aux
01477 equation_did_split_in_two = True
01478
01479 elif isinstance(eq_aux, str) or eq_aux == None:
01480 go_on = False
01481
01482 else:
01483 if isinstance(eq_aux1, Equation):
01484 next_eq_aux1 = eq_aux1.solve_next_step(**options)
01485
01486 if isinstance(eq_aux2, Equation):
01487 next_eq_aux2 = eq_aux2.solve_next_step(**options)
01488
01489 if eq_aux1 != None or eq_aux2 != None:
01490 result += markup['opening_math']
01491
01492 if isinstance(eq_aux1, Equation):
01493 result += eq_aux1.make_string(markup)
01494
01495 if next_eq_aux1 == None and 'unit' in options:
01496 result += " " + str(options['unit'])
01497
01498 if isinstance(eq_aux2, Equation):
01499 result += " " + _("or") + " "
01500
01501 elif eq_aux1 != None:
01502 result += eq_aux1
01503
01504 if isinstance(eq_aux2, Equation):
01505 result += eq_aux2.make_string(markup)
01506
01507 if next_eq_aux2 == None and 'unit' in options:
01508 result += " " + str(options['unit'])
01509
01510 elif eq_aux2 != None:
01511 result += eq_aux2
01512 eq_aux2 = None
01513
01514 if not isinstance(eq_aux1, Equation) \
01515 and not isinstance(eq_aux2, Equation):
01516
01517 go_on = False
01518
01519 if eq_aux1 != None or eq_aux2 != None:
01520 result += markup['closing_math']
01521
01522 if isinstance(eq_aux1, Equation):
01523 eq_aux1 = eq_aux1.solve_next_step(**options)
01524
01525 if isinstance(eq_aux2, Equation):
01526 eq_aux2 = eq_aux2.solve_next_step(**options)
01527
01528
01529
01530
01531 if (not equation_did_split_in_two):
01532 if eq_aux == None:
01533 pass
01534 else:
01535 result += eq_aux + markup['newline']
01536 else:
01537 if eq_aux1 == None and eq_aux2 == None:
01538 pass
01539 else:
01540 if eq_aux1 == None:
01541 result += eq_aux2 + markup['newline']
01542 else:
01543 result += eq_aux1 + markup['newline']
01544
01545 return result
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557