00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 import math, decimal, locale
00029 import error
00030 import obj
00031 import __
00032 import is_
00033 import alphabet
00034 import randomly
00035 import default
00036 import lib
00037 import debug
00038
00039 if debug.ENABLED:
00040 import latex
00041 import machine
00042
00043 try:
00044 locale.setlocale(locale.LC_ALL, default.LANGUAGE + '.' + default.ENCODING)
00045 except:
00046 locale.setlocale(locale.LC_ALL, '')
00047
00048
00049
00050 CONSTANT_TERMS_MAXIMUM_RATIO = 0.4
00051
00052
00053
00054 CONSTANT_TERMS_MINIMUM_NUMBER = 1
00055
00056
00057 expression_begins = True
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 def reduce_literal_items_product(provided_list):
00069 aux_dict = {}
00070
00071 if not isinstance(provided_list, list):
00072 raise error.UncompatibleType(provided_list, "A list")
00073
00074 for i in xrange(len(provided_list)):
00075 if isinstance(provided_list[i], Item):
00076 if provided_list[i].is_literal():
00077 if not provided_list[i].value in aux_dict:
00078 aux_dict[provided_list[i].value] = \
00079 provided_list[i].exponent.value
00080 else:
00081 aux_dict[provided_list[i].value] += \
00082 provided_list[i].exponent.value
00083 elif isinstance(provided_list[i], Product):
00084 if len(provided_list[i].factor) == 1:
00085 if isinstance(provided_list[i].factor[0], Item):
00086 if provided_list[i].factor[0].is_literal():
00087 if not provided_list[i].factor[0].value in aux_dict:
00088 aux_dict[provided_list[i].factor[0].value] = \
00089 provided_list[i].exponent \
00090 * provided_list[i].factor[0].exponent
00091 else:
00092 aux_dict[provided_list[i].factor[0].value] += \
00093 provided_list[i].exponent \
00094 * provided_list[i].factor[0].exponent
00095 else:
00096 raise error.UncompatibleType( \
00097 provided_list[i].factor[0], \
00098 "This Item should be a literal")
00099 else:
00100 raise error.UncompatibleType(provided_list[i].factor[0], \
00101 "This object should be an Item")
00102 else:
00103 raise error.UncompatibleType(provided_list[i], \
00104 "This Product should contain exactly\
00105 one object (and this should be a \
00106 literal Item)")
00107 else:
00108 raise error.UncompatibleType(provided_list[i], \
00109 "A literal Item or a Product \
00110 containing only one literal Item")
00111
00112 reduced_list = []
00113
00114 for key in aux_dict:
00115 aux_item = Item(('+', key, aux_dict[key]))
00116 reduced_list.append(aux_item)
00117
00118 return reduced_list
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 def put_term_in_lexicon(provided_key, associated_coeff, lexi):
00135
00136 key_s_been_found = False
00137
00138
00139
00140
00141
00142 for key in lexi:
00143 if provided_key == key:
00144
00145
00146 lexi[key].append(associated_coeff)
00147 key_s_been_found = True
00148
00149 if not key_s_been_found:
00150 new_coeff_sum = Sum([associated_coeff])
00151 lexi[provided_key] = new_coeff_sum
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 class Calculable(obj.Printable):
00165
00166
00167
00168
00169
00170
00171
00172
00173 def alphabetical_order_cmp(self, other_objct):
00174
00175 if self.is_numeric() and other_objct.is_numeric():
00176 return 0
00177
00178 elif self.is_literal() and other_objct.is_numeric():
00179 return 1
00180
00181 elif self.is_numeric() and other_objct.is_literal():
00182 return -1
00183
00184 elif self.is_literal() and other_objct.is_literal():
00185 self_value = self.get_letter()
00186 other_value = other_objct.get_letter()
00187
00188
00189 if self_value == other_value:
00190 return 0
00191 elif alphabet.order[self_value] > alphabet.order[other_value]:
00192 return 1
00193 else:
00194 return -1
00195
00196
00197
00198
00199
00200
00201
00202
00203 def is_numeric(self):
00204 raise error.MethodShouldBeRedefined(self, 'is_numeric')
00205
00206
00207
00208
00209
00210
00211
00212
00213 def is_literal(self):
00214 raise error.MethodShouldBeRedefined(self, 'is_literal')
00215
00216
00217
00218
00219
00220
00221
00222
00223 def is_null(self):
00224 raise error.MethodShouldBeRedefined(self, 'is_null')
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 def get_letter(self):
00235 raise error.MethodShouldBeRedefined(self, 'get_letter')
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 def is_equivalent_to_a_single_1(self):
00246 raise error.MethodShouldBeRedefined(self,
00247 'is_equivalent_to_a_single_1')
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 def is_equivalent_to_a_single_minus_1(self):
00258 raise error.MethodShouldBeRedefined(self,
00259 'is_equivalent_to_a_single_minus_1')
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 def is_equivalent_to_a_single_0(self):
00271 raise error.MethodShouldBeRedefined(self,
00272 'is_equivalent_to_a_single_0')
00273
00274
00275
00276
00277
00278
00279
00280
00281 def is_equivalent_to_a_single_neutral(self, elt):
00282 if elt == Item(0):
00283 return self.is_equivalent_to_a_single_0()
00284 elif elt == Item(1):
00285 return self.is_equivalent_to_a_single_1()
00286 else:
00287 print str(elt)
00288 print str(Item(0))
00289 raise error.UncompatibleType(elt, "neutral element for addition" \
00290 + " or multiplication, e.g." \
00291 + " Item(1) | Item(0).")
00292
00293
00294
00295
00296
00297
00298
00299
00300 def is_equivalent_to_a_single_numeric_Item(self):
00301 raise error.MethodShouldBeRedefined(self,
00302 'is_equivalent_to_a_single_numeric_Item')
00303
00304
00305
00306
00307
00308
00309
00310
00311 def is_equivalent_to_an_irreducible_Fraction(self):
00312 raise error.MethodShouldBeRedefined(self,
00313 'is_equivalent_to_an_irreducible_Fraction')
00314
00315
00316
00317
00318
00319
00320
00321
00322 def evaluate(self):
00323 raise error.MethodShouldBeRedefined(self, 'evaluate')
00324
00325
00326
00327
00328
00329
00330
00331
00332 def calculate_next_step(self, **options):
00333 raise error.MethodShouldBeRedefined(self, 'calculate_next_step')
00334
00335
00336
00337
00338
00339
00340
00341
00342 def deep_copy(self):
00343 result = object.__new__(type(self))
00344 result.__init__(self)
00345 return result
00346
00347
00348
00349
00350
00351
00352
00353
00354 def times(self, objct):
00355 res = Product([self, objct])
00356 res.set_compact_display(False)
00357 return res
00358
00359
00360
00361
00362
00363
00364
00365
00366 def plus(self, objct):
00367 return Sum([self, objct])
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396 class Value(Calculable):
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 def __init__(self, arg):
00412 self.has_been_rounded = False
00413
00414 if type(arg) == float \
00415 or type(arg) == int \
00416 or type(arg) == long \
00417 or type(arg) == decimal.Decimal:
00418
00419 self.value = decimal.Decimal(str(arg))
00420
00421 elif type(arg) == str:
00422 if is_.a_numerical_string(arg):
00423 self.value = decimal.Decimal(arg)
00424 else:
00425 self.value = arg
00426
00427 elif isinstance(arg, Value):
00428 self.value = arg.value
00429 self.has_been_rounded = arg.has_been_rounded
00430
00431
00432 else:
00433 raise error.UncompatibleType(arg, "Number|String")
00434
00435
00436
00437
00438
00439
00440 def __str__(self, **options):
00441 return "." + str(self.value) + "."
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453 def __cmp__(self, other_value):
00454 if not isinstance(other_value, Value):
00455 return -1
00456
00457 if self.value == other_value.value:
00458 return 0
00459 else:
00460 return -1
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 def __len__(self):
00471 return 1
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 def __mul__(self, objct):
00482 if isinstance(objct, Calculable):
00483 return self.value * objct.evaluate()
00484 else:
00485 return self.value * objct
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 def __add__(self, objct):
00496 if isinstance(objct, Calculable):
00497 return self.value + objct.evaluate()
00498 else:
00499 return self.value + objct
00500
00501
00502
00503
00504
00505
00506
00507
00508 def is_numeric(self):
00509 if type(self.value) == float \
00510 or type(self.value) == int \
00511 or type(self.value) == long \
00512 or type(self.value) == decimal.Decimal:
00513
00514 return True
00515 else:
00516 return False
00517
00518
00519
00520
00521
00522
00523
00524
00525 def is_literal(self):
00526 if type(self.value) == str:
00527
00528 return True
00529 else:
00530 return False
00531
00532
00533
00534
00535
00536
00537
00538
00539 def is_null(self):
00540 if self.is_numeric() and self.value == 0:
00541 return True
00542 else:
00543 return False
00544
00545
00546
00547
00548
00549
00550
00551
00552 def get_letter(self):
00553 if self.is_literal():
00554 return self.value
00555 else:
00556 raise error.UncompatibleType(self, "str, i.e. literal Value")
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 def is_equivalent_to_a_single_1(self):
00567 if self.is_numeric() and self.value == 1:
00568 return True
00569 else:
00570 return False
00571
00572
00573
00574
00575
00576
00577
00578
00579 def is_equivalent_to_a_single_minus_1(self):
00580 if self.is_numeric() and self.value == -1:
00581 return True
00582 else:
00583 return False
00584
00585
00586
00587
00588
00589
00590
00591
00592 def is_equivalent_to_a_single_0(self):
00593 if self.is_numeric() and self.value == 0:
00594 return True
00595 else:
00596 return False
00597
00598
00599
00600
00601
00602
00603
00604
00605 def is_equivalent_to_a_single_numeric_Item(self):
00606 return False
00607
00608
00609
00610
00611
00612
00613
00614
00615 def is_equivalent_to_an_irreducible_Fraction(self):
00616 return False
00617
00618
00619
00620
00621
00622
00623
00624 def is_a_perfect_square(self):
00625 if not self.is_numeric():
00626 raise error.UncompatibleType(self, "numeric Value")
00627
00628 return not self.sqrt().needs_to_get_rounded(0)
00629
00630
00631
00632
00633
00634
00635
00636
00637 def evaluate(self):
00638 if not self.is_numeric():
00639 raise error.UncompatibleType(self, "numeric Value")
00640 else:
00641 return self.value
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651 def calculate_next_step(self, **options):
00652 return None
00653
00654
00655
00656
00657
00658
00659 def sqrt(self):
00660 if self.is_numeric():
00661 return Value(self.value.sqrt())
00662 else:
00663 raise error.UncompatibleType(self, "numeric Value")
00664
00665
00666
00667
00668
00669
00670 def round(self, precision):
00671 if not self.is_numeric():
00672 raise error.UncompatibleType(self, "numeric Value")
00673 elif not (precision in [__.UNIT,
00674 __.TENTH,
00675 __.HUNDREDTH,
00676 __.THOUSANDTH,
00677 __.TEN_THOUSANDTH] \
00678 or (type(precision) == int and precision >= 0 and precision <= 4)):
00679
00680 raise error.UncompatibleType(precision, "must be __.UNIT or" \
00681 + "__.TENTH, " \
00682 + "__.HUNDREDTH, " \
00683 + "__.THOUSANDTH, " \
00684 + "__.TEN_THOUSANDTH, "\
00685 + "or 0, 1, 2, 3 or 4.")
00686 else:
00687 result_value = None
00688
00689 if type(precision) == int:
00690 result_value = Value(self.value.quantize(decimal.Decimal( \
00691 __.PRECISION[precision]),
00692 rounding=decimal.ROUND_HALF_UP) \
00693 .normalize())
00694 else:
00695 result_value = Value(self.value.quantize(decimal.Decimal( \
00696 precision),
00697 rounding=decimal.ROUND_HALF_UP) \
00698 .normalize())
00699
00700 if self.needs_to_get_rounded(precision):
00701 result_value.has_been_rounded = True
00702
00703 return result_value
00704
00705
00706
00707
00708
00709
00710
00711 def digits_number(self):
00712 if not self.is_numeric():
00713 raise error.UncompatibleType(self, "numeric Value")
00714 else:
00715 temp_result = len(str((self.value \
00716 - self.value.quantize( \
00717 decimal.Decimal(__.UNIT),
00718 rounding=decimal.ROUND_DOWN) \
00719 ))) \
00720 - 2
00721 if temp_result < 0:
00722 return 0
00723 else:
00724 return temp_result
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735 def needs_to_get_rounded(self, precision):
00736 if not (precision in [__.UNIT,
00737 __.TENTH,
00738 __.HUNDREDTH,
00739 __.THOUSANDTH,
00740 __.TEN_THOUSANDTH] \
00741 or (type(precision) == int and precision >= 0 and precision <= 4)):
00742
00743 raise error.UncompatibleType(precision, "must be __.UNIT or" \
00744 + "__.TENTH, " \
00745 + "__.HUNDREDTH, " \
00746 + "__.THOUSANDTH, " \
00747 + "__.TEN_THOUSANDTH, "\
00748 + "or 0, 1, 2, 3 or 4.")
00749
00750 precision_to_test = 0
00751
00752 if type(precision) == int:
00753 precision_to_test = precision
00754 else:
00755 precision_to_test = __.PRECISION[precision]
00756
00757 return self.digits_number() > precision_to_test
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767 def make_string(self, markup, **options):
00768 if self.is_numeric():
00769 return locale.str(self.value)
00770 else:
00771 return str(self.value)
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787 class Exponented(Calculable):
00788
00789
00790
00791
00792
00793
00794 def __mul__(self, objct):
00795 return self.times(objct)
00796
00797
00798
00799
00800
00801
00802
00803
00804 def __add__(self, objct):
00805 return self.plus(objct)
00806
00807
00808
00809
00810
00811
00812
00813
00814 def get_sign(self):
00815 raise error.MethodShouldBeRedefined(self, 'get_sign')
00816
00817
00818
00819
00820
00821
00822
00823
00824 def get_minus_signs_nb(self):
00825 raise error.MethodShouldBeRedefined(self, 'get_minus_signs_nb')
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836 def set_exponent(self, arg):
00837 if isinstance(arg, Calculable):
00838 self.exponent = arg.deep_copy()
00839 else:
00840 self.exponent = Value(arg)
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851 def set_sign(self, arg):
00852 if is_.a_sign(arg):
00853 self.sign = arg
00854 elif arg == 1:
00855 self.sign = '+'
00856 elif arg == -1:
00857 self.sign = '-'
00858 elif isinstance(arg, Calculable):
00859 if arg.is_equivalent_to_a_single_1():
00860 self.sign = '+'
00861 elif arg.is_equivalent_to_a_single_minus_1():
00862 self.sign = '-'
00863 else:
00864 raise error.UncompatibleType(self, "'+' or '-' or 1 or -1")
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 def set_opposite_sign(self):
00876 if self.get_sign() == '-':
00877 self.set_sign('+')
00878 elif self.get_sign() == '+':
00879 self.set_sign('-')
00880 else:
00881
00882 raise error.WrongObject("The sign of the object " \
00883 + str(self) \
00884 + " is " \
00885 + str(self.get_sign) \
00886 + " instead of '+' or '-'.")
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 def multiply_symbol_is_required(self, objct, position):
00899 raise error.MethodShouldBeRedefined(self,
00900 'multiply_symbol_is_required')
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912 def requires_brackets(self, position):
00913 raise error.MethodShouldBeRedefined(self, 'requires_brackets')
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925 def requires_inner_brackets(self):
00926 raise error.MethodShouldBeRedefined(self,
00927 'requires_innner_brackets')
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937 def exponent_must_be_displayed(self):
00938 if not self.exponent.is_equivalent_to_a_single_1():
00939 return True
00940 else:
00941 return False
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 def contains_exactly(self, objct):
00955 raise error.MethodShouldBeRedefined(self, 'contains_exactly')
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 def contains_a_rounded_number(self):
00967 raise error.MethodShouldBeRedefined(self, 'contains_a_rounded_number')
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977 def calculate_next_step(self, **options):
00978 raise error.MethodShouldBeRedefined(self, 'calculate_next_step')
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990 def expand_and_reduce_next_step(self, **options):
00991 raise error.MethodShouldBeRedefined(self,
00992 'expand_and_reduce_next_step')
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 class Item(Exponented):
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032 def __init__(self, arg):
01033 self.is_out_striked = False
01034 self.force_display_sign_once = False
01035 self.exponent = Value(1)
01036 self.sign = '+'
01037 self.unit = None
01038
01039
01040
01041
01042
01043 if is_.a_number(arg):
01044 if arg > 0:
01045 self.value_object = Value(arg)
01046 else:
01047 self.sign = '-'
01048 self.value_object = Value(-arg)
01049
01050
01051
01052
01053
01054 elif is_.a_string(arg) and len(arg) >= 1:
01055 if is_.a_sign(arg[0]) and len(arg) >= 2:
01056 self.sign = arg[0]
01057 self.value_object = Value(arg[1:len(arg)])
01058 else:
01059 self.sign = '+'
01060 self.value_object = Value(arg)
01061
01062
01063 elif type(arg) == Item :
01064 self.sign = arg.sign
01065 self.value_object = arg.value_object.deep_copy()
01066 self.exponent = arg.exponent.deep_copy()
01067 self.is_out_striked = arg.is_out_striked
01068 self.force_display_sign_once = arg.force_display_sign_once
01069
01070
01071 elif type(arg) == tuple and len(arg) == 3 and is_.a_sign(arg[0]) \
01072 and (is_.a_number(arg[1]) or is_.a_string(arg[1])) \
01073 and (is_.a_number(arg[2]) or is_.a_calculable(arg[2]) \
01074 or isinstance(arg[2], Value)):
01075
01076 self.sign = arg[0]
01077 self.value_object = Value(arg[1])
01078 if isinstance(arg[2], Exponented):
01079 self.exponent = arg[2].deep_copy()
01080 else:
01081 self.exponent = Value(arg[2])
01082
01083
01084 elif type(arg) == tuple and len(arg) == 2 and is_.a_sign(arg[0]) \
01085 and (is_.a_number(arg[1]) or is_.a_string(arg[1])):
01086
01087 self.sign = arg[0]
01088 self.value_object = Value(arg[1])
01089
01090
01091 elif arg == None:
01092 self.value_object = Value(1)
01093
01094
01095 elif isinstance(arg, Monomial) and arg.is_numeric()\
01096 and isinstance(arg.factor[0], Item):
01097
01098 self.sign = arg.get_sign()
01099 self.value_object = Value(arg.factor[0].value)
01100
01101
01102 elif isinstance(arg, Value):
01103 if arg.is_numeric():
01104 if arg.value < 0:
01105 self.sign = '-'
01106 self.value_object = Value(-arg.value)
01107 else:
01108 self.sign = '+'
01109 self.value_object = Value(arg.value)
01110 else:
01111 self.sign = '+'
01112 self.value_object = Value(arg.value)
01113
01114 self.value_object.has_been_rounded = arg.has_been_rounded
01115
01116
01117
01118
01119 else:
01120 raise error.UncompatibleType(arg,
01121 "Number|String|Item|" \
01122 + "(sign, Number|String, exponent)|" \
01123 + "(sign, Number|String)")
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 def __str__(self, **options):
01135 if self.is_out_striked:
01136 begining = " s{"
01137 else:
01138 begining = " {"
01139 return begining \
01140 + self.sign \
01141 + str(self.value) \
01142 + "^" \
01143 + str(self.exponent) +"} "
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 def __cmp__(self, other_item):
01155 if not isinstance(other_item, Item):
01156 return -1
01157
01158 if self.sign == other_item.sign \
01159 and self.value == other_item.value \
01160 and self.exponent == other_item.exponent:
01161 return 0
01162 else:
01163 return -1
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173 def __len__(self):
01174 return 1
01175
01176
01177
01178
01179
01180
01181
01182 def is_numeric(self):
01183 if self.value_object.is_numeric() and self.exponent.is_numeric():
01184 return True
01185 else:
01186 return False
01187
01188
01189
01190
01191
01192
01193
01194
01195 def is_literal(self):
01196 if self.value_object.is_literal() or self.exponent.is_literal(): \
01197 return True
01198 else:
01199 return False
01200
01201
01202
01203
01204
01205
01206
01207
01208 def is_null(self):
01209 if self.exponent.evaluate() == lib.ZERO_POLYNOMIAL_DEGREE \
01210 or (self.value_object.is_null()):
01211
01212 return True
01213 else:
01214 return False
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 def is_negative(self):
01226 if self.sign == '-':
01227 return True
01228 else:
01229 return False
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 def is_positive(self):
01241 if self.sign == '+':
01242 return True
01243 else:
01244 return False
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254 def turn_into_fraction(self):
01255 return Fraction(('+', self, Item(1)))
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 def is_equivalent_to_a_single_1(self):
01266 if self.sign == '+':
01267 if (self.exponent.is_null()) \
01268 or (self.value_object.is_equivalent_to_a_single_1()):
01269
01270 return True
01271
01272 return False
01273
01274
01275
01276
01277
01278
01279
01280
01281 def is_equivalent_to_a_single_minus_1(self):
01282 if self.sign == '-':
01283 if self.exponent.is_null() \
01284 or (self.value_object.is_equivalent_to_a_single_1()):
01285
01286 return True
01287
01288 if self.sign == '+':
01289 if self.value_object.is_equivalent_to_a_single_minus_1() \
01290 and lib.is_uneven(self.exponent):
01291
01292 return True
01293
01294 return False
01295
01296
01297
01298
01299
01300
01301
01302
01303 def is_equivalent_to_a_single_0(self):
01304 return self.is_null()
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 def is_equivalent_to_a_single_numeric_Item(self):
01315 return self.is_numeric()
01316
01317
01318
01319
01320
01321
01322
01323
01324 def is_equivalent_to_an_irreducible_Fraction(self):
01325 return False
01326
01327
01328
01329
01330
01331
01332
01333
01334 def is_expandable(self):
01335 return False
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347 def multiply_symbol_is_required(self, objct, position):
01348
01349
01350
01351 if isinstance(objct, Item):
01352
01353 if ((self.is_numeric() or self.is_equivalent_to_a_single_1()) \
01354 and (objct.is_numeric() \
01355 or objct.is_equivalent_to_a_single_1())):
01356
01357 return True
01358
01359
01360 elif self.is_literal() \
01361 and (objct.is_numeric() \
01362 or objct.is_equivalent_to_a_single_1()):
01363
01364 return True
01365
01366 elif self.is_numeric() and objct.is_literal():
01367 if self.value == 1 \
01368 or self.requires_brackets(position) \
01369 or objct.requires_brackets(position +1):
01370
01371 return True
01372 else:
01373 return False
01374
01375 elif self.is_literal() and objct.is_literal():
01376 if self.requires_brackets(position) \
01377 or objct.requires_brackets(position +1):
01378
01379 return True
01380 else:
01381 if not self.exponent_must_be_displayed() \
01382 and self.value == objct.value:
01383
01384 return True
01385 else:
01386 return False
01387
01388
01389 if isinstance(objct, Product):
01390 return self.multiply_symbol_is_required(objct.factor[0],
01391 position)
01392
01393
01394 if isinstance(objct, Sum):
01395 if len(objct.throw_away_the_neutrals()) >= 2:
01396 if self.is_numeric() and self.value == 1:
01397 return True
01398 else:
01399 return False
01400 else:
01401 return self.multiply_symbol_is_required(objct.\
01402 throw_away_the_neutrals().term[0],
01403 position)
01404
01405
01406 if isinstance(objct, Quotient):
01407 return True
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 def requires_brackets(self, position):
01420
01421 if position == 0:
01422 return False
01423
01424 elif self.sign == '+':
01425
01426
01427
01428
01429 if self.is_literal() and self.value[0] == '-':
01430 return True
01431 else:
01432 return False
01433 elif self.sign == '-':
01434 return True
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452 def requires_inner_brackets(self):
01453
01454 if (self.is_numeric() and self.value < 0) \
01455 or (self.is_literal() and self.value[0] == '-'):
01456
01457
01458 if self.is_negative():
01459 return True
01460
01461
01462
01463
01464
01465
01466 if (isinstance(self.exponent, Value) \
01467 or isinstance(self.exponent, Item)) \
01468 and self.exponent.is_numeric():
01469
01470 if lib.is_even(self.exponent):
01471 return True
01472
01473
01474 elif self.exponent.is_literal():
01475 return True
01476
01477
01478
01479
01480
01481
01482
01483 elif is_.a_calculable(self.exponent) \
01484 and not isinstance(self.exponent, Item):
01485
01486 if self.exponent.is_equivalent_to_a_single_1():
01487 return False
01488 elif isinstance(self.exponent, Operation) \
01489 and len(self.exponent) == 1 \
01490 and not self.exponent.exponent_must_be_displayed():
01491
01492 aux_item = Item((self.sign,
01493 self.value,
01494 self.exponent.element[0]))
01495 return aux_item.requires_inner_brackets()
01496
01497 else:
01498 return True
01499
01500 return False
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511 def contains_exactly(self, objct):
01512 return False
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523 def contains_a_rounded_number(self):
01524 return self.value_object.has_been_rounded
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535 def get_value(self):
01536 return self.value_object.value
01537
01538 value = property(get_value, doc = "Item's value")
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548 def get_sign(self):
01549 if self.is_null():
01550 return '+'
01551 else:
01552 return self.sign
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562 def get_minus_signs_nb(self):
01563 nb = 0
01564
01565 if self.is_negative() and not self.is_null():
01566 nb += 1
01567
01568 if self.value < 0 and lib.is_uneven(self.exponent):
01569 nb += 1
01570
01571 return nb
01572
01573
01574
01575
01576
01577
01578
01579
01580 def get_letter(self):
01581 if self.is_literal():
01582 return self.value
01583
01584 else:
01585 raise error.UncompatibleType(self, "Litteral Item")
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596 def set_is_out_striked(self, arg):
01597 if arg:
01598 self.is_out_striked = True
01599 else:
01600 self.is_out_striked = False
01601
01602
01603
01604
01605
01606
01607
01608
01609 def set_unit(self, arg):
01610 self.unit = str(arg)
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621 def evaluate(self):
01622 expon = self.exponent.evaluate()
01623
01624 if self.is_numeric():
01625 if self.is_positive():
01626 return (self.value)**expon
01627 else:
01628 return -(self.value)**expon
01629
01630 else:
01631 raise error.IncompatibleType(self, "Number|numeric Exponented")
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646 def calculate_next_step(self, **options):
01647 if not self.is_numeric():
01648 raise error.IncompatibleType(self, "Number|numeric Exponented")
01649
01650
01651 expon_test = self.exponent.calculate_next_step(**options)
01652
01653 if expon_test != None:
01654 return Item((self.sign,
01655 self.value,
01656 expon_test
01657 ))
01658
01659 expon = self.exponent.evaluate()
01660
01661
01662
01663
01664
01665
01666 if expon != 1:
01667
01668
01669 if self.value < 0:
01670
01671 aux_inner_sign = Item(('+', -1, expon))
01672 return Item((lib.sign_of_product([self.sign,
01673 aux_inner_sign]),
01674 (- self.value)**expon,
01675 1))
01676
01677 else:
01678 return Item((self.sign,
01679 self.value ** expon,
01680 1))
01681
01682
01683 else:
01684
01685 if self.value < 0 and self.sign == '-':
01686 return Item(('+',
01687 - self.value,
01688 expon))
01689
01690
01691
01692 else:
01693 return None
01694
01695
01696
01697
01698
01699
01700
01701
01702 def round(self, precision):
01703 if not self.exponent.is_equivalent_to_a_single_1():
01704 raise error.UncompatibleType(self, "the exponent should be" \
01705 + " equivalent to a single 1")
01706 else:
01707 return Item(self.value_object.round(precision))
01708
01709
01710
01711
01712
01713
01714
01715
01716 def digits_number(self):
01717 if not self.exponent.is_equivalent_to_a_single_1():
01718 raise error.UncompatibleType(self, "the exponent should be" \
01719 + " equivalent to a single 1")
01720 else:
01721 return self.value_object.digits_number()
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735 def needs_to_get_rounded(self, precision):
01736 if not self.exponent.is_equivalent_to_a_single_1():
01737 raise error.UncompatibleType(self, "the exponent should be" \
01738 + " equivalent to a single 1")
01739
01740 return self.value_object.needs_to_get_rounded(precision)
01741
01742
01743
01744
01745
01746
01747
01748 def expand_and_reduce_next_step(self, **options):
01749 if self.is_numeric():
01750 return self.calculate_next_step(**options)
01751 else:
01752 return None
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764 def make_string(self, markup, **options):
01765 global expression_begins
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777 if 'force_expression_begins' in options \
01778 and options['force_expression_begins'] == True:
01779
01780 expression_begins = options['force_expression_begins']
01781 options['force_expression_begins'] = False
01782
01783
01784 debug.write("\n" + "[Item] Entering make_string " \
01785 + "with force_display_sign_once == " \
01786 + str(self.force_display_sign_once),
01787 case=debug.make_string_in_item)
01788
01789 resulting_string = ""
01790
01791 sign = ''
01792
01793 inner_bracket_1 = ''
01794 inner_bracket_2 = ''
01795
01796 if self.requires_inner_brackets():
01797 inner_bracket_1 = markup['opening_bracket']
01798 inner_bracket_2 = markup['closing_bracket']
01799
01800 if not expression_begins \
01801 or ('force_display_sign' in options and self.is_numeric()) \
01802 or self.force_display_sign_once:
01803
01804 if self.sign == '+' or self.is_null():
01805 sign = markup['plus']
01806 else:
01807 sign = markup['minus']
01808 if self.force_display_sign_once:
01809 self.force_display_sign_once = False
01810 else:
01811 if self.sign == '-' and not self.is_null():
01812 sign = markup['minus']
01813
01814 if self.exponent.is_equivalent_to_a_single_0():
01815
01816 if 'force_display_exponent_0' in options \
01817 or 'force_display_exponents' in options:
01818
01819 resulting_string += inner_bracket_1 \
01820 + self.value_object.make_string(markup) \
01821 + inner_bracket_2 \
01822 + markup['opening_exponent'] \
01823 + markup['zero'] \
01824 + markup['closing_exponent']
01825 else:
01826 resulting_string += markup['one']
01827
01828 elif self.exponent_must_be_displayed():
01829 if isinstance(self.exponent, Exponented):
01830 expression_begins = True
01831
01832 resulting_string += inner_bracket_1 \
01833 + self.value_object.make_string(markup) \
01834 + inner_bracket_2 \
01835 + markup['opening_exponent'] \
01836 + self.exponent.make_string(markup,
01837 **options) \
01838 + markup['closing_exponent']
01839
01840 else:
01841
01842 if 'force_display_exponent_1' in options \
01843 or 'force_display_exponents' in options:
01844
01845 resulting_string += inner_bracket_1 \
01846 + self.value_object.make_string(markup) \
01847 + inner_bracket_2 \
01848 + markup['opening_exponent'] \
01849 + markup['one'] \
01850 + markup['closing_exponent']
01851 else:
01852 resulting_string += inner_bracket_1 \
01853 + self.value_object.make_string(markup) \
01854 + inner_bracket_2
01855
01856
01857 if self.is_out_striked:
01858 resulting_string = markup['opening_out_striked'] \
01859 + resulting_string \
01860 + markup['closing_out_striked']
01861
01862 if self.unit != None and 'display_unit' in options \
01863 and (options['display_unit'] == True \
01864 or options['display_unit'] == 'yes'):
01865
01866 resulting_string += " " + str(self.unit)
01867
01868 expression_begins = False
01869
01870
01871 return sign + resulting_string
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884 class SquareRoot(Exponented):
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900 def __init__(self, arg, **options):
01901 self.force_display_sign_once = False
01902 self.sign = '+'
01903 self.radicand = Item(1)
01904
01905
01906 if isinstance(arg, SquareRoot):
01907 if 'embbed' in options \
01908 and options['embbed'] == 'yes':
01909
01910 self.radicand = arg.deep_copy()
01911 else:
01912 self.force_display_sign_once = arg.force_display_sign_once
01913 self.sign = arg.sign
01914 self.radicand = arg.radicand.deep_copy()
01915
01916
01917 elif isinstance(arg, Exponented):
01918 self.radicand = arg.deep_copy()
01919
01920
01921 elif isinstance(arg, tuple) \
01922 and len(arg) == 2 \
01923 and is_.a_sign(arg[0]) \
01924 and isinstance(arg[1], Exponented):
01925
01926 self.sign = arg[0]
01927 self.radicand = arg[1].deep_copy()
01928
01929
01930 else:
01931 raise error.UncompatibleType(arg,
01932 "Exponented")
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943 def __str__(self, **options):
01944 return " " + self.sign \
01945 + "SQR{{ " \
01946 + str(self.radicand) \
01947 + " }} "
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958 def __cmp__(self, other_item):
01959 raise error.MethodShouldBeRedefined(self,
01960 '__cmp__ in SquareRoot')
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970 def __len__(self):
01971 return 1
01972
01973
01974
01975
01976
01977
01978
01979 def is_numeric(self):
01980 return self.radicand.is_numeric()
01981
01982
01983
01984
01985
01986
01987
01988
01989 def is_literal(self):
01990 return self.radicand.is_literal()
01991
01992
01993
01994
01995
01996
01997
01998
01999 def is_null(self):
02000 return self.radicand.is_null()
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011 def is_negative(self):
02012 if self.sign == '-':
02013 return True
02014 else:
02015 return False
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026 def is_positive(self):
02027 if self.sign == '+':
02028 return True
02029 else:
02030 return False
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040 def turn_into_fraction(self):
02041 return Fraction(('+', self, Item(1)))
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051 def is_equivalent_to_a_single_1(self):
02052 if self.sign == '+':
02053 return self.radicand.is_equivalent_to_a_single_1()
02054
02055 return False
02056
02057
02058
02059
02060
02061
02062
02063
02064 def is_equivalent_to_a_single_minus_1(self):
02065 if self.sign == '-':
02066 return self.radicand.is_equivalent_to_a_single_1()
02067
02068 return False
02069
02070
02071
02072
02073
02074
02075
02076
02077 def is_equivalent_to_a_single_0(self):
02078 return self.radicand.is_null()
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088 def is_equivalent_to_a_single_numeric_Item(self):
02089 return False
02090
02091
02092
02093
02094
02095
02096
02097
02098 def is_equivalent_to_an_irreducible_Fraction(self):
02099 return False
02100
02101
02102
02103
02104
02105
02106
02107
02108 def is_expandable(self):
02109 return self.radicand.is_expandable()
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121 def multiply_symbol_is_required(self, objct, position):
02122 raise error.MethodShouldBeRedefined(self,
02123 'multiply_symbol_is_required')
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135
02136
02137
02138
02139
02140
02141
02142
02143 def requires_brackets(self, position):
02144
02145 if position == 0:
02146 return False
02147
02148
02149 elif self.sign == '+':
02150 if self.force_display_sign_once:
02151 return True
02152 else:
02153 return False
02154 elif self.sign == '-':
02155 return True
02156
02157
02158
02159
02160
02161
02162
02163
02164 def requires_inner_brackets(self):
02165 return False
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176 def contains_exactly(self, objct):
02177 return False
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188 def contains_a_rounded_number(self):
02189 return self.radicand.contains_a_rounded_number()
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200 def get_sign(self):
02201 if self.is_null():
02202 return '+'
02203 else:
02204 return self.sign
02205
02206
02207
02208
02209
02210
02211
02212
02213
02214 def get_minus_signs_nb(self):
02215 if self.is_negative() and not self.is_null():
02216 return 1
02217 else:
02218 return 0
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230 def calculate_next_step(self, **options):
02231 if not self.is_numeric():
02232 return self.radicand.expand_and_reduce_next_step()
02233
02234
02235
02236 if 'decimal_result' in options \
02237 and self.radicand.calculate_next_step() == None:
02238
02239 result = Item(Value(self.radicand.evaluate()).sqrt()\
02240 .round(options['decimal_result'])
02241 )
02242
02243 result.set_sign(self.sign)
02244
02245 return result
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255 elif self.radicand.calculate_next_step() == None \
02256 and Value(self.radicand.evaluate()).is_a_perfect_square():
02257
02258 result = Item(Value(self.radicand.evaluate()).sqrt()
02259
02260
02261 )
02262
02263 result.set_sign(self.sign)
02264
02265 return result
02266
02267
02268
02269
02270 else:
02271 return None
02272
02273
02274
02275
02276
02277
02278
02279
02280 def expand_and_reduce_next_step(self, **options):
02281 if self.is_numeric():
02282 return self.calculate_next_step(**options)
02283 else:
02284 return radicand.expand_and_reduce_next_step(**options)
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296 def make_string(self, markup, **options):
02297 global expression_begins
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310 if 'force_expression_begins' in options \
02311 and options['force_expression_begins'] == True:
02312
02313 expression_begins = options['force_expression_begins']
02314 options['force_expression_begins'] = False
02315
02316 resulting_string = ""
02317
02318 sign = ''
02319
02320 if not expression_begins \
02321 or ('force_display_sign' in options and self.is_numeric()) \
02322 or self.force_display_sign_once:
02323
02324 if self.sign == '+' or self.is_null():
02325 sign = markup['plus']
02326 else:
02327 sign = markup['minus']
02328 if self.force_display_sign_once:
02329 self.force_display_sign_once = False
02330 else:
02331 if self.sign == '-' and not self.is_null():
02332 sign = markup['minus']
02333
02334
02335 resulting_string = sign + markup['opening_sqrt'] \
02336 + self.radicand.make_string(markup) \
02337 + markup['closing_sqrt']
02338
02339 expression_begins = False
02340
02341 return resulting_string
02342
02343
02344
02345
02346
02347
02348
02349
02350
02351
02352
02353 class Operation(Exponented):
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364 def __init__(self):
02365
02366 self.element = list()
02367
02368
02369
02370 self.neutral = None
02371
02372
02373
02374 self.symbol = None
02375
02376
02377 self.exponent = Value(1)
02378
02379
02380
02381
02382 self.str_openmark = ""
02383 self.str_closemark = ""
02384
02385
02386 self.compact_display = True
02387 self.info = []
02388
02389
02390
02391
02392
02393
02394
02395
02396 def operator(self, arg1, arg2):
02397 raise error.MethodShouldBeRedefined(self, 'operator')
02398
02399
02400
02401
02402
02403
02404
02405
02406 def __iter__(self):
02407 return iter(self.element)
02408
02409 def next(self):
02410 return self.element.next()
02411
02412
02413
02414
02415
02416
02417
02418
02419 def __getitem__(self, i):
02420 return self.element[i]
02421
02422
02423 def __setitem__(self, i, data):
02424 self.element[i] = data
02425
02426
02427
02428
02429
02430
02431
02432
02433 def __len__(self):
02434 return len(self.element)
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446 def __str__(self, **options):
02447 elements_list_string = ""
02448 for i in xrange(len(self)):
02449 elements_list_string += str(self.element[i])
02450 if i < len(self) - 1:
02451 elements_list_string += ' ' + self.symbol + ' '
02452
02453 info = ""
02454 if 'info' in options:
02455 info = str(self.compact_display) \
02456 + "|" \
02457 + "|" \
02458 + str(self.info) \
02459 + "||"
02460
02461 expo = ""
02462 if not self.exponent.is_equivalent_to_a_single_1():
02463 expo = "^{" + str(self.exponent) + "}"
02464
02465 return self.str_openmark \
02466 + info \
02467 + elements_list_string \
02468 + self.str_closemark \
02469 + expo \
02470 + " "
02471
02472
02473
02474
02475
02476
02477
02478
02479 def is_numeric(self):
02480 for elt in self:
02481 if not elt.is_numeric():
02482 return False
02483
02484 return True
02485
02486
02487
02488
02489
02490
02491
02492
02493 def is_literal(self):
02494 for elt in self:
02495 if not elt.is_literal():
02496 return False
02497
02498 return True
02499
02500
02501
02502
02503
02504
02505
02506 def is_equivalent_to_a_single_neutral(self, neutral_elt):
02507 for elt in self:
02508 if not elt.is_equivalent_to_a_single_neutral(neutral_elt):
02509 return False
02510
02511 return True
02512
02513
02514
02515
02516
02517
02518
02519
02520 def is_equivalent_to_a_single_numeric_Item(self):
02521 if not self.is_numeric() or not len(self) == 1:
02522 return False
02523 else:
02524 return self.element[0].is_equivalent_to_a_single_numeric_Item()
02525
02526
02527
02528
02529
02530
02531
02532
02533 def is_equivalent_to_an_irreducible_Fraction(self):
02534 if not self.is_numeric() or not len(self) == 1:
02535 return False
02536 else:
02537 return self.element[0].is_equivalent_to_an_irreducible_Fraction()
02538
02539
02540
02541
02542
02543
02544
02545
02546 def is_expandable(self):
02547 for elt in self.element:
02548 if elt.is_expandable():
02549 return True
02550
02551 return False
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563 def contains_exactly(self, objct):
02564 if len(self) != 1:
02565 return False
02566 elif self.element[0] == objct:
02567 return True
02568 else:
02569 return self.element[0].contains_exactly(objct)
02570
02571
02572
02573
02574
02575
02576
02577
02578 def contains_a_rounded_number(self):
02579 for elt in self.element:
02580 if elt.contains_a_rounded_number():
02581 return True
02582
02583 return False
02584
02585
02586
02587
02588
02589
02590
02591
02592 def get_elements(self):
02593 return self.element
02594
02595
02596
02597
02598
02599
02600
02601 def get_info(self):
02602 return self.info
02603
02604
02605
02606
02607
02608
02609
02610
02611 def get_letter(self):
02612 if self.is_literal():
02613 return self.element[0].get_letter()
02614
02615 else:
02616 raise error.UncompatibleType(self, "Litteral Operation")
02617
02618
02619
02620
02621
02622
02623
02624
02625 def get_sign(self):
02626 return self.element[0].get_sign()
02627
02628 sign = property(get_sign,
02629 doc = "Sign of the first element of the Operation")
02630
02631
02632
02633
02634
02635
02636
02637
02638 def set_sign(self, arg):
02639 self.element[0].set_sign(arg)
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649 def set_compact_display(self, arg):
02650 if not (arg == True or arg == False):
02651 raise error.UncompatibleType(self, "Boolean")
02652
02653 self.compact_display = arg
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663 def append(self, elt):
02664 self.element.append(elt)
02665 self.info.append(False)
02666
02667
02668
02669
02670
02671
02672
02673
02674
02675 def remove(self, elt):
02676 i = 0
02677
02678
02679 while i < len(self) \
02680 and self.element[i] != elt \
02681 and not self.element[i].contains_exactly(elt):
02682
02683 i += 1
02684
02685
02686 if i == len(self):
02687 raise error.UnreachableData(str(elt) \
02688 + " in " \
02689 + str(self))
02690
02691
02692 self.element.pop(i)
02693 self.info.pop(i)
02694
02695
02696
02697
02698
02699
02700
02701
02702
02703 def evaluate(self):
02704 answer = self.neutral.value
02705
02706 for elt in self:
02707 if isinstance(elt, Item) or isinstance(elt, Value):
02708
02709
02710 val = elt.value
02711 expo = 1
02712 sign_val = 1
02713
02714 if isinstance(elt, Item):
02715 expo = elt.exponent.evaluate()
02716 if elt.is_negative():
02717 sign_val = -1
02718
02719 if expo == 0:
02720 val = 1
02721
02722 answer = self.operator(answer, sign_val * (val ** expo))
02723
02724 elif isinstance(elt, Operation):
02725 answer = self.operator(answer, elt.evaluate())
02726
02727 external_expon = self.exponent.evaluate()
02728
02729 return (answer ** external_expon)
02730
02731
02732
02733
02734
02735
02736
02737
02738 def throw_away_the_neutrals(self):
02739 collected_positions = list()
02740
02741 for i in xrange(len(self)):
02742 if self.element[i].is_equivalent_to_a_single_neutral(self.neutral):
02743
02744 debug.write("\n" + str(self.element[i]) \
02745 + "has been detected as " \
02746 + "'single neutral'" \
02747 + " the ref. neutral being " \
02748 + str(self.neutral),
02749 case=debug.throw_away_the_neutrals)
02750 collected_positions.append(i)
02751
02752 result = None
02753
02754 if isinstance(self, Product):
02755 result = Product(self)
02756 elif isinstance(self, Sum):
02757 result = Sum(self)
02758
02759 if len(collected_positions) == len(self):
02760 result.element = list()
02761 result.element.append(Item(self.neutral))
02762 result.info = [False]
02763
02764 else:
02765 for i in xrange(len(collected_positions)):
02766
02767
02768
02769 result.element.pop(collected_positions[i] - i)
02770 result.info.pop(collected_positions[i] - i)
02771
02772 return result
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786 class Product(Operation):
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808 def __init__(self, arg):
02809
02810 self.element = list()
02811
02812 self.symbol = '×'
02813
02814 self.neutral = Item(1)
02815
02816
02817
02818
02819
02820
02821
02822 self.compact_display = True
02823
02824
02825
02826
02827 self.info = list()
02828
02829
02830 self.exponent = Value(1)
02831
02832 self.str_openmark = "<"
02833 self.str_closemark = ">"
02834
02835
02836 if arg == None or (type(arg) == list and len(arg) == 0):
02837 self.element.append(Item(1))
02838
02839
02840 elif isinstance(arg, Product):
02841 self.compact_display = arg.compact_display
02842 self.exponent = arg.exponent.deep_copy()
02843 for i in xrange(len(arg.element)):
02844 self.element.append(arg.element[i].deep_copy())
02845 for i in xrange(len(arg.info)):
02846 self.info.append(arg.info[i])
02847
02848
02849 elif is_.a_number(arg):
02850 self.element.append(Item(arg))
02851
02852
02853 elif isinstance(arg, Exponented):
02854 self.element.append(arg.deep_copy())
02855
02856
02857 elif (type(arg) == list) and len(arg) >= 1:
02858 for i in xrange(len(arg)):
02859
02860 if i == 0:
02861 self.info.append(False)
02862 else:
02863 self.info.append(True)
02864
02865
02866
02867
02868
02869
02870 if isinstance(arg[i], Exponented):
02871 self.element.append(arg[i].deep_copy())
02872
02873 elif is_.a_number(arg[i]):
02874 self.element.append(Item(arg[i]))
02875
02876 elif arg[i] == None:
02877 self.element.append(Item(1))
02878
02879 else:
02880 raise error.UncompatibleType(arg[i],
02881 "This element of the\
02882 provided list\
02883 should have been either a\
02884 a Exponented or a Number")
02885
02886
02887 else:
02888 raise error.UncompatibleType(arg,
02889 "Product|Exponented|Number|\
02890 [Exponenteds|Numbers]")
02891
02892
02893
02894
02895
02896
02897 def is_null(self):
02898 for element in self:
02899 if element.is_null():
02900 return True
02901
02902 return False
02903
02904
02905
02906
02907
02908
02909
02910
02911 def set_exponent(self, nb):
02912 if is_.a_number(nb):
02913 self.exponent = Value(nb)
02914 elif (type(nb) == Value or type(nb) == Item) and nb.is_numeric():
02915 self.exponent = nb.deep_copy()
02916 else:
02917 raise error.UncompatibleType(nb, 'any number OR numeric Value|Item')
02918
02919
02920
02921
02922
02923
02924
02925 def get_elements(self):
02926 return self.element
02927
02928
02929
02930
02931
02932
02933
02934 def get_info(self):
02935 return self.info
02936
02937
02938
02939
02940
02941
02942 factor = property(get_elements,
02943 doc = "To access the factors of the Product.")
02944
02945 display_multiply_symbol = property(get_info,
02946 doc = "The 'info' field")
02947
02948
02949
02950
02951 def operator(self, arg1, arg2):
02952 return arg1 * arg2
02953
02954
02955
02956
02957
02958
02959
02960
02961
02962
02963
02964
02965
02966 def __cmp__(self, objct):
02967 if not isinstance(objct, Product):
02968 return -1
02969
02970 if len(self) != len(objct):
02971 return -1
02972
02973 for i in xrange(len(self)):
02974 if self.factor[i] != objct.factor[i]:
02975 return -1
02976
02977 if self.exponent != objct.exponent:
02978 return -1
02979
02980 return 0
02981
02982
02983
02984
02985
02986
02987
02988
02989 def is_equivalent_to_a_single_1(self):
02990
02991
02992 if not self.exponent.is_equivalent_to_a_single_1():
02993 return False
02994
02995 if len(self) == 1:
02996 return self.factor[0].is_equivalent_to_a_single_1()
02997
02998 return self.is_equivalent_to_a_single_neutral(Item(1))
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008 def is_equivalent_to_a_single_minus_1(self):
03009 if not self.exponent.is_equivalent_to_a_single_1():
03010 return False
03011
03012 a_factor_different_from_1_and_minus1_has_been_found = False
03013 equivalent_to_minus1_nb_factors = 0
03014
03015 for factor in self:
03016 if factor.is_equivalent_to_a_single_minus_1():
03017 equivalent_to_minus1_nb_factors += 1
03018 elif not factor.is_equivalent_to_a_single_1():
03019 a_factor_different_from_1_and_minus1_has_been_found = True
03020
03021 if a_factor_different_from_1_and_minus1_has_been_found:
03022 return False
03023 elif equivalent_to_minus1_nb_factors == 1:
03024 return True
03025 else:
03026 return False
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036 def is_equivalent_to_a_single_0(self):
03037 answer = True
03038
03039 for factor in self:
03040 answer = answer and factor.is_equivalent_to_a_single_0()
03041
03042 return answer
03043
03044
03045
03046
03047
03048
03049
03050
03051
03052
03053
03054
03055
03056
03057 def is_reducible(self):
03058 if self.is_equivalent_to_a_single_0() \
03059 or self.is_equivalent_to_a_single_1() \
03060 or self.is_equivalent_to_a_single_minus_1():
03061
03062
03063 debug.write("[Product.is_reducible() returning False] - A\n",
03064 case=debug.product_is_reducible)
03065
03066 return False
03067
03068
03069
03070
03071
03072
03073
03074 if not self.exponent.is_equivalent_to_a_single_1():
03075
03076 debug.write("[Product.is_reducible() returning True] - B\n",
03077 case=debug.product_is_reducible)
03078
03079 return True
03080
03081
03082
03083
03084
03085 if self.compact_display:
03086 test_product = self.throw_away_the_neutrals()
03087 else:
03088 test_product = Product(self)
03089
03090
03091
03092
03093
03094 numerics = test_product.get_factors_list(__.NUMERIC)
03095
03096
03097
03098 if len(numerics) >= 2:
03099
03100 debug.write("[Product.is_reducible() returning True] - C\n",
03101 case=debug.product_is_reducible)
03102
03103 return True
03104
03105
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115
03116 if len(numerics) == 1 \
03117 and (not numerics[0].exponent.is_equivalent_to_a_single_1() \
03118 or numerics[0].is_equivalent_to_a_single_0()):
03119
03120
03121 debug.write("[Product.is_reducible() returning True] - D\n",
03122 case=debug.product_is_reducible)
03123
03124 return True
03125
03126
03127
03128 elif len(numerics) == 1 and len(test_product) == 1:
03129
03130 debug.write("[Product.is_reducible() returning False] - E\n",
03131 case=debug.product_is_reducible)
03132
03133 return False
03134
03135
03136
03137
03138
03139
03140
03141 literals = self.get_factors_list(__.LITERALS)
03142 aux_lexicon = dict()
03143
03144 for element in literals:
03145 put_term_in_lexicon(element, Item(1), aux_lexicon)
03146
03147
03148
03149 for key in aux_lexicon:
03150 if len(aux_lexicon[key]) >= 2:
03151
03152 debug.write("[Product.is_reducible() returning True] - F\n",
03153 case=debug.product_is_reducible)
03154
03155 return True
03156
03157
03158
03159
03160
03161
03162
03163 for i in xrange(len(literals)):
03164
03165
03166
03167
03168
03169 if test_product.factor[0].is_numeric() \
03170 or (test_product.factor[0].is_literal() and i != 0):
03171
03172 if literals[i].sign == '-':
03173
03174 debug.write(\
03175 "[Product.is_reducible() returning True] - G\n",
03176 case=debug.product_is_reducible)
03177
03178 return True
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188
03189 if len(numerics) == 0:
03190
03191 debug.write("[Product.is_reducible() returning False] - H\n",
03192 case=debug.product_is_reducible)
03193
03194 return False
03195
03196
03197 elif len(numerics) == 1:
03198 if test_product.get_first_factor().is_numeric():
03199
03200 debug.write("[Product.is_reducible() returning False] - I\n",
03201 case=debug.product_is_reducible)
03202
03203 return False
03204
03205 elif numerics[0].is_equivalent_to_a_single_1() \
03206 and self.compact_display:
03207
03208 debug.write("[Product.is_reducible() returning False] - J\n",
03209 case=debug.product_is_reducible)
03210 return False
03211
03212 else:
03213
03214 debug.write("[Product.is_reducible() returning True] - K\n",
03215 case=debug.product_is_reducible)
03216 debug.write("numerics[0] = " + str(numerics[0]),
03217 case=debug.product_is_reducible)
03218
03219 return True
03220
03221
03222
03223 debug.write("[Product.is_reducible() returning False] - L\n",
03224 case=debug.product_is_reducible)
03225
03226 return False
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238 def multiply_symbol_is_required(self, objct, position):
03239 next_to_last = len(self) - 1
03240
03241 if isinstance(objct, Item):
03242 return self.factor[next_to_last].multiply_symbol_is_required(objct,
03243 position)
03244
03245
03246 if isinstance(objct, Product):
03247 return self.factor[next_to_last].multiply_symbol_is_required( \
03248 objct.factor[0],
03249 position)
03250
03251
03252 if isinstance(objct, Sum):
03253 if len(objct) == 1:
03254 return self.multiply_symbol_is_required(objct.term[0],
03255 position)
03256 else:
03257
03258 return self.factor[0].multiply_symbol_is_required(objct,
03259 position)
03260
03261
03262 if isinstance(objct, Quotient):
03263 return True
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275 def requires_brackets(self, position):
03276
03277 if self.exponent.is_equivalent_to_a_single_1():
03278
03279
03280 self_without_ones = self.throw_away_the_neutrals()
03281
03282 if len(self_without_ones) == 1:
03283 return self_without_ones.factor[0].requires_brackets(position)
03284
03285
03286
03287
03288
03289
03290 else:
03291 return False
03292
03293
03294
03295
03296
03297
03298
03299
03300
03301 else:
03302 return False
03303
03304
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314 def requires_inner_brackets(self):
03315
03316 debug.write("\nEntering Product.requires_inner_brackets()\n",
03317 case=debug.requires_inner_brackets_in_product)
03318
03319 if self.exponent_must_be_displayed():
03320
03321
03322 debug.write("\nProduct.requires_inner_brackets() : the exponent" \
03323 " should be displayed\n",
03324 case=debug.requires_inner_brackets_in_product)
03325
03326 compacted_self = Product(self)
03327 compacted_self = compacted_self.throw_away_the_neutrals()
03328
03329 if len(compacted_self) == 1:
03330
03331
03332 debug.write("\nProduct.requires_inner_brackets() : len(comp" \
03333 "acted_self is 1\n",
03334 case=debug.requires_inner_brackets_in_product)
03335
03336 if compacted_self.get_sign() == '+' \
03337 and \
03338 not compacted_self.factor[0].exponent_must_be_displayed() \
03339 and \
03340 not (compacted_self.exponent_must_be_displayed() \
03341 and len(compacted_self.factor[0]) >= 2):
03342
03343 return False
03344 else:
03345 return True
03346
03347
03348
03349 else:
03350 return True
03351
03352 else:
03353 return False
03354
03355
03356
03357
03358
03359
03360
03361 def get_factors_list_except(self, objct):
03362 if len(self) == 1 and self.factor[0] == objct:
03363 return None
03364 else:
03365 if objct in self.factor:
03366 aux_list = list()
03367 objct_was_found = False
03368 for i in xrange(len(self)):
03369 if self.factor[i] != objct:
03370 aux_list.append(self.factor[i])
03371 else:
03372 if objct_was_found:
03373 aux_list.append(self.factor[i])
03374 else:
03375 objct_was_found = True
03376 return aux_list
03377 else:
03378 raise error.UnreachableData("the object : " + str(objct) \
03379 + " in this Product : " \
03380 + str(self))
03381
03382
03383
03384
03385
03386
03387
03388
03389
03390
03391
03392
03393
03394
03395 def get_first_factor(self):
03396 if len(self) == 0:
03397 return None
03398 else:
03399
03400
03401 if isinstance(self.factor[0], Sum) \
03402 and len(self.factor[0]) == 1:
03403
03404 answer = Product(self.factor[0].term[0]).get_first_factor()
03405
03406
03407 elif isinstance(self.factor[0], Product):
03408 answer = self.factor[0].get_first_factor()
03409
03410
03411
03412 else:
03413 answer = self.factor[0]
03414
03415 answer.set_exponent(answer.exponent * self.exponent)
03416 return answer
03417
03418
03419
03420
03421
03422
03423
03424
03425 def get_minus_signs_nb(self):
03426 answer = 0
03427 for factor in self:
03428 answer += factor.get_minus_signs_nb()
03429
03430 return answer
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456 def get_factors_list(self, given_kind):
03457 resulting_list = list()
03458 a_factor_not_equivalent_to_1_has_been_found = False
03459
03460 for factor in self:
03461 if isinstance(factor, Item) \
03462 and ( \
03463 (factor.is_numeric() and given_kind == __.NUMERIC) \
03464 or \
03465 (factor.is_literal() and given_kind == __.LITERALS) \
03466 ):
03467
03468
03469 if factor.is_positive() \
03470 and not (self.compact_display
03471 and factor.is_equivalent_to_a_single_1()):
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483 item_to_be_added = Item((factor.sign, \
03484 factor.value, \
03485 factor.exponent * self.exponent \
03486 ))
03487 item_to_be_added.set_is_out_striked(factor.is_out_striked)
03488 resulting_list.append(item_to_be_added)
03489 a_factor_not_equivalent_to_1_has_been_found = True
03490
03491 elif factor.is_negative():
03492
03493
03494
03495
03496
03497
03498 item_to_be_added = factor
03499 if lib.is_even(self.exponent):
03500 item_to_be_added = Product([factor])
03501 item_to_be_added.set_exponent(self.exponent)
03502 resulting_list.append(item_to_be_added)
03503 a_factor_not_equivalent_to_1_has_been_found = True
03504
03505 elif isinstance(factor, Product):
03506
03507
03508
03509
03510
03511 aux_product = Product(factor)
03512 aux_product.set_exponent(factor.exponent * self.exponent)
03513 temp_list = aux_product.get_factors_list(given_kind)
03514
03515 if len(temp_list) != 0:
03516 resulting_list += temp_list
03517 a_factor_not_equivalent_to_1_has_been_found = True
03518
03519 elif isinstance(factor, Sum):
03520 if len(factor) == 1:
03521
03522
03523
03524 aux_list = list()
03525 aux_list.append(factor.term[0])
03526 aux_product = Product(aux_list)
03527 aux_product.set_exponent(factor.exponent)
03528 temp_list = aux_product.get_factors_list(given_kind)
03529 if len(temp_list) != 0:
03530 resulting_list += temp_list
03531 a_factor_not_equivalent_to_1_has_been_found = True
03532
03533 elif given_kind == __.OTHERS:
03534
03535
03536 aux_sum = Sum(factor)
03537 aux_sum.set_exponent(factor.exponent * self.exponent)
03538 resulting_list.append(aux_sum)
03539 a_factor_not_equivalent_to_1_has_been_found = True
03540
03541 elif isinstance(factor, Quotient):
03542 if (factor.is_numeric() and given_kind == __.NUMERIC) \
03543 or \
03544 (factor.is_literal() and given_kind == __.LITERALS):
03545
03546 resulting_list.append(factor)
03547 a_factor_not_equivalent_to_1_has_been_found = True
03548 else:
03549 if given_kind == __.OTHERS:
03550 resulting_list.append(factor)
03551 a_factor_not_equivalent_to_1_has_been_found = True
03552
03553
03554 if given_kind == __.NUMERIC \
03555 and not a_factor_not_equivalent_to_1_has_been_found \
03556 and len(resulting_list) == 0:
03557
03558 resulting_list.append(Item(1))
03559
03560 return resulting_list
03561
03562
03563
03564
03565
03566
03567
03568
03569
03570
03571 def set_factor(self, n, arg):
03572 self.element[n] = arg
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583 def calculate_next_step(self, **options):
03584 if not self.is_numeric() or isinstance(self, Monomial):
03585 return self.expand_and_reduce_next_step(**options)
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611 if len(self) >= 2:
03612
03613
03614 nb_items = 0
03615 nb_minus_1 = 0
03616 nb_fractions = 0
03617
03618
03619 for i in xrange(len(self)):
03620
03621 if isinstance(self.factor[i], Item):
03622 if not (self.factor[i].is_equivalent_to_a_single_1() \
03623 and self.compact_display
03624 or
03625 self.factor[i].is_equivalent_to_a_single_minus_1()):
03626
03627 nb_items += 1
03628 else:
03629 if self.factor[i].is_equivalent_to_a_single_minus_1():
03630 nb_minus_1 += 1
03631
03632 if isinstance(self.factor[i], Monomial) \
03633 and self.factor[i].is_numeric() \
03634 and isinstance(self.factor[i][0], Item):
03635
03636 if not (self.factor[i].is_equivalent_to_a_single_1() \
03637 and self.compact_display
03638 or
03639 self.factor[i].is_equivalent_to_a_single_minus_1()):
03640
03641 nb_items += 1
03642 self.factor[i] = Item(self.factor[i][0])
03643 else:
03644 if self.factor[i].is_equivalent_to_a_single_minus_1():
03645 self.factor[i] = Item(-1)
03646 nb_minus_1 += 1
03647
03648
03649 if isinstance(self.factor[i], Fraction):
03650 if not (self.factor[i].is_equivalent_to_a_single_1() \
03651 or
03652 self.factor[i].is_equivalent_to_a_single_minus_1()):
03653
03654 nb_fractions += 1
03655 else:
03656 if self.factor[i].is_equivalent_to_a_single_minus_1():
03657 nb_minus_1 += 1
03658
03659
03660
03661
03662
03663 if nb_fractions == 0 and nb_items >= 1:
03664 return Product([Item(self.evaluate())])
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674 elif nb_fractions >= 2 and nb_items == 0:
03675 resulting_sign_list = []
03676 resulting_nume_list = []
03677 resulting_deno_list = []
03678 possibly_items_list = []
03679
03680 for i in xrange(len(self)):
03681 if isinstance(self.factor[i], Fraction) \
03682 and not (self.factor[i].is_equivalent_to_a_single_1() \
03683 or
03684 self.factor[i].is_equivalent_to_a_single_minus_1()):
03685
03686
03687
03688
03689
03690 resulting_sign_list.append(self.factor[i])
03691 for j in xrange(len(self.factor[i].numerator.factor)):
03692 item_to_add = Item( \
03693 self.factor[i].numerator.factor[j])
03694 item_to_add.set_sign('+')
03695 resulting_nume_list.append(item_to_add)
03696
03697
03698 for j in xrange(len(self.factor[ \
03699 i].denominator.factor)):
03700
03701 item_to_add = Item( \
03702 self.factor[i].denominator.factor[j])
03703 item_to_add.set_sign('+')
03704 resulting_deno_list.append(item_to_add)
03705
03706
03707
03708 else:
03709 possibly_items_list.append(self.factor[i])
03710
03711 resulting_sign = lib.sign_of_product(resulting_sign_list)
03712 resulting_nume = Product(resulting_nume_list)
03713 resulting_nume.set_compact_display(False)
03714 resulting_deno = Product(resulting_deno_list)
03715 resulting_deno.set_compact_display(False)
03716
03717 resulting_fraction = Fraction((resulting_sign,
03718 resulting_nume,
03719 resulting_deno))
03720
03721 if len(possibly_items_list) == 0:
03722 return resulting_fraction
03723 else:
03724 return Product(possibly_items_list + [resulting_fraction])
03725
03726
03727
03728
03729
03730
03731
03732
03733 elif nb_fractions == 1 and nb_minus_1 == 1:
03734
03735 the_fraction = None
03736 for i in xrange(len(self)):
03737 if isinstance(self.factor[i], Fraction):
03738 the_fraction = Fraction(self.factor[i])
03739
03740 if the_fraction.calculate_next_step(**options) == None:
03741 return None
03742
03743 else:
03744 return Product([Item(-1),
03745 the_fraction.calculate_next_step(**options)])
03746
03747
03748
03749
03750
03751 elif nb_fractions == 1 and nb_minus_1 == 0 and nb_items == 0:
03752
03753 the_fraction = None
03754 for i in xrange(len(self)):
03755 if isinstance(self.factor[i], Fraction):
03756 the_fraction = Fraction(self.factor[i])
03757
03758 return the_fraction.calculate_next_step(**options)
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777
03778 elif len(self) == 1:
03779 if isinstance(self.factor[0], Item):
03780 new_item = Item(self.factor[0])
03781 new_item.set_exponent(self.exponent * new_item.exponent)
03782 return new_item.calculate_next_step(**options)
03783
03784 elif isinstance(self.factor[0], Fraction):
03785 new_fraction = Fraction(self.factor[0])
03786 new_fraction.set_exponent(self.exponent \
03787 * new_fraction.exponent)
03788 return new_fraction.calculate_next_step(**options)
03789
03790 elif isinstance(self.factor[0], Sum):
03791 new_sum = self.factor[0].calculate_next_step(**options)
03792 if new_sum != None:
03793 return Product([new_sum])
03794 else:
03795 return None
03796
03797
03798
03799
03800
03801
03802
03803
03804
03805
03806
03807
03808
03809
03810
03811
03812 def order(self):
03813 num_factors = self.get_factors_list(__.NUMERIC)
03814
03815 literal_factors = self.get_factors_list(__.LITERALS)
03816 literal_factors.sort(Exponented.alphabetical_order_cmp)
03817
03818 other_factors = self.get_factors_list(__.OTHERS)
03819
03820 return Product(num_factors + literal_factors + other_factors)
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833 def reduce_(self):
03834
03835
03836
03837
03838 numeric_part = Product(self.get_factors_list(__.NUMERIC)).evaluate()
03839
03840
03841 raw_literals_list = self.get_factors_list(__.LITERALS)
03842 literals_list = reduce_literal_items_product(raw_literals_list)
03843 literals_list.sort(Exponented.alphabetical_order_cmp)
03844
03845
03846 final_sign = lib.sign_of_product([numeric_part] + raw_literals_list)
03847
03848 if numeric_part >= 0:
03849 numeric_item = Item((final_sign, numeric_part, 1))
03850 else:
03851 numeric_item = Item((final_sign, -1*numeric_part, 1))
03852
03853
03854 others_list = self.get_factors_list(__.OTHERS)
03855
03856
03857 if numeric_item.is_equivalent_to_a_single_0():
03858 return Product([Item(0)])
03859 else:
03860 return Product([numeric_item] + literals_list + others_list)
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872 def expand_and_reduce_next_step(self, **options):
03873
03874 debug.write("\nEntered :\n" \
03875 + "[expand_and_reduce_next_step_product]\n" \
03876 + "Current Product is : \n" \
03877 + str(self) + "\n" \
03878 + "\n",
03879 case=debug.expand_and_reduce_next_step_product)
03880
03881
03882 if type(self) == BinomialIdentity:
03883 return self.expand()
03884
03885 if self.is_numeric() and not isinstance(self, Monomial):
03886
03887 debug.write("\nExiting :\n" \
03888 + "[expand_and_reduce_next_step_product] " \
03889 + "Calling calculate_next_step on self\n",
03890 case=debug.expand_and_reduce_next_step_product)
03891 return self.calculate_next_step(**options)
03892
03893 if isinstance(self, Monomial):
03894
03895 debug.write("\nExiting :\n" \
03896 + "[expand_and_reduce_next_step_product] " \
03897 + "Returning None\n",
03898 case=debug.expand_and_reduce_next_step_product)
03899 return None
03900
03901 copy = Product(self)
03902
03903 a_factor_at_least_has_been_modified = False
03904
03905
03906 for i in xrange(len(copy)):
03907 test = copy.factor[i].expand_and_reduce_next_step(**options)
03908 if test != None:
03909 if isinstance(test, Operation) and len(test) == 1:
03910
03911 copy.element[i] = test[0]
03912 else:
03913 copy.element[i] = test
03914 a_factor_at_least_has_been_modified = True
03915
03916 if a_factor_at_least_has_been_modified:
03917
03918
03919
03920
03921
03922
03923 if len(copy) >= 2 \
03924 and copy.factor[0].is_equivalent_to_a_single_minus_1():
03925
03926 if isinstance(copy.factor[1], Product) \
03927 and copy.factor[1].exponent.is_equivalent_to_a_single_1() \
03928 and copy.factor[1].get_first_factor().is_positive():
03929
03930 new_copy = Product(copy)
03931 new_copy.element = list()
03932 new_first_factor = Item(-1).times(copy.factor[1].
03933 get_first_factor())
03934 new_first_factor = new_first_factor.reduce_()
03935 new_copy.element.append(new_first_factor)
03936 for i in xrange(len(copy.factor[1]) - 1):
03937 new_copy.element.append(copy.factor[1].factor[i + 1])
03938 for i in xrange(len(copy.factor) - 2):
03939 new_copy.element.append(copy.factor[i + 2])
03940 copy = new_copy
03941 return copy
03942
03943
03944 else:
03945
03946 debug.write("\n[expand_and_reduce_next_step_product] " \
03947 + "No factor has been modified\n",
03948 case=debug.expand_and_reduce_next_step_product)
03949 if self.is_reducible():
03950
03951 debug.write("\n[expand_and_reduce_next_step_product] " \
03952 + "self is reducible, returning self.reduce_\n",
03953 case=debug.expand_and_reduce_next_step_product)
03954 return self.reduce_()
03955
03956
03957
03958
03959
03960
03961
03962
03963 else:
03964
03965 debug.write("\n[expand_and_reduce_next_step_product] " \
03966 + "self is not reducible, returning None\n",
03967 case=debug.expand_and_reduce_next_step_product)
03968 return None
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981 def make_string(self, markup, **options):
03982 global expression_begins
03983
03984 if 'force_expression_begins' in options \
03985 and options['force_expression_begins'] == True:
03986
03987 expression_begins = True
03988 options['force_expression_begins'] = False
03989
03990
03991
03992
03993 position = 0
03994 if 'force_position' in options \
03995 and is_.an_integer(options['force_position']):
03996
03997 position = options['force_position']
03998
03999
04000 temp_options = dict()
04001 for key in options:
04002 if key != 'force_position':
04003 temp_options[key] = options[key]
04004 options = temp_options
04005
04006
04007 debug.write( \
04008 "\n\nEntered make_string in Product : expression_begins = " \
04009 + str(expression_begins) + " | position set to " + str(position)\
04010 + "\nCurrent Product :\n" + str(self),
04011 case=debug.make_string_in_product)
04012
04013
04014
04015
04016
04017
04018
04019 if self.compact_display:
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046 resulting_string = ""
04047
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057
04058
04059
04060
04061
04062 couple = (None, None)
04063
04064
04065
04066 flag = False
04067
04068
04069
04070
04071
04072
04073
04074 orphan_minus_sign = False
04075
04076
04077
04078 unclosed_bracket = 0
04079
04080
04081
04082
04083
04084 if self.factor[0].is_equivalent_to_a_single_1():
04085
04086
04087
04088
04089
04090
04091
04092
04093 pass
04094 elif self.factor[0].is_equivalent_to_a_single_minus_1():
04095
04096 debug.write("\n[n°0] : processing a '-1' 1st " \
04097 + "factor : " \
04098 + str(self.factor[0]) \
04099 + "\nwith position forced to " \
04100 + str(position),
04101 case=debug.make_string_in_product)
04102 if position >= 1:
04103 debug.write(" and a bracket is */opened/*\n",
04104 case=debug.make_string_in_product)
04105 resulting_string += markup['opening_bracket']
04106 unclosed_bracket += 1
04107
04108
04109
04110
04111 resulting_string += markup['minus']
04112 position += 1
04113 orphan_minus_sign = True
04114
04115
04116
04117
04118
04119
04120
04121 expression_begins = False
04122 else:
04123
04124
04125
04126
04127
04128
04129
04130
04131
04132 if (Product(self.get_factors_list_except(self.factor[0]))
04133 .is_equivalent_to_a_single_1() \
04134 and position == 0 ) \
04135 or not (self.factor[0].requires_brackets(position) \
04136 and len(self) >= 2) \
04137 or self.requires_inner_brackets():
04138
04139
04140 debug.write("\n[n°1A] : processing 1st " \
04141 + "factor : " \
04142 + str(self.factor[0]) \
04143 + "\nwith position forced to " \
04144 + str(position) \
04145 + " ; NO brackets",
04146 case=debug.make_string_in_product)
04147
04148 resulting_string += self.factor[0].make_string(
04149 markup,
04150 force_position=position,
04151 **options)
04152
04153
04154
04155
04156
04157 else:
04158 expression_begins = True
04159
04160 debug.write("\n[n°1B] : processing " \
04161 + "1st factor :" \
04162 + " " + str(self.factor[0]) \
04163 + "\nwith position NOT forced to "\
04164 + str(position) \
04165 + ", needs brackets ? " \
04166 + str(self.factor[0].\
04167 requires_brackets(position)) \
04168 + " ; a bracket is */opened/*\n",
04169 case=debug.make_string_in_product)
04170
04171 resulting_string += markup['opening_bracket'] \
04172 + self.factor[0].make_string(markup,
04173 **options)
04174
04175
04176 unclosed_bracket += 1
04177
04178 if len(self.factor[0]) >= 2:
04179 debug.write("and " \
04180 + "*/closed/*\n",
04181 case=debug.make_string_in_product)
04182 resulting_string += \
04183 markup['closing_bracket']
04184 unclosed_bracket -= 1
04185
04186
04187
04188
04189 flag = True
04190 position += 1
04191 couple = (self.factor[0], None)
04192
04193
04194 if len(self) >= 2:
04195 for i in xrange(len(self) - 1):
04196 if self.factor[i + 1].is_equivalent_to_a_single_1():
04197
04198
04199 pass
04200 else:
04201 if couple == (None, None):
04202
04203
04204 couple = (self.factor[i + 1], None)
04205 if self.factor[i + 1].requires_brackets(position)\
04206 and not Product(self.get_factors_list_except(
04207 self.factor[i+1])
04208 ).is_equivalent_to_a_single_1():
04209
04210 expression_begins = True
04211
04212 debug.write("\n[n°2A] : " \
04213 + "processing " \
04214 + "factor : "\
04215 + str(self.factor[i+1])\
04216 + "\nwith position " \
04217 + "NOT forced to " \
04218 + str(position) \
04219 + " ; " \
04220 + "a bracket is " \
04221 + "*/opened/*\n",
04222 case=debug.make_string_in_product)
04223
04224 resulting_string += markup['opening_bracket'] \
04225 + self.factor[i+1].make_string(\
04226 markup,\
04227 **options)
04228
04229
04230 unclosed_bracket += 1
04231
04232 if len(self.factor[i+1]) >= 2:
04233 debug.write("and " \
04234 + "*/closed/*\n",
04235 case=debug.make_string_in_product)
04236 resulting_string += \
04237 markup['closing_bracket']
04238 unclosed_bracket -= 1
04239
04240
04241 else:
04242
04243
04244
04245 if orphan_minus_sign:
04246 expression_begins = True
04247
04248 debug.write("\n[n°2B] : " \
04249 + "(orphan - sign) " \
04250 + "processing " \
04251 + "factor : "\
04252 + str(self.factor[i+1])\
04253 + "\nwith position " \
04254 + "forced to " \
04255 + str(position) \
04256 + " ; NO brackets",
04257 case=debug.make_string_in_product)
04258
04259 resulting_string += \
04260 self.factor[i+1].make_string(
04261 markup,
04262 force_position=position,
04263 **options)
04264 else:
04265
04266 debug.write("\n[n°2C] : " \
04267 + "(NO orphan - sign) "\
04268 + "processing " \
04269 + "factor : "\
04270 + str(self.factor[i+1])\
04271 + "\nwith position " \
04272 + "forced to " \
04273 + str(position) \
04274 + " ; NO brackets",
04275 case=debug.make_string_in_product)
04276
04277 resulting_string += \
04278 self.factor[i+1].make_string(
04279 markup,
04280 force_position=position,
04281 **options)
04282
04283
04284 flag = True
04285 position += 1
04286
04287 else:
04288 if couple[1] == None:
04289
04290
04291 current_factor_1 = couple[0]
04292 current_factor_2 = self.factor[i + 1]
04293 else:
04294
04295
04296 current_factor_1 = couple[1]
04297 current_factor_2 = self.factor[i + 1]
04298
04299 couple = (current_factor_1, current_factor_2)
04300
04301
04302
04303
04304
04305
04306 debug.write( \
04307 "\nChecking if a × should be required \n" \
04308 + "between " + str(couple[0]) + " and " \
04309 + str(couple[1]),
04310 case=debug.make_string_in_product)
04311 if couple[0].multiply_symbol_is_required(couple[1],
04312 position - 1):
04313
04314
04315 debug.write( \
04316 "\n... yes\n",
04317 case=debug.make_string_in_product)
04318 if unclosed_bracket >= 1:
04319 if couple[0].multiply_symbol_is_required(\
04320 couple[1],
04321 0):
04322
04323
04324 debug.write( \
04325 "\nthe bracket is */closed/*\n",
04326 case=debug.make_string_in_product)
04327 resulting_string += \
04328 markup['closing_bracket']
04329 unclosed_bracket -= 1
04330
04331 resulting_string += markup['times']
04332 else:
04333 pass
04334 else:
04335 resulting_string += markup['times']
04336
04337 else:
04338
04339 debug.write( \
04340 "\n... no\n",
04341 case=debug.make_string_in_product)
04342
04343
04344
04345
04346
04347
04348
04349 expression_begins = True
04350
04351 if couple[1].requires_brackets(position):
04352
04353
04354
04355
04356
04357
04358
04359
04360 debug.write("\n[n°3A] : " \
04361 + "processing " \
04362 + "factor : "\
04363 + str(couple[1])\
04364 + "\nwith position " \
04365 + "NOT forced to " \
04366 + str(position) \
04367 + " ; a bracket is " \
04368 + "*/opened/*\n",
04369 case=debug.make_string_in_product)
04370
04371 resulting_string += markup['opening_bracket'] \
04372 + couple[1].make_string(
04373 markup,
04374 **options)
04375
04376
04377 unclosed_bracket += 1
04378
04379 if len(self.factor[i+1]) >= 2:
04380 debug.write("and " \
04381 + "*/closed/*\n",
04382 case=debug.make_string_in_product)
04383 resulting_string += \
04384 markup['closing_bracket']
04385 unclosed_bracket -= 1
04386
04387 else:
04388
04389 debug.write("\n[n°3B] : " \
04390 + "processing " \
04391 + "factor : "\
04392 + str(couple[1])\
04393 + "\nwith position " \
04394 + "forced to " \
04395 + str(position) \
04396 + " ; NO brackets",
04397 case=debug.make_string_in_product)
04398
04399 resulting_string += \
04400 couple[1].make_string(markup,
04401 force_position=position,
04402 **options)
04403
04404 position += 1
04405 flag = True
04406
04407
04408
04409
04410
04411 if not flag:
04412
04413
04414 if not expression_begins \
04415 and self.factor[0].is_equivalent_to_a_single_1():
04416
04417 resulting_string += markup['plus'] + markup['one']
04418
04419 else:
04420 resulting_string += markup['one']
04421
04422
04423
04424 expression_begins = False
04425
04426
04427 if unclosed_bracket >= 1:
04428 for i in xrange(unclosed_bracket):
04429
04430 debug.write( \
04431 "\n[end of product]the bracket is */closed/*\n",
04432 case=debug.make_string_in_product)
04433 resulting_string += markup['closing_bracket']
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444
04445 else:
04446
04447
04448
04449
04450
04451
04452
04453 resulting_string = ""
04454
04455
04456 if self.factor[0].requires_brackets(position) \
04457 and not len(self) == 1:
04458
04459
04460 expression_begins = True
04461
04462 debug.write("\n[n°4A]× : " \
04463 + "processing " \
04464 + "1st factor : "\
04465 + str(self.factor[0])\
04466 + "\nwith position " \
04467 + "NOT forced to " \
04468 + str(position) \
04469 + " ; WITH brackets",
04470 case=debug.make_string_in_product)
04471
04472 resulting_string += markup['opening_bracket'] \
04473 + self.factor[0].make_string(markup,
04474 **options) \
04475 + markup['closing_bracket']
04476 else:
04477
04478 debug.write("\n[n°4B]× : " \
04479 + "processing " \
04480 + "1st factor : "\
04481 + str(self.factor[0])\
04482 + "\nwith position " \
04483 + "forced to " \
04484 + str(position) \
04485 + " ; NO brackets",
04486 case=debug.make_string_in_product)
04487 resulting_string += self.factor[0].make_string(markup,
04488 force_position=position,
04489 **options)
04490
04491
04492 position += 1
04493
04494
04495
04496 if len(self) >= 2:
04497 for i in xrange(len(self) - 1):
04498
04499
04500 if self.factor[i].multiply_symbol_is_required(
04501 self.factor[i+1],
04502 i) \
04503 or self.display_multiply_symbol[i+1]:
04504
04505 resulting_string += markup['times']
04506 else:
04507 pass
04508
04509
04510 expression_begins = True
04511
04512 if self.factor[i+1].requires_brackets(i+1):
04513
04514
04515
04516
04517
04518 debug.write("\n[n°5A]× : " \
04519 + "processing " \
04520 + "factor : "\
04521 + str(self.factor[i+1])\
04522 + "\nwith position " \
04523 + "NOT forced to " \
04524 + str(position) \
04525 + " ; WITH brackets",
04526 case=debug.make_string_in_product)
04527
04528 resulting_string += markup['opening_bracket'] \
04529 + self.factor[i+1].make_string(
04530 markup,
04531 **options)\
04532 + markup['closing_bracket']
04533 else:
04534
04535 debug.write("\n[n°5B]× : " \
04536 + "processing " \
04537 + "factor : "\
04538 + str(self.factor[i+1])\
04539 + "\nwith position " \
04540 + "forced to " \
04541 + str(position) \
04542 + " ; NO brackets",
04543 case=debug.make_string_in_product)
04544 resulting_string += self.factor[i+1].make_string(
04545 markup,
04546 force_position=position,
04547 **options)
04548
04549 position += 1
04550
04551
04552
04553
04554 if self.requires_inner_brackets():
04555
04556 debug.write("\n[n°6] - wrapped in (inner) brackets\n",
04557 case=debug.make_string_in_product)
04558
04559 resulting_string = markup['opening_bracket'] \
04560 + resulting_string \
04561 + markup['closing_bracket']
04562
04563 if self.exponent_must_be_displayed():
04564 expression_begins = True
04565 exponent_string = self.exponent.make_string(markup,
04566 **options)
04567
04568 debug.write("\n[n°7] - processing the exponent\n",
04569 case=debug.make_string_in_product)
04570
04571 resulting_string += markup['opening_exponent'] \
04572 + exponent_string \
04573 + markup['closing_exponent']
04574 expression_begins = False
04575
04576 return resulting_string
04577
04578
04579
04580
04581
04582
04583
04584
04585
04586
04587
04588 class Sum(Operation):
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607 def __init__(self, arg):
04608
04609 self.element = list()
04610
04611 self.symbol = '+'
04612
04613 self.neutral = Item(0)
04614
04615
04616
04617
04618
04619
04620
04621 self.compact_display = True
04622 self.info = list()
04623
04624
04625 self.force_inner_brackets_display = False
04626
04627 self.exponent = Value(1)
04628
04629 self.str_openmark = "["
04630 self.str_closemark = "]"
04631
04632
04633 if isinstance(arg, Sum):
04634 self.compact_display = arg.compact_display
04635 self.force_inner_brackets_display = \
04636 arg.force_inner_brackets_display
04637 self.exponent = arg.exponent.deep_copy()
04638 for i in xrange(len(arg)):
04639 self.element.append(arg.term[i].deep_copy())
04640 self.display_complete_writing.append( \
04641 arg.display_complete_writing[i])
04642
04643
04644 elif is_.a_number(arg) or is_.a_string(arg):
04645 self.element.append(Item(arg))
04646 self.display_complete_writing.append(False)
04647
04648
04649 elif is_.a_calculable(arg):
04650 self.element.append(arg.deep_copy())
04651 self.display_complete_writing.append(False)
04652
04653
04654 elif (type(arg) == list) and len(arg) >= 1:
04655 for i in xrange(len(arg)):
04656
04657
04658 if isinstance(arg[i], Sum) \
04659 and arg[i].exponent.is_equivalent_to_a_single_1():
04660
04661 for j in xrange(len(arg[i])):
04662 self.element.append(arg[i].term[j].deep_copy())
04663 self.display_complete_writing.append( \
04664 arg[i].display_complete_writing[j])
04665
04666 elif is_.a_calculable(arg[i]):
04667 self.element.append(arg[i].deep_copy())
04668 self.display_complete_writing.append(False)
04669
04670 elif is_.a_number(arg[i]) or is_.a_string(arg[i]):
04671 self.element.append(Item(arg[i]))
04672 self.display_complete_writing.append(False)
04673
04674 else:
04675 raise error.UncompatibleType(arg[i],
04676 "This element from the " \
04677 + "provided list should have"\
04678 + "been : Number|String|" \
04679 + "Exponented")
04680
04681
04682 elif arg == None or (type(arg) == list and len(arg) == 0):
04683 self.element.append(Item(0))
04684 self.display_complete_writing.append(False)
04685
04686
04687 else:
04688 raise error.UncompatibleType(arg,
04689 "Sum|Number|String|Exponented|" \
04690 + "[Numbers|Strings|Exponenteds]")
04691
04692
04693
04694
04695
04696 def get_elements(self):
04697 return self.element
04698
04699
04700
04701
04702
04703
04704
04705 def get_info(self):
04706 return self.info
04707
04708
04709
04710
04711
04712
04713 term = property(get_elements,
04714 doc = "To access the terms of the Sum.")
04715
04716 display_complete_writing = property(get_info,
04717 doc = "The 'info' field")
04718
04719
04720
04721
04722 def operator(self, arg1, arg2):
04723 return arg1 + arg2
04724
04725
04726
04727
04728
04729
04730
04731
04732
04733
04734
04735
04736
04737 def __cmp__(self, objct):
04738 if not isinstance(objct, Sum):
04739 return -1
04740
04741 if len(self) != len(objct):
04742 return -1
04743
04744 for i in xrange(len(self)):
04745 if self.term[i] != objct.term[i]:
04746 return -1
04747
04748 if self.exponent != objct.exponent:
04749 return -1
04750
04751 return 0
04752
04753
04754
04755
04756
04757
04758
04759
04760 def is_null(self):
04761 if self.evaluate() == 0:
04762 return True
04763 else:
04764 return False
04765
04766
04767
04768
04769
04770
04771
04772
04773 def is_equivalent_to_a_single_1(self):
04774
04775 if len(self) == 1:
04776 return self.term[0].is_equivalent_to_a_single_1()
04777
04778 a_term_different_from_0_and_1_has_been_found = False
04779 equivalent_to_1_terms_nb = 0
04780
04781 for term in self:
04782 if term.is_equivalent_to_a_single_1():
04783 equivalent_to_1_terms_nb += 1
04784 elif not term.is_equivalent_to_a_single_0():
04785 a_term_different_from_0_and_1_has_been_found = True
04786
04787 if a_term_different_from_0_and_1_has_been_found:
04788 return False
04789 elif equivalent_to_1_terms_nb == 1:
04790 return True
04791 else:
04792 return False
04793
04794
04795
04796
04797
04798
04799
04800
04801
04802 def is_equivalent_to_a_single_minus_1(self):
04803 a_term_different_from_0_and_minus1_has_been_found = False
04804 equivalent_to_minus1_terms_nb = 0
04805
04806 for term in self:
04807 if term.is_equivalent_to_a_single_minus_1():
04808 equivalent_to_minus1_terms_nb += 1
04809 elif not term.is_equivalent_to_a_single_0():
04810 a_term_different_from_0_and_minus1_has_been_found = True
04811
04812 if a_term_different_from_0_and_minus1_has_been_found:
04813 return False
04814 elif equivalent_to_minus1_terms_nb == 1:
04815 return True
04816 else:
04817 return False
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827 def is_equivalent_to_a_single_0(self):
04828 return self.is_equivalent_to_a_single_neutral(Item(0))
04829
04830
04831
04832
04833
04834
04835
04836
04837
04838
04839 def is_reducible(self):
04840 if self.is_equivalent_to_a_single_0() \
04841 or self.is_equivalent_to_a_single_1() \
04842 or self.is_equivalent_to_a_single_minus_1():
04843
04844 return False
04845
04846 lexi = self.get_terms_lexicon()[0]
04847
04848
04849
04850 for key in lexi:
04851 if len(lexi[key].term) >= 2:
04852 return True
04853
04854 return False
04855
04856
04857
04858
04859
04860
04861
04862
04863 def get_minus_signs_nb(self):
04864 return 0
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874
04875 def next_displayable_term_nb(self, position):
04876 for i in xrange(len(self) - 1 - position):
04877 if not self.term[i + 1 + position].is_equivalent_to_a_single_0():
04878 return i + 1 + position
04879 return None
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891 def multiply_symbol_is_required(self, objct, position):
04892
04893 if isinstance(objct, Item):
04894 if len(self) >= 2:
04895 if objct.is_numeric() or (objct.is_literal() \
04896 and objct.sign == '-'):
04897 return True
04898 else:
04899 return False
04900 else:
04901 return self.term[0].multiply_symbol_is_required(objct,
04902 position)
04903
04904
04905 if isinstance(objct, Sum):
04906 if len(self) >= 2 and len(objct) >= 2:
04907 return False
04908 if len(self) == 1:
04909 return self.term[0].multiply_symbol_is_required(objct,
04910 position)
04911 if len(objct) == 1:
04912 return self.multiply_symbol_is_required(objct.term[0],
04913 position)
04914
04915
04916 if isinstance(objct, Product):
04917 if len(self) == 1:
04918 return self.term[0].multiply_symbol_is_required(objct,
04919 position)
04920 else:
04921 return self.multiply_symbol_is_required(objct.factor[0],
04922 position)
04923
04924
04925 if isinstance(objct, Quotient):
04926 return True
04927
04928
04929
04930
04931
04932
04933
04934
04935
04936
04937
04938 def requires_brackets(self, position):
04939
04940 tested_sum = None
04941 if self.compact_display:
04942 tested_sum = self.throw_away_the_neutrals()
04943
04944 else:
04945 tested_sum = self.deep_copy()
04946
04947 if len(tested_sum) >= 2:
04948
04949
04950 debug.write( \
04951 "\n[SUM] requires_brackets : self.requires_inner_brackets = " \
04952 + str(tested_sum.requires_inner_brackets()) \
04953 + "\n",
04954 case=debug.requires_brackets_in_sum)
04955 return not tested_sum.requires_inner_brackets()
04956
04957
04958 else:
04959
04960
04961
04962
04963
04964 if not tested_sum.exponent.is_equivalent_to_a_single_1():
04965 return tested_sum.term[0].requires_brackets(position + 1)
04966 else:
04967 return tested_sum.term[0].requires_brackets(position)
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979 def requires_inner_brackets(self):
04980 if self.exponent_must_be_displayed():
04981 if len(self) == 1 or self.is_equivalent_to_a_single_1():
04982 if not (self.get_sign() == '+' and self.term[0].is_numeric()):
04983 return True
04984 else:
04985 return False
04986
04987
04988 else:
04989 return True
04990
04991 return False
04992
04993
04994
04995
04996
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010 def numeric_terms_require_to_be_reduced(self):
05011 at_least_one_numeric_term_has_been_found = False
05012 at_least_two_numeric_terms_have_been_found = False
05013 two_scattered_terms_have_been_found = False
05014 last_numeric_term_position = -1
05015 for i in xrange(len(self)):
05016 if self.term[i].is_equivalent_to_a_single_numeric_Item():
05017 if not at_least_one_numeric_term_has_been_found:
05018 at_least_one_numeric_term_has_been_found = True
05019 last_numeric_term_position = i
05020 else:
05021 at_least_two_numeric_terms_have_been_found = True
05022 if last_numeric_term_position == i - 1:
05023 last_numeric_term_position = i
05024 else:
05025 two_scattered_terms_have_been_found = True
05026
05027 if at_least_two_numeric_terms_have_been_found \
05028 and not two_scattered_terms_have_been_found:
05029
05030 return True
05031
05032
05033
05034
05035
05036
05037 def get_numeric_terms(self):
05038 numeric_terms_list = []
05039
05040 for term in self:
05041 if isinstance(term, Sum):
05042 numeric_terms_list = numeric_terms_list \
05043 + term.get_numeric_terms()
05044
05045 elif term.is_numeric():
05046 numeric_terms_list.append(term)
05047
05048 return numeric_terms_list
05049
05050
05051
05052
05053
05054
05055
05056
05057 def get_literal_terms(self):
05058 literal_terms_list = []
05059
05060 for term in self:
05061 if isinstance(term, Sum):
05062 literal_terms_list = literal_terms_list \
05063 + term.get_literal_terms()
05064
05065 elif not term.is_numeric():
05066 literal_terms_list.append(term)
05067
05068 return literal_terms_list
05069
05070
05071
05072
05073
05074
05075
05076
05077
05078
05079
05080
05081
05082
05083
05084
05085
05086
05087
05088
05089 def get_terms_lexicon(self):
05090
05091 lexi = {}
05092
05093 index = []
05094
05095
05096 for term in self:
05097
05098
05099 if isinstance(term, Item) and term.is_numeric():
05100 put_term_in_lexicon(__.NUMERIC, term, lexi)
05101 if not __.NUMERIC in index:
05102 index.append(__.NUMERIC)
05103
05104
05105 elif isinstance(term, Item) and term.is_literal():
05106
05107
05108
05109 if term.is_positive():
05110 associated_coeff = Item(1)
05111 else:
05112 associated_coeff = Item(-1)
05113
05114
05115
05116 positive_associated_item = Item(('+',
05117 term.value,
05118 term.exponent))
05119
05120
05121 put_term_in_lexicon(positive_associated_item,
05122 associated_coeff,
05123 lexi)
05124 if not positive_associated_item in index:
05125 index.append(positive_associated_item)
05126
05127
05128 elif isinstance(term, Monomial):
05129 if term.get_degree() == 0 or term.is_null():
05130 put_term_in_lexicon(__.NUMERIC, term[0], lexi)
05131 if not __.NUMERIC in index:
05132 index.append(__.NUMERIC)
05133 else:
05134 put_term_in_lexicon(term[1], term[0], lexi)
05135 if not term[1] in index:
05136 index.append(term[1])
05137
05138
05139 elif isinstance(term, Product):
05140
05141 aux_product = term.reduce_()
05142
05143
05144
05145 associated_coeff = aux_product.factor.pop(0)
05146
05147
05148
05149
05150 if len(aux_product.factor) == 0:
05151 put_term_in_lexicon(__.NUMERIC, associated_coeff, lexi)
05152 if not __.NUMERIC in index:
05153 index.append(__.NUMERIC)
05154
05155
05156
05157
05158
05159
05160 elif len(aux_product.factor) == 1 \
05161 and isinstance(aux_product.factor[0], Item) \
05162 and aux_product.factor[0].is_literal():
05163
05164 put_term_in_lexicon(aux_product.factor[0], \
05165 associated_coeff, \
05166 lexi)
05167 if not aux_product.factor[0] in index:
05168 index.append(aux_product.factor[0])
05169
05170
05171
05172
05173 else:
05174 put_term_in_lexicon(aux_product, associated_coeff, lexi)
05175 if not aux_product in index:
05176 index.append(aux_product)
05177
05178
05179
05180 elif isinstance(term, Sum):
05181
05182
05183
05184
05185
05186
05187 if term.exponent != Value(1):
05188 associated_coeff = Item(1)
05189 put_term_in_lexicon(term, associated_coeff, lexi)
05190
05191 if not term in index:
05192 index.append(term)
05193
05194 else:
05195
05196
05197 lexi_index_tuple_to_add = term.get_terms_lexicon()
05198
05199 lexi_to_add = lexi_index_tuple_to_add[0]
05200 index_to_add = lexi_index_tuple_to_add[1]
05201
05202
05203
05204 additional_keys = list()
05205
05206
05207
05208
05209
05210
05211 for suppl_key in index_to_add:
05212
05213
05214
05215
05216 added_key = False
05217
05218 for key in lexi:
05219 if key == suppl_key:
05220 for objct in lexi_to_add[suppl_key].term:
05221 put_term_in_lexicon(key, objct, lexi)
05222
05223
05224
05225
05226 added_key = True
05227
05228 if not added_key:
05229 additional_keys.append(suppl_key)
05230
05231
05232
05233
05234
05235
05236
05237
05238 for suppl_key in additional_keys:
05239 lexi[suppl_key] = lexi_to_add[suppl_key]
05240 index.append(suppl_key)
05241
05242 return (lexi, index)
05243
05244
05245
05246
05247
05248
05249
05250
05251 def set_force_inner_brackets_display(self, arg):
05252 self.force_inner_brackets_display = arg
05253
05254
05255
05256
05257
05258
05259
05260
05261 def set_term(self, n, arg):
05262 self.element[n] = arg
05263
05264
05265
05266
05267
05268
05269
05270
05271
05272 def calculate_next_step(self, **options):
05273 if not self.is_numeric():
05274 return self.expand_and_reduce_next_step(**options)
05275
05276 copy = self.deep_copy()
05277
05278 debug.write("\n[SUM] Entering calculate_next_step\n"\
05279 + "with copied Sum :\n" \
05280 + str(copy),
05281 case=debug.calculate_next_step_sum)
05282
05283 if len(copy) == 1 and (isinstance(copy.term[0], Operation) \
05284 or isinstance(copy.term[0], Fraction)):
05285
05286
05287 debug.write("\n[SUM]Exiting calculate_next_step" \
05288 + "diving recursively in element[0]",
05289 case=debug.calculate_next_step_sum)
05290 return copy.term[0].calculate_next_step(**options)
05291
05292
05293
05294
05295 a_term_has_been_depacked = False
05296 for i in xrange(len(copy)):
05297 if (isinstance(copy.term[i], Operation) \
05298 and len(copy.term[i]) == 1) \
05299 or isinstance(copy.term[i], Monomial):
05300
05301 copy.element[i] = copy.term[i].element[0]
05302 a_term_has_been_depacked = True
05303
05304 if a_term_has_been_depacked:
05305
05306 debug.write("\n[SUM]Exiting calculate_next_step" \
05307 + "having depacked one element at least" \
05308 + "\ncalculate_next_step is called on :\n"\
05309 + str(copy),
05310 case=debug.calculate_next_step_sum)
05311 return copy.calculate_next_step(**options)
05312
05313
05314
05315
05316
05317
05318 a_minus_sign_in_a_fraction_was_found = False
05319 for i in xrange(len(copy)):
05320 if isinstance(copy.term[i], Fraction) \
05321 and (copy.term[i].numerator.get_sign() == '-'\
05322 or copy.term[i].denominator.get_sign() == '-'):
05323
05324
05325 copy.element[i].set_sign( \
05326 lib.sign_of_product([ \
05327 copy.element[i].get_sign(),
05328 copy.element[i].numerator.get_sign(),
05329 copy.element[i].denominator.get_sign()])
05330 )
05331 copy.element[i].numerator.set_sign('+')
05332 copy.element[i].denominator.set_sign('+')
05333 a_minus_sign_in_a_fraction_was_found = True
05334
05335 if a_minus_sign_in_a_fraction_was_found:
05336
05337 debug.write("\n[SUM]Exiting calculate_next_step" \
05338 + "having changed negative denominators" \
05339 + "\nthe returned object is :\n"\
05340 + str(copy),
05341 case=debug.calculate_next_step_sum)
05342 return copy
05343
05344
05345
05346
05347
05348
05349
05350
05351 numeric_items_nb = 0
05352 fractions_nb = 0
05353
05354 for i in xrange(len(copy)):
05355 if isinstance(copy.term[i], Fraction):
05356 fractions_nb += 1
05357 elif isinstance(copy.term[i], Item) \
05358 and copy.term[i].is_numeric():
05359
05360 numeric_items_nb += 1
05361 elif isinstance(copy.term[i], Product) \
05362 and len(copy.term[i]) == 1 \
05363 and isinstance(copy.term[i].factor[0], Item) \
05364 and copy.term[i].factor[0].is_numeric():
05365
05366 copy.element[i] = copy.term[i].factor[0]
05367 numeric_items_nb += 1
05368
05369
05370 debug.write("\n[SUM]calculate_next_step\n" \
05371 + "We found : " \
05372 + str(fractions_nb) + " fractions, and " \
05373 + str(numeric_items_nb) \
05374 + " numeric items.\n",
05375 case=debug.calculate_next_step_sum)
05376
05377
05378
05379 fractions_have_been_added = False
05380 dont_touch_these = []
05381
05382 if fractions_nb >= 1:
05383
05384
05385 lexi = {}
05386 for objct in copy:
05387 if isinstance(objct, Fraction):
05388 put_term_in_lexicon(objct.denominator, objct, lexi)
05389
05390
05391 if debug.calculate_next_step_sum and debug.ENABLED:
05392 built_lexi = ""
05393 for key in lexi:
05394 built_lexi += "Key : " + str(key) + \
05395 "\nValue : " + str(lexi[key]) + "\n"
05396 debug.write("\n[SUM]calculate_next_step\n" \
05397 + "Looking for fractions having the "\
05398 + "same denominator ; " \
05399 + "built the lexicon : \n" \
05400 + str(built_lexi),
05401 case=debug.calculate_next_step_sum)
05402
05403
05404
05405 for denominator_key in lexi:
05406 if len(lexi[denominator_key]) >= 2:
05407 fractions_have_been_added = True
05408 common_denominator = denominator_key
05409 numes_list = []
05410 for fraction in lexi[denominator_key]:
05411 if fraction.sign == '+':
05412 numes_list.append(fraction.numerator)
05413 else:
05414 new_term = Product([Item(-1)] \
05415 + fraction.numerator.factor)
05416 if fraction.numerator.get_sign() == '+':
05417 new_term = new_term.reduce_()
05418 new_term.compact_display = True
05419 numes_list.append(new_term)
05420
05421 new_fraction = Fraction((Sum(numes_list),
05422 common_denominator))
05423
05424
05425 debug.write("\n[SUM]calculate_next_step\n" \
05426 + "Found " \
05427 + str(len(lexi[denominator_key])) \
05428 + " fractions having this denominator "\
05429 + "\n" + str(denominator_key)\
05430 + "\n new_fraction looks like :\n" \
05431 + str(new_fraction),
05432 case=debug.calculate_next_step_sum)
05433
05434 first_fraction_met = True
05435 for i in xrange(len(copy)):
05436 if not i >= len(copy):
05437
05438 debug.write(\
05439 "\n[SUM]calculate_next_step\n" \
05440 + "copy.term[" + str(i) + "] = " \
05441 + str(copy.term[i]) \
05442 + "\nlooked for here :\n" \
05443 + str(lexi[denominator_key]),
05444 case=debug.calculate_next_step_sum)
05445 if isinstance(copy.term[i], Fraction) \
05446 and copy.term[i] in lexi[denominator_key].term:
05447
05448
05449 debug.write(\
05450 "\n[SUM]calculate_next_step\n" \
05451 + "copy.term[" + str(i) + "] is in"\
05452 + " this lexicon :\n" \
05453 + str(lexi[denominator_key]),
05454 case=debug.calculate_next_step_sum)
05455 if first_fraction_met:
05456 copy.element[i] = new_fraction
05457 first_fraction_met = False
05458 dont_touch_these.append(new_fraction)
05459 else:
05460 copy.remove(copy.term[i])
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470 some_terms_have_been_moved = False
05471 max_found_gap = 1
05472 last_numeric_item_position = 0
05473
05474 if numeric_items_nb >= 2:
05475 numeric_terms_collection = []
05476 for i in xrange(len(copy)):
05477 if isinstance(copy.term[i], Item) \
05478 and copy.term[i].is_numeric():
05479
05480 if i - last_numeric_item_position > max_found_gap:
05481 max_found_gap = i - last_numeric_item_position
05482 last_numeric_item_position = i
05483 numeric_terms_collection.append(copy.term[i])
05484
05485
05486
05487
05488 if fractions_nb >= 1:
05489 first_numeric_item_met = True
05490 for i in xrange(len(copy)):
05491 if not i >= len(copy) \
05492 and isinstance(copy.term[i], Item) \
05493 and copy.term[i].is_numeric():
05494
05495 if first_numeric_item_met:
05496 copy.term[i] = Sum(numeric_terms_collection)
05497 first_numeric_item_met = False
05498 if max_found_gap >= 2:
05499 some_terms_have_been_moved = True
05500 dont_touch_these.append(copy.term[i])
05501 else:
05502 copy.remove(copy.term[i])
05503
05504
05505
05506
05507
05508 a_term_has_been_modified = False
05509
05510 for i in xrange(len(copy)):
05511 if not copy.term[i] in dont_touch_these:
05512 temp = copy.term[i].calculate_next_step(**options)
05513 if temp != None:
05514 copy.term[i] = temp
05515 a_term_has_been_modified = True
05516
05517
05518
05519
05520 if fractions_have_been_added \
05521 or a_term_has_been_modified \
05522 or some_terms_have_been_moved:
05523
05524 return copy
05525
05526
05527
05528
05529
05530
05531
05532
05533 if len(copy) == 1:
05534
05535
05536 return None
05537
05538
05539 if numeric_items_nb >= 1 and fractions_nb == 0:
05540 return Sum([Item(copy.evaluate())])
05541
05542
05543 if numeric_items_nb == 0 and fractions_nb >= 1:
05544 denos_list = []
05545 for i in xrange(len(copy)):
05546 denos_list.append(copy.term[i].denominator.factor[0].value)
05547
05548 lcm = lib.lcm_of_the_list(denos_list)
05549 lcm_item = Item(lcm)
05550
05551
05552
05553
05554
05555
05556 same_deno_reduction_required = False
05557
05558 for i in xrange(len(copy)):
05559 if lcm_item != copy.term[i].denominator.factor[0]:
05560 same_deno_reduction_required = True
05561
05562 if same_deno_reduction_required:
05563 for i in xrange(len(copy)):
05564 aux_item = Item(int(lcm/copy.term[i].\
05565 denominator.factor[0].value))
05566 if aux_item.value != 1:
05567 copy.term[i].numerator = \
05568 Product([copy.term[i].numerator.factor[0],
05569 aux_item])
05570 copy.term[i].numerator.compact_display = False
05571 copy.term[i].denominator = \
05572 Product([copy.term[i].denominator.factor[0],
05573 aux_item])
05574 copy.term[i].denominator.compact_display = False
05575 copy.term[i].same_deno_reduction_in_progress = True
05576
05577 else:
05578 numes_list = []
05579 for i in xrange(len(copy)):
05580 numes_list.append(copy.term[i].\
05581 numerator.factor[0].times( \
05582 Item((copy.term[i].sign, 1))).\
05583 reduce_().factor[0]
05584 )
05585
05586 copy = Sum([Fraction(('+',
05587 Sum(numes_list),
05588 lcm_item))])
05589
05590 return copy
05591
05592
05593 if numeric_items_nb >= 1 and fractions_nb >= 1:
05594
05595 for i in xrange(len(copy)):
05596 if isinstance(copy.term[i], Item) \
05597 and copy.term[i].is_numeric():
05598
05599 copy.term[i] = copy.term[i].turn_into_fraction()
05600 copy.term[i].same_deno_reduction_in_progress = True
05601
05602 return copy.calculate_next_step(**options)
05603
05604
05605
05606
05607
05608
05609
05610
05611
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624
05625
05626 def intermediate_reduction_line(self):
05627
05628
05629
05630
05631
05632
05633
05634
05635 numeric_terms_must_be_reduced = False
05636
05637 if self.numeric_terms_require_to_be_reduced():
05638
05639 numeric_terms_must_be_reduced = True
05640
05641
05642 (lexi, index) = self.get_terms_lexicon()
05643
05644 final_sum_terms_list = list()
05645
05646 for key in index:
05647 if key == __.NUMERIC:
05648 temp_object = lexi[key]
05649 if numeric_terms_must_be_reduced:
05650 temp_object = Item(temp_object.evaluate())
05651 elif len(temp_object) == 1:
05652 temp_object = temp_object.term[0]
05653
05654 elif lexi[key].is_equivalent_to_a_single_1():
05655 temp_object = key
05656
05657 else:
05658 if len(lexi[key]) == 1:
05659 temp_object = Product([lexi[key].term[0], key])
05660 else:
05661 temp_object = Product([lexi[key], key])
05662
05663 final_sum_terms_list.append(temp_object)
05664
05665 final_sum = Sum(final_sum_terms_list)
05666
05667 if self.force_inner_brackets_display:
05668 final_sum.set_force_inner_brackets_display(True)
05669
05670 return final_sum
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687
05688
05689 def reduce_(self):
05690
05691
05692 (lexi, index) = self.get_terms_lexicon()
05693
05694
05695 debug.write("\n[SUM] Entered reduce_ with the Sum :\n"\
05696 + str(self),
05697 case=debug.reduce_in_sum)
05698
05699 if debug.ENABLED and debug.reduce_in_sum:
05700 lexi_content = ""
05701 for elt in lexi:
05702 lexi_content += str(elt) + " : " + str(lexi[elt]) + " ; "
05703
05704 debug.write("\nget_terms_lexicon returned this : "\
05705 + lexi_content,
05706 case=debug.reduce_in_sum)
05707
05708
05709 final_sum_terms_list = list()
05710
05711 for key in index:
05712
05713 if key == __.NUMERIC:
05714 temp_object = lexi[key].evaluate()
05715
05716 elif lexi[key].is_equivalent_to_a_single_1():
05717 temp_object = key
05718
05719 else:
05720 computed_coeff = Item(lexi[key].evaluate())
05721 if computed_coeff.is_equivalent_to_a_single_0():
05722 temp_object = computed_coeff
05723 else:
05724 temp_object = Product([computed_coeff, key])
05725
05726 final_sum_terms_list.append(temp_object)
05727
05728 final_sum = (Sum(final_sum_terms_list)).throw_away_the_neutrals()
05729
05730 if self.force_inner_brackets_display:
05731 final_sum.set_force_inner_brackets_display(True)
05732
05733
05734
05735 if len(final_sum) == 1 \
05736 and final_sum.term[0].exponent.is_equivalent_to_a_single_1():
05737
05738 final_sum = final_sum.term[0]
05739
05740
05741 debug.write("\n[SUM] Leaving reduce_, returning :\n"\
05742 + str(final_sum),
05743 case=debug.reduce_in_sum)
05744
05745 return final_sum
05746
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756
05757 def expand_and_reduce_next_step(self, **options):
05758 if self.is_numeric():
05759 return self.calculate_next_step(**options)
05760
05761
05762 debug.write("\nEntered :\n" \
05763 + "[expand_and_reduce_next_step_sum]\n" \
05764 + "Current Sum is : \n" \
05765 + str(self) + "\n" \
05766 + str(self.display_complete_writing)\
05767 + "\n",
05768 case=debug.expand_and_reduce_next_step_sum)
05769
05770 copy = Sum(self).throw_away_the_neutrals()
05771
05772
05773
05774
05775
05776
05777
05778
05779 new_copy = Sum(copy)
05780 new_copy.element = list()
05781 new_copy.info = list()
05782 an_imbricated_sum_has_been_found = False
05783 a_degree_0_monomial_has_been_found = False
05784
05785 for i in xrange(len(copy)):
05786 if (not isinstance(copy.term[i], Sum) \
05787 or (isinstance(copy.term[i], Sum) \
05788 and not copy.term[i].exponent.is_equivalent_to_a_single_1( \
05789 )))\
05790 and not (isinstance(copy.term[i], Monomial) \
05791 and copy.term[i].degree == 0):
05792
05793 new_copy.element.append(copy.term[i])
05794 new_copy.display_complete_writing.append( \
05795 copy.display_complete_writing[i])
05796
05797 elif isinstance(copy.term[i], Monomial) \
05798 and copy.term[i].degree == 0:
05799
05800 new_copy.element.append(copy.term[i].factor[0])
05801 new_copy.display_complete_writing.append( \
05802 copy.display_complete_writing[i])
05803 else:
05804 an_imbricated_sum_has_been_found = True
05805 for j in xrange(len(copy.term[i])):
05806 new_copy.element.append(copy.term[i].term[j])
05807 new_copy.display_complete_writing.append( \
05808 copy.term[i].display_complete_writing[j])
05809
05810 if an_imbricated_sum_has_been_found \
05811 or a_degree_0_monomial_has_been_found:
05812
05813
05814 debug.write("\nExiting recursively :\n" \
05815 + "[expand_and_reduce_next_step_sum]\n" \
05816 + "a term has been modified, " \
05817 + "recursive call on :\n"\
05818 + str(new_copy) \
05819 + "\n",
05820 case=debug.expand_and_reduce_next_step_sum)
05821
05822 return new_copy.expand_and_reduce_next_step(**options)
05823
05824
05825
05826
05827 a_term_at_least_has_been_modified = False
05828
05829
05830
05831 numeric_terms_must_be_reduced = False
05832 the_first_numeric_term_has_been_found = False
05833
05834 if copy.numeric_terms_require_to_be_reduced():
05835
05836 numeric_terms_must_be_reduced = True
05837 (lexi, index) = copy.get_terms_lexicon()
05838 numeric_value = Item(lexi[__.NUMERIC].evaluate())
05839
05840
05841
05842
05843
05844 terms_to_remove = list()
05845
05846
05847 modified_term = list()
05848
05849
05850
05851
05852 for i in xrange(len(copy)):
05853 test = copy.term[i].expand_and_reduce_next_step(**options)
05854 if test != None:
05855 copy.term[i] = test
05856 a_term_at_least_has_been_modified = True
05857 modified_term.append(True)
05858 else:
05859 modified_term.append(False)
05860
05861
05862
05863 if numeric_terms_must_be_reduced \
05864 and a_term_at_least_has_been_modified:
05865
05866 for i in xrange(len(copy)):
05867 if copy.term[i].is_numeric() \
05868 and not modified_term[i]:
05869
05870 if the_first_numeric_term_has_been_found:
05871 terms_to_remove.append(copy.term[i])
05872 else:
05873 copy.term[i] = numeric_value
05874 the_first_numeric_term_has_been_found = True
05875
05876 for j in xrange(len(terms_to_remove)):
05877 copy.remove(terms_to_remove[j])
05878
05879
05880
05881
05882
05883
05884
05885
05886
05887
05888
05889
05890
05891
05892
05893
05894 if a_term_at_least_has_been_modified:
05895
05896 debug.write("\nExiting :\n" \
05897 + "[expand_and_reduce_next_step_sum]\n" \
05898 + "a term has been modified, returning :\n"\
05899 + str(copy) \
05900 + "\n",
05901 case=debug.expand_and_reduce_next_step_sum)
05902 return copy
05903
05904
05905 else:
05906 if copy.is_numeric() and copy.is_reducible():
05907
05908 debug.write("\nExiting :\n" \
05909 + "[expand_and_reduce_next_step_sum]\n"\
05910 + "no term has been modified, but : "\
05911 + str(copy) \
05912 + "\nis numeric and reducible\n" \
05913 + "returning a reduced copy of it",
05914 case=debug.expand_and_reduce_next_step_sum)
05915
05916 return copy.reduce_()
05917
05918 elif copy.is_reducible():
05919 debug.write("\nExiting :\n" \
05920 + "[expand_and_reduce_next_step_sum]\n"\
05921 + "no term has been modified, and : "\
05922 + str(copy) \
05923 + "\nisn't numeric but is reducible\n" \
05924 + "returning the intermediate line " \
05925 + "generated from it",
05926 case=debug.expand_and_reduce_next_step_sum)
05927
05928 return copy.intermediate_reduction_line()
05929
05930 else:
05931 debug.write("\nExiting :\n" \
05932 + "[expand_and_reduce_next_step_sum]\n"\
05933 + "no term has been modified, and : "\
05934 + str(copy) \
05935 + "\nisn't numeric nor reducible, " \
05936 + "returning None\n",
05937 case=debug.expand_and_reduce_next_step_sum)
05938
05939 return None
05940
05941
05942
05943
05944
05945
05946
05947
05948
05949
05950 def make_string(self, markup, **options):
05951 global expression_begins
05952
05953 if 'force_expression_begins' in options \
05954 and options['force_expression_begins'] == True:
05955
05956 expression_begins = options['force_expression_begins']
05957 options['force_expression_begins'] = False
05958
05959
05960
05961
05962
05963
05964
05965 resulting_string = ""
05966
05967
05968
05969
05970 flag = False
05971
05972
05973
05974
05975
05976
05977
05978
05979
05980
05981 debug.write( \
05982 "\nIn make_string in Sum : expression_begins = " \
05983 + str(expression_begins) \
05984 + "\nforce_inner_brackets_display = " \
05985 + str(self.force_inner_brackets_display),
05986 case=debug.make_string_in_sum)
05987
05988 if ((not (self.exponent.is_equivalent_to_a_single_1())) \
05989 and (len(self) >= 2 \
05990 or \
05991 (len(self) == 1 and self.term[0].get_sign() == '-'))) \
05992 or self.force_inner_brackets_display:
05993
05994 if not expression_begins:
05995 resulting_string += markup['plus'] + markup['opening_bracket']
05996 else:
05997 resulting_string += markup['opening_bracket']
05998
05999 expression_begins = True
06000
06001
06002
06003 if self.compact_display:
06004 for i in xrange(len(self)):
06005
06006 if not self.term[i].is_equivalent_to_a_single_0():
06007 resulting_string += self.term[i].make_string(markup,
06008 **options)
06009 flag = True
06010 next_term_nb = self.next_displayable_term_nb(i)
06011
06012
06013 if debug.ENABLED and debug.make_string_in_sum:
06014 if next_term_nb == None:
06015 debug.write( \
06016 "\nIn make_string in Sum : " \
06017 + "no next term to display.",
06018 case=debug.make_string_in_sum)
06019 else:
06020 debug.write( \
06021 "\nIn make_string in Sum : " \
06022 + "the next term to display is " \
06023 + str(self.term[next_term_nb]),
06024 case=debug.make_string_in_sum)
06025
06026 if next_term_nb != None \
06027 and ( \
06028 self.term[next_term_nb].requires_inner_brackets() \
06029 or (isinstance(self.term[next_term_nb], Product) \
06030 and \
06031 (self.term[next_term_nb].factor[0].requires_brackets(0)\
06032 or self.term[next_term_nb].factor[0].is_equivalent_to_a_single_0()\
06033 ) and not \
06034 (len(self.term[next_term_nb].throw_away_the_neutrals()) == 1 \
06035 and self.term[next_term_nb].throw_away_the_neutrals() \
06036 .factor[0].requires_brackets(0)
06037 )
06038 ) \
06039 ):
06040
06041
06042 debug.write( \
06043 "\nIn make_string in Sum : " \
06044 + "adding a + for the next term in case it can't"\
06045 + " do that itself.\n",
06046 case=debug.make_string_in_sum)
06047
06048
06049
06050
06051
06052
06053
06054
06055
06056
06057
06058
06059
06060
06061
06062
06063 resulting_string += markup['plus']
06064 expression_begins = True
06065
06066
06067 else:
06068 for i in xrange(len(self)):
06069 if self.display_complete_writing[i] \
06070 and not self.term[i].requires_inner_brackets() \
06071 and not self.term[i].is_equivalent_to_a_single_0():
06072
06073 resulting_string += markup['opening_bracket'] \
06074 + self.term[i].make_string(markup, \
06075 force_display_sign='ok',\
06076 **options) \
06077 + markup['closing_bracket']
06078 flag = True
06079
06080 elif not self.term[i].is_equivalent_to_a_single_0():
06081 resulting_string += self.term[i].make_string(markup,
06082 **options)
06083 flag = True
06084
06085
06086
06087 next_term_nb = self.next_displayable_term_nb(i)
06088
06089 if next_term_nb != None \
06090 and self.display_complete_writing[next_term_nb]:
06091
06092 resulting_string += markup['plus']
06093 expression_begins = True
06094
06095
06096 if flag == False:
06097 resulting_string += markup['zero']
06098
06099
06100
06101
06102 if ((not (self.exponent.is_equivalent_to_a_single_1())) \
06103 and (len(self) >= 2 \
06104 or \
06105 (len(self) == 1 and self.term[0].get_sign() == '-'))) \
06106 or self.force_inner_brackets_display:
06107
06108 resulting_string += markup['closing_bracket']
06109
06110 if self.exponent_must_be_displayed():
06111 expression_begins = True
06112 exponent_string = self.exponent.make_string(markup,
06113 **options)
06114 resulting_string += markup['opening_exponent'] \
06115 + exponent_string \
06116 + markup['closing_exponent']
06117
06118 return resulting_string
06119
06120
06121
06122
06123
06124
06125
06126
06127
06128
06129 class Quotient(Exponented):
06130
06131
06132
06133
06134
06135
06136
06137
06138
06139
06140
06141
06142
06143
06144
06145
06146 def __init__(self, arg, **options):
06147
06148 self.exponent = Value(1)
06149
06150 self.numerator = Value(1)
06151 self.denominator = Value(1)
06152 self.sign = '+'
06153 self.symbol = 'like_a_fraction'
06154
06155 if 'use_divide_symbol' in options:
06156 self.symbol = 'use_divide_symbol'
06157
06158
06159 if type(arg) == tuple and len(arg) >= 3 and is_.a_sign(arg[0]) \
06160 and \
06161 (is_.a_calculable(arg[1]) or is_.a_number(arg[1]) or \
06162 is_.a_string(arg[1])) \
06163 and \
06164 (is_.a_calculable(arg[2]) or is_.a_number(arg[2]) or \
06165 is_.a_string(arg[2])):
06166
06167 self.sign = arg[0]
06168 if is_.a_number(arg[1]) or is_.a_string(arg[1]):
06169 self.numerator = Item(arg[1])
06170 else:
06171 self.numerator = arg[1].deep_copy()
06172
06173 if is_.a_number(arg[2]) or is_.a_string(arg[2]):
06174 self.denominator = Item(arg[2])
06175 else:
06176 self.denominator = arg[2].deep_copy()
06177
06178
06179 if len(arg) >= 4:
06180 if is_.a_number(arg[3]):
06181 self.exponent = Value(arg[3])
06182 else:
06183 self.exponent = arg[3].deep_copy()
06184
06185 if len(arg) >= 5:
06186 self.symbol = arg[4]
06187
06188
06189 elif isinstance(arg, Quotient):
06190 self.exponent = arg.exponent.deep_copy()
06191 self.numerator = arg.numerator.deep_copy()
06192 self.denominator = arg.denominator.deep_copy()
06193 self.sign = arg.sign
06194 self.symbol = arg.symbol
06195
06196
06197 else:
06198 raise error.UncompatibleType(arg,
06199 "(sign, numerator, denominator)|\
06200 (sign, numerator, denominator, exponent)")
06201
06202
06203
06204
06205
06206
06207
06208
06209
06210
06211 def __str__(self, **options):
06212 return "Q# " + \
06213 str(self.sign) + \
06214 " ( " + \
06215 str(self.numerator) + \
06216 " / " + \
06217 str(self.denominator) + \
06218 " ) ^ { " + \
06219 str(self.exponent) + \
06220 " } #Q"
06221
06222
06223
06224
06225
06226
06227
06228
06229
06230
06231
06232 def __len__(self):
06233 return 1
06234
06235
06236
06237
06238
06239
06240
06241 def is_numeric(self):
06242 if self.numerator.is_numeric() and self.denominator.is_numeric():
06243 return True
06244 else:
06245 return False
06246
06247
06248
06249
06250
06251
06252
06253
06254 def is_literal(self):
06255 if self.numerator.is_literal() and self.denominator.is_literal():
06256 return True
06257 else:
06258 return False
06259
06260
06261
06262
06263
06264
06265
06266
06267 def is_null(self):
06268 return self.numerator.is_null()
06269
06270
06271
06272
06273
06274
06275
06276
06277
06278 def is_negative(self):
06279 if self.sign == '-':
06280 return True
06281 else:
06282 return False
06283
06284
06285
06286
06287
06288
06289
06290
06291
06292
06293 def is_positive(self):
06294 if self.sign == '+':
06295 return True
06296 else:
06297 return False
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310 def is_equivalent_to_a_single_1(self):
06311 if self.sign == '+' and \
06312 self.numerator.is_equivalent_to_a_single_1() and \
06313 self.denominator.is_equivalent_to_a_single_1():
06314 return True
06315
06316 else:
06317 return False
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329 def is_equivalent_to_a_single_minus_1(self):
06330 if self.sign == '-' and \
06331 self.numerator.is_equivalent_to_a_single_1() and \
06332 self.denominator.is_equivalent_to_a_single_1():
06333
06334 return True
06335
06336 else:
06337 return False
06338
06339
06340
06341
06342
06343
06344
06345
06346
06347 def is_equivalent_to_a_single_0(self):
06348 return self.numerator.is_equivalent_to_a_single_0()
06349
06350
06351
06352
06353
06354
06355
06356
06357 def is_equivalent_to_a_single_numeric_Item(self):
06358 if not self.is_numeric():
06359 return False
06360 else:
06361 return self.denominator.is_equivalent_to_a_single_1() \
06362 and self.numerator.is_equivalent_to_a_single_numeric_Item()
06363
06364
06365
06366
06367
06368
06369
06370
06371 def is_equivalent_to_an_irreducible_Fraction(self):
06372 return False
06373
06374
06375
06376
06377
06378
06379
06380
06381
06382
06383 def multiply_symbol_is_required(self, objct, position):
06384
06385 if isinstance(objct, Quotient):
06386 return True
06387
06388
06389 if objct.is_literal():
06390 return False
06391 else:
06392 return True
06393
06394
06395
06396
06397
06398
06399
06400
06401
06402
06403
06404 def requires_brackets(self, position):
06405 if self.sign == '-' and position >= 1:
06406 return True
06407 else:
06408 return False
06409
06410
06411
06412
06413
06414
06415
06416
06417
06418
06419 def requires_inner_brackets(self):
06420 return self.exponent_must_be_displayed()
06421
06422
06423
06424
06425
06426
06427
06428
06429
06430
06431
06432
06433 def contains_exactly(self, objct):
06434 if self.denominator.is_equivalent_to_a_single_1() \
06435 and self.sign == '+':
06436
06437 if self.numerator == objct:
06438 return True
06439 else:
06440 return self.numerator.contains_exactly(objct)
06441
06442 else:
06443 return False
06444
06445
06446
06447
06448
06449
06450
06451
06452
06453
06454
06455 def contains_a_rounded_number(self):
06456 if self.numerator.contains_a_rounded_number() \
06457 or self.denominator.contains_a_rounded_number():
06458
06459 return True
06460
06461 return False
06462
06463
06464
06465
06466
06467
06468
06469
06470 def get_sign(self):
06471 if self.is_null():
06472 return '+'
06473 else:
06474 return self.sign
06475
06476
06477
06478
06479
06480
06481
06482
06483
06484 def get_minus_signs_nb(self):
06485 answer = 0
06486 if self.sign == '-':
06487 answer += 1
06488
06489 return answer + self.numerator.get_minus_signs_nb() \
06490 + self.denominator.get_minus_signs_nb()
06491
06492
06493
06494
06495
06496
06497
06498 def evaluate(self):
06499 if self.sign == '+':
06500 sign = 1
06501 else:
06502 sign = -1
06503
06504 num = self.numerator.evaluate()
06505 deno = self.denominator.evaluate()
06506
06507 return sign * (num / deno) ** self.exponent
06508
06509
06510
06511
06512
06513
06514
06515
06516 def invert(self):
06517 new_quotient = Quotient(self)
06518 if isinstance(self, Fraction):
06519 new_quotient = Fraction(self)
06520 new_quotient.numerator = self.denominator
06521 new_quotient.denominator = self.numerator
06522
06523 return new_quotient
06524
06525
06526
06527
06528
06529
06530
06531
06532
06533 def calculate_next_step(self, **options):
06534
06535
06536 if isinstance(self.denominator, Fraction):
06537 if self.sign == '+':
06538 sign_item = Item(1)
06539 else:
06540 sign_item = Item(-1)
06541
06542 next_step = Product([sign_item,
06543 self.numerator,
06544 self.denominator.invert()])
06545 next_step.set_exponent(self.exponent)
06546 return next_step.throw_away_the_neutrals()
06547
06548 if self.numerator.calculate_next_step(**options) != None:
06549 if self.denominator.calculate_next_step(**options) != None:
06550 return Quotient((self.sign,
06551 self.numerator.calculate_next_step(**options),
06552 self.denominator.calculate_next_step(**options),
06553 self.exponent,
06554 self.symbol))
06555 else:
06556 return Quotient((self.sign,
06557 self.numerator.calculate_next_step(**options),
06558 self.denominator,
06559 self.exponent,
06560 self.symbol))
06561
06562 elif self.denominator.calculate_next_step(**options) != None:
06563 return Quotient((self.sign,
06564 self.numerator,
06565 self.denominator.calculate_next_step(**options),
06566 self.exponent,
06567 self.symbol))
06568
06569
06570 else:
06571 if isinstance(self.denominator, Quotient):
06572 if self.sign == '+':
06573 sign_item = Item(1)
06574 else:
06575 sign_item = Item(-1)
06576
06577 next_step = Product([sign_item,
06578 self.numerator,
06579 self.denominator.invert()])
06580 next_step.set_exponent(self.exponent)
06581 return next_step
06582
06583 else:
06584
06585
06586 return None
06587
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597
06598
06599 def make_string(self, markup, **options):
06600 global expression_begins
06601
06602
06603 debug.write("In make_string of Quotient\nDetails :\n" \
06604 + str(self) \
06605 + "\n",
06606 case=debug.make_string_in_quotient)
06607 if 'force_expression_begins' in options \
06608 and options['force_expression_begins'] == True:
06609
06610 expression_begins = True
06611 options['force_expression_begins'] = False
06612
06613 if 'force_position' in options \
06614 and is_.an_integer(options['force_position']):
06615
06616 temp_options = dict()
06617 for key in options:
06618 if key != 'force_position':
06619 temp_options[key] = options[key]
06620 options = temp_options
06621
06622
06623 sign = ''
06624 nume = ''
06625 deno = ''
06626
06627 if self.sign == '+' and not expression_begins:
06628 sign = markup['plus']
06629 elif self.sign == '-':
06630 sign = markup['minus']
06631
06632 expression_begins = True
06633 nume = self.numerator.make_string(markup,
06634 force_position=0,
06635 **options)
06636 expression_begins = True
06637 deno = self.denominator.make_string(markup,
06638 force_position=0,
06639 **options)
06640
06641 if self.symbol == 'use_divide_symbol':
06642 if isinstance(self.numerator, Sum) \
06643 and len(self.numerator.throw_away_the_neutrals()) >= 2 \
06644 and not self.numerator.requires_inner_brackets():
06645
06646 nume = markup['opening_bracket'] \
06647 + nume \
06648 + markup['closing_bracket']
06649
06650 if isinstance(self.denominator, Sum) \
06651 and len(self.denominator.throw_away_the_neutrals()) >= 2 \
06652 and not self.denominator.requires_inner_brackets():
06653
06654 deno = markup['opening_bracket'] \
06655 + deno \
06656 + markup['closing_bracket']
06657
06658
06659
06660 elif self.denominator.get_sign() == '-':
06661
06662 deno = markup['opening_bracket'] \
06663 + deno \
06664 + markup['closing_bracket']
06665
06666
06667
06668 if self.exponent_must_be_displayed():
06669 expression_begins = True
06670 exponent_string = self.exponent.make_string(markup,
06671 **options)
06672
06673 if self.symbol == 'like_a_fraction':
06674 return sign + markup['opening_bracket'] \
06675 + markup['opening_fraction'] \
06676 + nume \
06677 + markup['fraction_vinculum'] \
06678 + deno \
06679 + markup['closing_fraction'] \
06680 + markup['closing_bracket'] \
06681 + markup['opening_exponent'] \
06682 + exponent_string \
06683 + markup['closing_exponent']
06684
06685 else:
06686 return sign + markup['opening_bracket'] \
06687 + nume \
06688 + markup['divide'] \
06689 + deno \
06690 + markup['closing_bracket'] \
06691 + markup['opening_exponent'] \
06692 + exponent_string \
06693 + markup['closing_exponent']
06694
06695 else:
06696 if self.symbol == 'like_a_fraction':
06697 return sign + markup['opening_fraction'] \
06698 + nume \
06699 + markup['fraction_vinculum'] \
06700 + deno \
06701 + markup['closing_fraction']
06702
06703 else:
06704 return sign + nume \
06705 + markup['divide'] \
06706 + deno
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717
06718 class Monomial(Product):
06719
06720
06721
06722
06723
06724
06725
06726
06727
06728
06729
06730
06731
06732
06733
06734
06735
06736
06737
06738
06739
06740
06741
06742
06743
06744
06745
06746 def __init__(self, arg, **options):
06747 self.compact_display = True
06748 self.element = list()
06749 self.info = list()
06750 self.info.append(False)
06751 self.info.append(False)
06752 self.exponent = Value(1)
06753 self.neutral = Item(1)
06754
06755
06756 if arg == __.DEFAULT:
06757 factor1 = Item(1)
06758 factor2 = Item(('+', default.MONOMIAL_LETTER, 0))
06759 self.element.append(factor1)
06760 self.element.append(factor2)
06761
06762
06763 elif type(arg) == Monomial :
06764 self.compact_display = arg.compact_display
06765 self.info = list()
06766 self.info.append(arg.info[0])
06767 self.info.append(arg.info[1])
06768 factor1 = arg.factor[0].deep_copy()
06769 factor2 = Item(arg.factor[1])
06770 self.element.append(factor1)
06771 self.element.append(factor2)
06772 self.exponent = arg.exponent.deep_copy()
06773
06774
06775 elif type(arg) == tuple and len(arg) == 3 and is_.a_sign(arg[0]) \
06776 and (is_.a_number(arg[1]) and is_.an_integer(arg[2])):
06777
06778 factor1 = Item((arg[0], arg[1]))
06779 factor2 = Item(('+', default.MONOMIAL_LETTER, arg[2]))
06780 self.element.append(factor1)
06781 self.element.append(factor2)
06782
06783
06784 elif type(arg) == tuple and len(arg) == 2 \
06785 and (is_.a_number(arg[0]) or (is_.a_calculable(arg[0]) \
06786 and arg[0].is_numeric()) \
06787 and is_.an_integer(arg[1])):
06788
06789 if is_.a_number(arg[0]):
06790 if arg[0] >= 0:
06791 factor1 = Item(('+', arg[0]))
06792 elif arg[0] < 0:
06793 factor1 = Item(('-', -arg[0]))
06794 else:
06795 factor1 = arg[0].deep_copy()
06796
06797 factor2 = Item(('+', default.MONOMIAL_LETTER, arg[1]))
06798 self.element.append(factor1)
06799 self.element.append(factor2)
06800
06801
06802 elif type(arg) == tuple and len(arg) == 3 and arg[0] == __.RANDOMLY \
06803 and is_.a_number(arg[1]) and is_.an_integer(arg[2]):
06804
06805 aux_ratio = 0.5
06806 if 'randomly_plus_signs_ratio' in options \
06807 and is_.a_number(options['randomly_plus_signs_ratio']):
06808
06809 aux_ratio = options['randomly_plus_signs_ratio']
06810 factor1 = Item((randomly.sign(plus_signs_ratio=aux_ratio),
06811 randomly.integer(1, arg[1])))
06812 factor2 = Item(('+',
06813 default.MONOMIAL_LETTER,
06814 randomly.integer(0, arg[2])))
06815 self.element.append(factor1)
06816 self.element.append(factor2)
06817
06818
06819 else:
06820 raise error.UncompatibleType(arg, \
06821 "__.DEFAULT|Monomial|" \
06822 + "(sign, coeff, degree)|" \
06823 + "(number|numeric Exponented, " \
06824 + "integer)|" \
06825 + "(__.RANDOMLY, max_coeff, " \
06826 + "max_degree)")
06827
06828
06829
06830 if self.factor[0].is_null():
06831 self.element[1].exponent = Value(lib.ZERO_POLYNOMIAL_DEGREE)
06832
06833 if self.element[1].exponent == Value(0) \
06834 and isinstance(self.element[0], Item):
06835
06836
06837
06838
06839 self.value_object = Value(self.factor[0].value)
06840
06841
06842
06843
06844
06845
06846
06847
06848
06849
06850 def __str__(self, **options):
06851
06852 expo = ""
06853
06854 if self.exponent != Value(1):
06855 expo = "^{" + str(self.exponent) + "} "
06856
06857 return " <<" + str(self.coeff) \
06858 + "× X ^" + str(self.degree) + ">> " + expo
06859
06860
06861
06862
06863
06864
06865
06866
06867 def is_null(self):
06868 if self.degree == lib.ZERO_POLYNOMIAL_DEGREE \
06869 or self.coeff.is_null():
06870 return True
06871 else:
06872 return False
06873
06874
06875
06876
06877
06878
06879
06880
06881 def is_numeric(self):
06882 if self.is_null():
06883 return True
06884
06885 if self.degree == 0:
06886 return True
06887
06888 return False
06889
06890
06891
06892
06893
06894
06895
06896
06897
06898 def is_positive(self):
06899 return self.element[0].is_positive()
06900
06901
06902
06903
06904
06905
06906
06907
06908
06909
06910 def is_negative(self):
06911 return self.element[0].is_negative()
06912
06913
06914
06915
06916
06917
06918
06919
06920
06921 def get_sign(self):
06922 if self.is_null():
06923 return '+'
06924 else:
06925 return self.factor[0].get_sign()
06926
06927 sign = property(get_sign, doc = "Monomial's sign")
06928
06929
06930
06931
06932
06933
06934
06935
06936
06937 def get_coeff(self):
06938 return self.factor[0]
06939
06940 coeff = property(get_coeff, doc = "Monomial's coefficient")
06941
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951 def get_value(self):
06952 return self.value_object.value
06953
06954 value = property(get_value, doc = "0-degree-Monomial's value")
06955
06956
06957
06958
06959
06960
06961
06962
06963
06964 def get_degree(self):
06965 return self.factor[1].exponent.evaluate()
06966
06967 degree = property(get_degree, doc = "Monomial's degree")
06968
06969
06970
06971
06972
06973
06974
06975
06976
06977
06978 def get_letter(self):
06979 return self.factor[1].value
06980
06981 letter = property(get_letter, doc = "Monomial's letter")
06982
06983
06984
06985
06986
06987
06988
06989
06990 def set_sign(self, arg):
06991 if is_.a_sign(arg):
06992 self.element[0].sign = arg
06993 else:
06994 raise error.UncompatibleType(arg, "sign")
06995
06996
06997
06998
06999
07000
07001
07002
07003 def set_letter(self, letter):
07004 self.element[1].value_object = Value(letter)
07005
07006
07007
07008
07009
07010
07011
07012
07013
07014 def set_degree(self, arg):
07015 if is_.a_natural_integer(arg):
07016 self.factor[1].set_exponent(arg)
07017 else:
07018 raise error.UncompatibleType(arg, "natural integer")
07019
07020
07021
07022
07023
07024
07025
07026 def set_coeff(self, arg):
07027 self.element[0] = Item(arg)
07028
07029
07030
07031
07032
07033
07034
07035
07036
07037
07038
07039
07040
07041
07042
07043
07044
07045
07046 def plus(self, objct):
07047 if isinstance(objct, Monomial) or isinstance(objct, Polynomial):
07048
07049 debug.write("\nMonomial adding to a " \
07050 + "Monomial|Polynomial",
07051 case=debug.monomial_plus)
07052 result = Polynomial([self, objct])
07053
07054 debug.write("\nresult : " + str(result),
07055 case=debug.monomial_plus)
07056 return result
07057 else:
07058 return Sum([self, objct])
07059
07060
07061
07062
07063
07064
07065
07066
07067
07068
07069
07070 class Polynomial(Sum):
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087
07088
07089
07090
07091
07092
07093
07094
07095
07096
07097 def __init__(self, arg):
07098 self.compact_display = True
07099
07100 self.neutral = Item(0)
07101 self.element = list()
07102 self.info = list()
07103
07104
07105
07106
07107
07108
07109
07110
07111
07112
07113 self.exponent = Value(1)
07114
07115 self.force_inner_brackets_display = False
07116
07117 if isinstance(arg, Sum):
07118 self.force_inner_brackets_display = \
07119 arg.force_inner_brackets_display
07120
07121
07122 if arg == __.DEFAULT:
07123 self.element.append(Monomial(__.DEFAULT))
07124 self.display_complete_writing.append(False)
07125
07126
07127 elif ((type(arg) == list) and len(arg) >= 1) or isinstance(arg, Sum):
07128 for i in xrange(len(arg)):
07129
07130 debug.write("\nCopying : " + str(arg[i]),
07131 case=debug.init_in_polynomial)
07132 if isinstance(arg[i], Monomial):
07133 self.element.append(arg[i].deep_copy())
07134 self.display_complete_writing.append(False)
07135 elif isinstance(arg[i], Polynomial):
07136 for j in xrange(len(arg[i])):
07137 self.element.append(arg[i].term[j].deep_copy())
07138 self.display_complete_writing.append(
07139 arg[i].display_complete_writing[j])
07140 else:
07141 raise error.UncompatibleType(arg[i],
07142 " but in this list or Sum are" \
07143 + " only Monomials & " \
07144 + "Polynomials welcome. " \
07145 "Given object : " \
07146 + str(arg[i]))
07147
07148
07149 elif type(arg) == tuple and len(arg) == 4 and arg[0] == __.RANDOMLY:
07150
07151 length = 0
07152
07153
07154 if type(arg[3]) == tuple and len(arg[3]) == 2 \
07155 and is_.an_integer(arg[3][1]) and arg[3][0] == __.RANDOMLY:
07156
07157 if arg[3][1] < 1:
07158 raise error.OutOfRangeArgument(arg[3][1],
07159 "This integer should be\
07160 greater or equal to 1.")
07161 else:
07162 length = randomly.integer(1, arg[3][1])
07163
07164
07165 elif is_.an_integer(arg[3]) and arg[3] >= 1:
07166 length = arg[3]
07167 else:
07168 raise error.UncompatibleType(arg,
07169 "(__.RANDOMLY,\
07170 max_coeff,\
07171 max_degree,\
07172 length|(__.RANDOMLY, max_length))")
07173
07174
07175
07176
07177
07178
07179
07180
07181
07182 max_nb_constant_terms = max([
07183 int(CONSTANT_TERMS_MAXIMUM_RATIO
07184 * length),
07185 CONSTANT_TERMS_MINIMUM_NUMBER
07186 ])
07187
07188 current_nb_constant_terms = 0
07189 deg_to_put_in_again = None
07190 the_last_drawing_has_to_be_put_in_again = False
07191 degrees_list = [i for i in xrange(arg[2] + 1)]
07192
07193 for i in xrange(length):
07194
07195 coeff = randomly.integer(1, arg[1])
07196
07197
07198 deg = randomly.pop(degrees_list)
07199
07200 if the_last_drawing_has_to_be_put_in_again:
07201 degrees_list.append(deg_to_put_in_again)
07202
07203 the_last_drawing_has_to_be_put_in_again = True
07204
07205 deg_to_put_in_again = deg
07206
07207 if deg == 0:
07208 current_nb_constant_terms += 1
07209 if current_nb_constant_terms == max_nb_constant_terms:
07210 degrees_list = [i + 1 for i in xrange(arg[2])]
07211 the_last_drawing_has_to_be_put_in_again = False
07212
07213
07214 self.append(Monomial((randomly.sign(), coeff, deg)))
07215
07216
07217 debug.write("\n[init_in_polynomial]\n" \
07218 + "Randomly Created Polynomial is : \n" \
07219 + str(self) + "\n" \
07220 + str(self.display_complete_writing)\
07221 + "\n",
07222 case=debug.init_in_polynomial)
07223
07224
07225
07226 else:
07227 raise error.UncompatibleType(arg,
07228 "__.DEFAULT |\
07229 [Monomial|Polynomial] |\
07230 Sum(Monomial|Polynomial) |\
07231 (__.RANDOMLY,\
07232 max_coeff,\
07233 max_degree,\
07234 [length|(__.RANDOMLY, max_length)])"
07235 )
07236
07237
07238
07239
07240
07241
07242
07243
07244
07245
07246 def __str__(self, **options):
07247 resulting_string = " [["
07248 for i in xrange(len(self)):
07249 resulting_string += str(self.term[i])
07250 if i < len(self) - 1:
07251 resulting_string += ", "
07252
07253
07254 resulting_string += "]] "
07255 return resulting_string
07256
07257
07258
07259
07260
07261
07262
07263
07264
07265 def get_max_degree(self):
07266 d = lib.ZERO_POLYNOMIAL_DEGREE
07267
07268 for i in xrange(len(self)):
07269 if self.term[i].degree > d:
07270 d = self.term[i].degree
07271
07272 return d
07273
07274
07275
07276
07277
07278
07279
07280
07281
07282 def get_degree(self):
07283
07284 for i in xrange(self.get_max_degree(), -1, -1):
07285 coefficients_sum = 0
07286
07287 for j in xrange(len(self)):
07288
07289 if self.term[j].degree == i:
07290 if self.term[j].sign == '+':
07291 coefficients_sum += self.term[j].coeff
07292 else:
07293 coefficients_sum -= self.term[j].coeff
07294
07295
07296
07297
07298 if coefficients_sum != 0:
07299
07300
07301 return i
07302
07303 return lib.ZERO_POLYNOMIAL_DEGREE
07304
07305 degree = property(get_degree, doc = 'Real degree of the Polynomial')
07306
07307
07308
07309
07310
07311
07312
07313
07314
07315
07316
07317
07318
07319
07320
07321
07322
07323
07324
07325 def plus(self, objct):
07326 if isinstance(objct, Monomial) or isinstance(objct, Polynomial):
07327 return Polynomial([self, objct])
07328 else:
07329 return Sum([self, objct])
07330
07331
07332
07333
07334
07335
07336
07337
07338
07339
07340
07341 class Fraction(Quotient):
07342
07343
07344
07345
07346
07347
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358
07359
07360
07361 def __init__(self, arg, **options):
07362
07363 self.exponent = Value(1)
07364
07365 self.numerator = Product([Item(1)])
07366 self.denominator = Product([Item(2)])
07367 self.sign = '+'
07368 self.status = "nothing"
07369 self.symbol = 'like_a_fraction'
07370 self.same_deno_reduction_in_progress = False
07371
07372 arg_sign = 'default'
07373 arg_nume = 'default'
07374 arg_deno = 'default'
07375
07376 if type(arg) == tuple:
07377 if len(arg) >= 3 and arg[0] != __.RANDOMLY:
07378 arg_sign = arg[0]
07379 arg_nume = arg[1]
07380 arg_deno = arg[2]
07381 elif len(arg) == 6 and arg[0] == __.RANDOMLY:
07382 arg_sign = arg[1]
07383 arg_nume = arg[3]
07384 arg_deno = arg[5]
07385 elif len(arg) == 2:
07386 arg_nume = arg[0]
07387 arg_deno = arg[1]
07388
07389
07390
07391
07392 if type(arg) == tuple \
07393 and len(arg) >= 2 \
07394 and arg[0] != __.RANDOMLY \
07395 and \
07396 ((isinstance(arg_nume, Exponented) and arg_nume.is_numeric()) \
07397 or \
07398 is_.a_number(arg_nume)) \
07399 and \
07400 ((isinstance(arg_deno, Exponented) and arg_deno.is_numeric()) \
07401 or \
07402 is_.a_number(arg_deno)):
07403
07404
07405 if is_.a_number(arg_nume):
07406 self.numerator = Product([Item(arg_nume)])
07407 elif not isinstance(arg_nume, Product):
07408 self.numerator = Product(arg_nume.deep_copy())
07409 else:
07410 self.numerator = arg_nume.deep_copy()
07411
07412 if is_.a_number(arg_deno):
07413 self.denominator = Product([Item(arg_deno)])
07414 elif not isinstance(arg_deno, Product):
07415 self.denominator = Product(arg_deno.deep_copy())
07416 else:
07417 self.denominator = arg_deno.deep_copy()
07418
07419 if len(arg) == 2 \
07420 and 'copy_other_fields_from' in options \
07421 and isinstance(options['copy_other_fields_from'], Fraction):
07422
07423 self.exponent = options['copy_other_fields_from'].exponent.\
07424 deep_copy()
07425 self.sign = options['copy_other_fields_from'].sign
07426 self.status = options['copy_other_fields_from'].status
07427 self.symbol = options['copy_other_fields_from'].symbol
07428 self.same_deno_reduction_in_progress = \
07429 options['copy_other_fields_from'].same_deno_reduction_in_progress
07430
07431 if len(arg) >= 3 and is_.a_sign(arg_sign):
07432 self.sign = arg[0]
07433
07434 if len(arg) >= 4:
07435 self.exponent = arg[3].deep_copy()
07436
07437
07438
07439 elif type(arg) == tuple \
07440 and len(arg) == 6 \
07441 and arg[0] == __.RANDOMLY \
07442 and (is_.a_sign(arg_sign) or arg_sign == __.RANDOMLY) \
07443 and is_.an_integer(arg_deno) and arg_deno >= 2 \
07444 and is_.an_integer(arg_nume) and arg_nume >= 1 \
07445 and (is_.a_sign(arg[2]) or arg[2] == __.RANDOMLY) \
07446 and (is_.a_sign(arg[4]) or arg[4] == __.RANDOMLY):
07447
07448 numbers_box_nume = [j+1 for j in xrange(arg_nume)]
07449 numbers_box_deno = [j+1 for j in xrange(arg_deno)]
07450
07451 nume = randomly.pop(numbers_box_nume)
07452 nume_sign = '+'
07453 if arg[2] == __.RANDOMLY:
07454 nume_sign = randomly.sign(plus_signs_ratio=0.75)
07455 if nume_sign == '-':
07456 nume_sign = -1
07457 else:
07458 nume_sign = 1
07459 else:
07460 nume_sign = arg[2]
07461
07462 if numbers_box_deno[0] == 1:
07463 numbers_box_deno.pop(0)
07464 deno = randomly.pop(numbers_box_deno)
07465 deno_sign = '+'
07466 if arg[4] == __.RANDOMLY:
07467 deno_sign = randomly.sign(plus_signs_ratio=0.75)
07468 if deno_sign == '-':
07469 deno_sign = -1
07470 else:
07471 deno_sign = 1
07472 else:
07473 deno_sign = arg[4]
07474
07475 self.numerator = Product([nume_sign, nume]).reduce_()
07476 self.denominator = Product([deno_sign, deno]).reduce_()
07477
07478 if arg_sign == __.RANDOMLY:
07479 self.sign = randomly.sign(plus_signs_ratio=0.75)
07480 else:
07481 self.sign = arg_sign
07482
07483
07484
07485
07486
07487 elif isinstance(arg, Fraction):
07488 self.exponent = arg.exponent.deep_copy()
07489 self.numerator = arg.numerator.deep_copy()
07490 self.denominator = arg.denominator.deep_copy()
07491 self.sign = arg.sign
07492 self.status = arg.status
07493 self.same_deno_reduction_in_progress = \
07494 arg.same_deno_reduction_in_progress
07495
07496
07497 elif arg == "default":
07498
07499 pass
07500
07501
07502 elif isinstance(arg, Monomial) and arg.is_numeric()\
07503 and isinstance(arg.factor[0], Fraction):
07504
07505 self.exponent = Value(1)
07506 self.numerator = arg.factor[0].numerator.deep_copy()
07507 self.denominator = arg.factor[0].denominator.deep_copy()
07508 self.sign = arg.factor[0].sign
07509 self.status = arg.factor[0].status
07510 self.same_deno_reduction_in_progress = \
07511 arg.factor[0].same_deno_reduction_in_progress
07512
07513
07514
07515 else:
07516 raise error.UncompatibleType(arg, "(sign, numerator, denominator)")
07517
07518
07519 temp_objects = [self.numerator, self.denominator]
07520
07521 for i in xrange(len(temp_objects)):
07522 if len(temp_objects[i]) == 1:
07523 if isinstance(temp_objects[i].factor[0], Sum) \
07524 and len(temp_objects[i].factor[0]) == 1:
07525
07526 temp_objects[i] = temp_objects[i].factor[0].term[0]
07527
07528 elif isinstance(temp_objects[i].factor[0], Product) \
07529 and len(temp_objects[i].factor[0]) == 1:
07530
07531 temp_objects[i] = temp_objects[i].factor[0].factor[0]
07532
07533 if not isinstance(temp_objects[i], Product):
07534 temp_objects[i] = Product([temp_objects[i]])
07535
07536 self.numerator = temp_objects[0]
07537 self.denominator = temp_objects[1]
07538
07539
07540
07541
07542
07543
07544
07545
07546 def __cmp__(self, obj):
07547 if not isinstance(obj, Fraction):
07548 return -1
07549
07550 if self.sign == obj.sign \
07551 and self.numerator == obj.numerator \
07552 and self.denominator == obj.denominator \
07553 and self.exponent == obj.exponent:
07554
07555 return 0
07556 else:
07557
07558
07559 return -1
07560
07561
07562
07563
07564
07565
07566
07567
07568
07569
07570
07571
07572
07573 def is_reducible(self):
07574 if not self.is_numeric():
07575 return False
07576
07577 if self.numerator.evaluate() == 0:
07578 return True
07579
07580 if not isinstance(self.numerator, Product):
07581 if isinstance(self.numerator, Item):
07582 self.numerator = Product(self.numerator)
07583 else:
07584 return False
07585
07586 if not isinstance(self.denominator, Product):
07587 if isinstance(self.denominator, Item):
07588 self.denominator = Product(self.denominator)
07589 else:
07590 return False
07591
07592
07593 for i in xrange(len(self.numerator)):
07594 if not (isinstance(self.numerator.factor[i], Item) \
07595 and is_.an_integer(self.numerator.factor[i].value) \
07596 and self.numerator.factor[i].exponent == Value(1) \
07597 ):
07598 return False
07599
07600 for i in xrange(len(self.denominator)):
07601 if not (isinstance(self.denominator.factor[i], Item) \
07602 and is_.an_integer(self.denominator.factor[i].value) \
07603 and self.denominator.factor[i].exponent == Value(1) \
07604 ):
07605 return False
07606
07607 if lib.gcd(self.numerator.evaluate(), self.denominator.evaluate()) > 1:
07608 return True
07609 else:
07610 return False
07611
07612
07613
07614
07615
07616
07617
07618
07619 def is_equivalent_to_an_irreducible_Fraction(self):
07620 return self.is_reducible()
07621
07622
07623
07624
07625
07626
07627
07628
07629
07630
07631 def get_simplification_in_progress(self):
07632 for i in xrange(len(self.numerator)):
07633 if isinstance(self.numerator.factor[i], Item):
07634 if self.numerator.factor[i].is_out_striked:
07635 return True
07636
07637 for i in xrange(len(self.denominator)):
07638 if isinstance(self.denominator.factor[i], Item):
07639 if self.denominator.factor[i].is_out_striked:
07640 return True
07641
07642 return False
07643
07644
07645 simplification_in_progress = property(get_simplification_in_progress,
07646 doc = "Fraction's simplification_" \
07647 + "in_progressstatus")
07648
07649
07650
07651
07652
07653
07654
07655
07656
07657
07658 def set_down_numerator_s_minus_sign(self):
07659 if len(self.numerator) == 1 \
07660 and self.numerator.calculate_next_step() == None \
07661 and len(self.denominator) == 1 \
07662 and self.denominator.calculate_next_step() == None \
07663 and self.denominator.get_sign() == '+' \
07664 and self.numerator.get_sign() == '-' \
07665 and self.get_sign() == '+':
07666
07667 self.set_sign(lib.sign_of_product([\
07668 self.get_sign(),
07669 self.numerator.get_sign()
07670 ]))
07671 self.numerator.set_sign('+')
07672
07673
07674
07675
07676
07677
07678
07679
07680
07681
07682
07683 def simplification_line(self):
07684 if not self.is_reducible():
07685 return self
07686
07687 elif self.numerator.evaluate() == 0:
07688 return Item(0)
07689
07690 else:
07691
07692
07693
07694
07695
07696
07697
07698 new_numerator = Product([Item(1) \
07699 for i in xrange(len(self.numerator))])
07700 new_denominator = Product([Item(1) \
07701 for i in xrange(len(self.denominator))])
07702
07703 this_numerators_factor_has_been_processed = [False \
07704 for i in xrange(len(self.numerator))]
07705 this_denominators_factor_has_been_processed = [False \
07706 for i in xrange(len(self.denominator))]
07707
07708
07709
07710
07711
07712
07713
07714
07715
07716
07717
07718
07719
07720
07721
07722
07723
07724
07725
07726
07727
07728
07729
07730 for i in xrange(len(self.numerator)):
07731 for j in xrange(len(self.denominator)):
07732 if self.numerator.factor[i].value \
07733 == self.denominator.factor[j].value \
07734 and not (this_numerators_factor_has_been_processed[i] \
07735 or this_denominators_factor_has_been_processed[j]):
07736
07737 new_numerator.element[i] = self.numerator.factor[i].\
07738 deep_copy()
07739 new_numerator.element[i].set_is_out_striked(True)
07740 debug.write("\n[0]Striked out : " \
07741 + str(new_numerator.factor[i]),
07742 case=debug.striking_out_in_simplification_line)
07743
07744 new_denominator.element[j] = self.denominator\
07745 .factor[j]\
07746 .deep_copy()
07747 new_denominator.factor[j].set_is_out_striked(True)
07748 debug.write("\n[1]Striked out : " \
07749 + str(new_denominator.factor[j]),
07750 case=debug.striking_out_in_simplification_line)
07751
07752 this_numerators_factor_has_been_processed[i] = True
07753 this_denominators_factor_has_been_processed[j] = True
07754
07755
07756
07757 for i in xrange(len(self.numerator)):
07758 for j in xrange(len(self.denominator)):
07759 if not this_denominators_factor_has_been_processed[j] \
07760 and not this_numerators_factor_has_been_processed[i]:
07761
07762 gcd = lib.pupil_gcd(self.numerator.factor[i].value, \
07763 self.denominator.factor[j].value)
07764 if gcd != 1:
07765 if gcd == self.numerator.factor[i].value:
07766 new_numerator.element[i] = \
07767 self.numerator.factor[i]\
07768 .deep_copy()
07769
07770 new_numerator.factor[i].set_is_out_striked( \
07771 True)
07772
07773 debug.write("\n[2A]Striked out : " \
07774 + str(new_numerator.factor[i]),
07775 case=debug.striking_out_in_simplification_line)
07776
07777 this_numerators_factor_has_been_processed[i] =\
07778 True
07779
07780 factor1 = gcd
07781 factor2 = self.denominator.factor[j].value/gcd
07782
07783 if self.denominator.factor[j].sign == '-':
07784 factor1 *= -1
07785
07786 item1 = Item(factor1)
07787 item1.set_is_out_striked(True)
07788 debug.write("\n[2B]Striked out : " \
07789 + str(item1),
07790 case=debug.striking_out_in_simplification_line)
07791
07792
07793 item2 = Item(factor2)
07794
07795 new_denominator.factor[j] = \
07796 Product([item1, item2])
07797
07798 this_denominators_factor_has_been_processed[j]\
07799 = True
07800
07801 elif gcd == self.denominator.factor[j].value:
07802 new_denominator.factor[j] = \
07803 self.denominator.factor[j]\
07804 .deep_copy()
07805
07806 new_denominator.factor[j].set_is_out_striked( \
07807 True)
07808
07809 this_denominators_factor_has_been_processed[j]\
07810 = True
07811
07812 factor1 = gcd
07813 factor2 = self.numerator.factor[i].value / gcd
07814
07815 if self.numerator.factor[i].sign == '-':
07816 factor1 *= -1
07817
07818 item1 = Item(factor1)
07819 item1.set_is_out_striked(True)
07820 debug.write("\n[3]Striked out : " \
07821 + str(item1),
07822 case=debug.striking_out_in_simplification_line)
07823
07824 item2 = Item(factor2)
07825
07826 new_numerator.factor[i] = Product([item1,
07827 item2])
07828
07829 this_numerators_factor_has_been_processed[i] =\
07830 True
07831
07832 else:
07833 factor1 = gcd
07834 factor2 = self.numerator.factor[i].value / gcd
07835
07836 if self.numerator.factor[i].sign == '-':
07837 factor1 *= -1
07838
07839 item1 = Item(factor1)
07840 item1.set_is_out_striked(True)
07841 debug.write("\n[4]Striked out : " \
07842 + str(item1),
07843 case=debug.striking_out_in_simplification_line)
07844
07845 item2 = Item(factor2)
07846
07847 new_numerator.factor[i] = Product([item1,
07848 item2])
07849
07850 this_numerators_factor_has_been_processed[i] =\
07851 True
07852
07853 factor1 = gcd
07854 factor2 = self.denominator.factor[j].value/gcd
07855 if self.denominator.factor[j].sign == '-':
07856 factor1 *= -1
07857
07858 item1 = Item(factor1)
07859 item1.set_is_out_striked(True)
07860 debug.write("\n[5]Striked out : " \
07861 + str(item1),
07862 case=debug.striking_out_in_simplification_line)
07863 item2 = Item(factor2)
07864
07865 new_denominator.factor[j] = Product([item1,
07866 item2])
07867
07868 this_denominators_factor_has_been_processed[j]\
07869 = True
07870
07871 for i in xrange(len(new_numerator)):
07872 if not this_numerators_factor_has_been_processed[i]:
07873 new_numerator.factor[i] = self.numerator.factor[i]
07874
07875 for j in xrange(len(new_denominator)):
07876 if not this_denominators_factor_has_been_processed[j]:
07877 new_denominator.factor[j] = self.denominator.factor[j]
07878
07879
07880
07881
07882
07883
07884
07885
07886
07887
07888
07889
07890
07891 final_numerator = []
07892 final_denominator = []
07893 for i in xrange(len(new_numerator)):
07894 if isinstance(new_numerator.factor[i], Item):
07895 final_numerator.append(new_numerator.factor[i].deep_copy())
07896 elif isinstance(new_numerator.factor[i], Product):
07897 for j in xrange(len(new_numerator.factor[i])):
07898 final_numerator.append(new_numerator.factor[i]\
07899 .factor[j]\
07900 .deep_copy())
07901
07902 for i in xrange(len(new_denominator)):
07903 if isinstance(new_denominator.factor[i], Item):
07904 final_denominator.append(new_denominator.factor[i]\
07905 .deep_copy())
07906 elif isinstance(new_denominator.factor[i], Product):
07907 for j in xrange(len(new_denominator.factor[i])):
07908 final_denominator.append( \
07909 new_denominator.factor[i]\
07910 .factor[j]\
07911 .deep_copy())
07912
07913
07914 for i in xrange(len(final_numerator)):
07915 if not final_numerator[i].is_out_striked:
07916 for j in xrange(len(final_denominator)):
07917 if not final_denominator[j].is_out_striked:
07918 if final_numerator[i].value == \
07919 final_denominator[j].value:
07920
07921 final_numerator[i].set_is_out_striked(True)
07922 debug.write("\n[6]Striked out : " \
07923 + str(final_numerator[i]),
07924 case=debug.striking_out_in_simplification_line)
07925 final_denominator[j].set_is_out_striked(True)
07926 debug.write("\n[7]Striked out : " \
07927 + str(final_numerator[i]),
07928 case=debug.striking_out_in_simplification_line)
07929
07930
07931
07932
07933
07934
07935
07936 position_of_the_last_minus_sign = None
07937
07938 if self.sign == '-':
07939 position_of_the_last_minus_sign = ('f', 0)
07940
07941 if len(final_numerator) >= 2 or len(final_denominator) >= 2:
07942 debug.write("\n[Simplification line entering minus " \
07943 + "signs simplification]",
07944 case=debug.simplification_line_minus_signs)
07945 for I in [final_numerator, final_denominator]:
07946 for i in xrange(len(I)):
07947 if I[i].get_sign() == '-':
07948 if position_of_the_last_minus_sign == None:
07949 if I == final_numerator:
07950 position_of_the_last_minus_sign = ('n', i)
07951 else:
07952 position_of_the_last_minus_sign = ('d', i)
07953 elif position_of_the_last_minus_sign[0] == 'f':
07954 self.set_sign('+')
07955 I[i].set_sign('+')
07956 I[i].force_display_sign_once = True
07957 position_of_the_last_minus_sign = None
07958 debug.write("\n[Simplification line : minus " \
07959 + "signs simplification]" \
07960 + " [A] 2 signs set to '+' ",
07961 case=debug.simplification_line_minus_signs)
07962 elif position_of_the_last_minus_sign[0] == 'n':
07963 final_numerator[ \
07964 position_of_the_last_minus_sign[1]].\
07965 set_sign('+')
07966 final_numerator[ \
07967 position_of_the_last_minus_sign[1]].\
07968 force_display_sign_once = True
07969 I[i].set_sign('+')
07970 I[i].force_display_sign_once = True
07971 position_of_the_last_minus_sign = None
07972 debug.write("\n[Simplification line : minus " \
07973 + "signs simplification]" \
07974 + " [B] 2 signs set to '+' ",
07975 case=debug.simplification_line_minus_signs)
07976 elif position_of_the_last_minus_sign[0] == 'd':
07977 final_denominator[ \
07978 position_of_the_last_minus_sign[1]].\
07979 set_sign('+')
07980 final_denominator[ \
07981 position_of_the_last_minus_sign[1]].\
07982 force_display_sign_once = True
07983 I[i].set_sign('+')
07984 I[i].force_display_sign_once = True
07985 position_of_the_last_minus_sign = None
07986 debug.write("\n[Simplification line : minus " \
07987 + "signs simplification]" \
07988 + " [C] 2 signs set to '+' ",
07989 case=debug.simplification_line_minus_signs)
07990
07991 answer = Fraction((self.sign,
07992 Product(final_numerator),
07993 Product(final_denominator)
07994 ))
07995
07996 if debug.ENABLED and debug.simplification_line_minus_signs:
07997
07998 for i in xrange(len(answer.numerator)):
07999 if answer.numerator[i].force_display_sign_once:
08000 debug.write("\n[Simplification line : found a plus " \
08001 + "sign forced to display in nume]",
08002 case=debug.simplification_line_minus_signs)
08003
08004 for i in xrange(len(answer.denominator)):
08005 if answer.denominator[i].force_display_sign_once:
08006 debug.write("\n[Simplification line : found a plus " \
08007 + "sign forced to display in deno]",
08008 case=debug.simplification_line_minus_signs)
08009
08010
08011 answer.status = "simplification_in_progress"
08012
08013 return answer
08014
08015
08016
08017
08018
08019
08020
08021
08022 def replace_striked_out(self):
08023
08024 debug.write("\nEntering replace_striked_out\n"\
08025 + "with the Fraction :\n" \
08026 + str(self),
08027 case=debug.replace_striked_out)
08028
08029 result = Fraction(self)
08030
08031
08032
08033 for i in xrange(len(result.numerator)):
08034 if result.numerator.factor[i].is_out_striked:
08035 result.numerator.factor[i].value_object = Value(1)
08036 result.numerator.factor[i].is_out_striked = False
08037
08038
08039 for j in xrange(len(result.denominator)):
08040 if result.denominator.factor[j].is_out_striked:
08041 result.denominator.factor[j].value_object = Value(1)
08042 result.denominator.factor[j].is_out_striked = False
08043
08044 return result
08045
08046
08047
08048
08049
08050
08051
08052
08053
08054 def simplified(self):
08055 debug.write("\nEntering simplified\n"\
08056 + "with Fraction :\n" \
08057 + str(self),
08058 case=debug.simplified)
08059
08060 aux_fraction = None
08061
08062 if self.simplification_in_progress:
08063 aux_fraction = Fraction(self)
08064 else:
08065 aux_fraction = Fraction(self.simplification_line())
08066
08067
08068
08069 final_sign = lib.sign_of_product([Item((aux_fraction.sign, 1, 1)),
08070 aux_fraction.numerator,
08071 aux_fraction.denominator])
08072
08073 aux_fraction = aux_fraction.replace_striked_out()
08074
08075 final_numerator = Product([Item(int( \
08076 math.fabs(aux_fraction.numerator.evaluate())))])
08077
08078 final_denominator = Product([Item(int( \
08079 math.fabs(aux_fraction.denominator.evaluate())))])
08080
08081
08082
08083
08084 if final_denominator.is_equivalent_to_a_single_1():
08085 if final_sign == '-':
08086 return Item((Item(-1).times(final_numerator)).evaluate())
08087 else:
08088 return final_numerator
08089 else:
08090 return Fraction((final_sign, final_numerator, final_denominator))
08091
08092
08093
08094
08095
08096
08097
08098
08099
08100
08101 def __str__(self, **options):
08102 return "F# " + \
08103 str(self.sign) + \
08104 " ( " + \
08105 str(self.numerator) + \
08106 " / " + \
08107 str(self.denominator) + \
08108 " ) ^ { " + \
08109 str(self.exponent) + \
08110 " } #F"
08111
08112
08113
08114
08115
08116
08117
08118
08119
08120
08121
08122 def calculate_next_step(self, **options):
08123
08124 debug.write("\nEntering calculate_next_step_fraction\n"\
08125 + "with Fraction :\n" \
08126 + str(self),
08127 case=debug.calculate_next_step_fraction)
08128
08129
08130
08131 if 'decimal_result' in options \
08132 and self.numerator.calculate_next_step() == None \
08133 and self.denominator.calculate_next_step() == None:
08134
08135 if self.sign == '+':
08136 result_sign = 1
08137 else:
08138 result_sign = -1
08139 result = Item(Value(result_sign \
08140 * self.numerator.evaluate() \
08141 / self.denominator.evaluate())\
08142 .round(options['decimal_result'])
08143 )
08144
08145 debug.write("\n[calculate_next_step_fraction] " \
08146 + "Decimal calculation has been done. Result : \n"\
08147 + str(result) + " which has_been_rounded : " \
08148 + str(result.contains_a_rounded_number()) \
08149 + "\n",
08150 case=debug.calculate_next_step_fraction)
08151 return result
08152
08153 temp_next_nume = self.numerator.calculate_next_step(**options)
08154 temp_next_deno = self.denominator.calculate_next_step(**options)
08155
08156
08157
08158 if self.simplification_in_progress:
08159 self_simplified = Fraction(self).simplified()
08160 if isinstance(self_simplified, Item) \
08161 or (isinstance(self_simplified, Fraction) \
08162 and not self_simplified.is_reducible()):
08163
08164
08165 debug.write("\n[calculate_next_step_fraction] "\
08166 + "1st CASE-a\n",
08167 case=debug.calculate_next_step_fraction)
08168 return self_simplified
08169 else:
08170
08171 debug.write("\n[calculate_next_step_fraction] "\
08172 + "1st CASE-b\n",
08173 case=debug.calculate_next_step_fraction)
08174 aux_fraction = Fraction(self)
08175 aux_fraction = aux_fraction.replace_striked_out()
08176 aux_fraction.numerator = \
08177 aux_fraction.numerator.throw_away_the_neutrals()
08178 aux_fraction.denominator = \
08179 aux_fraction.denominator.throw_away_the_neutrals()
08180 return aux_fraction.simplification_line()
08181
08182
08183 elif self.same_deno_reduction_in_progress:
08184
08185 debug.write("\n[calculate_next_step_fraction] "\
08186 + "2d CASE\n",
08187 case=debug.calculate_next_step_fraction)
08188 new_nume = self.numerator
08189 new_deno = self.denominator
08190
08191 if temp_next_nume != None:
08192 new_nume = temp_next_nume
08193 if temp_next_deno != None:
08194 new_deno = temp_next_deno
08195
08196 resulting_fraction = Fraction((new_nume, new_deno),
08197 copy_other_fields_from=self)
08198
08199 if temp_next_deno != None or temp_next_nume != None:
08200 return resulting_fraction
08201 else:
08202 return None
08203
08204
08205 elif self.is_reducible():
08206
08207 debug.write("\n[calculate_next_step_fraction] "\
08208 + "3d CASE\n",
08209 case=debug.calculate_next_step_fraction)
08210 return self.simplification_line()
08211
08212
08213
08214
08215 elif self.denominator.is_equivalent_to_a_single_1():
08216
08217 debug.write("\n[calculate_next_step_fraction] "\
08218 + "4th CASE\n",
08219 case=debug.calculate_next_step_fraction)
08220 if self.sign == '-':
08221
08222 return Item((Item(-1).times(self.numerator)).evaluate())
08223 else:
08224 return self.numerator
08225
08226
08227 elif temp_next_nume != None or temp_next_deno != None:
08228
08229 debug.write("\n[calculate_next_step_fraction] "\
08230 + "6th CASE\n",
08231 case=debug.calculate_next_step_fraction)
08232 new_nume = self.numerator
08233 new_deno = self.denominator
08234
08235 if temp_next_nume != None:
08236 new_nume = temp_next_nume
08237 if temp_next_deno != None:
08238 new_deno = temp_next_deno
08239
08240 resulting_fraction = Fraction((new_nume, new_deno),
08241 copy_other_fields_from=self)
08242
08243 resulting_fraction.set_down_numerator_s_minus_sign()
08244
08245 return resulting_fraction
08246
08247
08248 elif (len(self.numerator) == 1 \
08249 and self.numerator.factor[0].get_sign() == '-') \
08250 or (len(self.denominator) == 1 \
08251 and self.denominator.factor[0].get_sign() == '-'):
08252
08253 self.set_sign(lib.sign_of_product([self.get_sign(),
08254 self.numerator.get_sign(),
08255 self.denominator.get_sign()]))
08256
08257 self.numerator.factor[0].set_sign('+')
08258 self.denominator.factor[0].set_sign('+')
08259
08260 return self
08261
08262
08263
08264
08265
08266
08267 else:
08268
08269 debug.write("\n[calculate_next_step_fraction] "\
08270 + "7th CASE\n",
08271 case=debug.calculate_next_step_fraction)
08272 return None
08273
08274
08275
08276
08277
08278
08279
08280
08281 def expand_and_reduce_next_step(self, **options):
08282 return self.calculate_next_step(**options)
08283
08284
08285
08286
08287
08288
08289
08290
08291
08292
08293
08294 class Expandable(Product):
08295
08296
08297
08298
08299
08300
08301
08302
08303
08304
08305
08306
08307
08308
08309
08310
08311
08312
08313
08314
08315 def __init__(self, arg, **options):
08316 if not ((isinstance(arg, tuple) and len(arg) == 2) \
08317 or isinstance(arg, Expandable)):
08318
08319 raise error.UncompatibleType(arg,
08320 "That should be a tuple of two" \
08321 + " elements")
08322
08323 max_coeff = 12
08324
08325 if 'max_coeff' in options and type(options['max_coeff']) == int:
08326 max_coeff = options['max_coeff']
08327
08328
08329 self.element = list()
08330
08331 self.compact_display = True
08332 self.info = [False, False]
08333
08334 self.neutral = Item(1)
08335
08336 self.symbol = '×'
08337 self.str_openmark = "<XPD:"
08338 self.str_closemark = ":XPD>"
08339
08340
08341
08342 self.exponent = Value(1)
08343
08344 sum1 = None
08345 sum2 = None
08346
08347
08348
08349 if isinstance(arg, Expandable):
08350 self.compact_display = arg.compact_display
08351 self.element = []
08352 for i in xrange(len(arg.element)):
08353 self.element.append(arg.element[i].deep_copy())
08354 for i in xrange(len(arg.info)):
08355 self.info.append(arg.info[i])
08356
08357
08358
08359
08360 else:
08361 if isinstance(arg[0], Exponented) \
08362 and isinstance(arg[1], Exponented):
08363
08364 if not isinstance(arg[0], Sum):
08365 sum1 = Sum([arg[0].deep_copy()])
08366 else:
08367 sum1 = arg[0].deep_copy()
08368 if not isinstance(arg[1], Sum):
08369 sum2 = Sum([arg[1].deep_copy()])
08370 else:
08371 sum2 = arg[1].deep_copy()
08372
08373
08374
08375 elif arg[0] == __.RANDOMLY:
08376 if arg[1] == 'monom0_polyn1':
08377 sum1 = Sum(Monomial((__.RANDOMLY, max_coeff, 0)))
08378
08379 if sum1.element[0].factor[0].value == 1:
08380 sum1.element[0].factor[0].value_object = Value(\
08381 randomly.integer(2,
08382 max_coeff))
08383
08384 sum2 = Polynomial((__.RANDOMLY, max_coeff, 1, 2))
08385
08386 elif arg[1] == 'monom1_polyn1':
08387 sum1 = Sum(Monomial((__.RANDOMLY, max_coeff, 1)))
08388 sum1.element[0].set_degree(1)
08389 sum2 = Polynomial((__.RANDOMLY, max_coeff, 1, 2))
08390
08391 elif arg[1] == 'polyn1_polyn1':
08392 sum1 = Polynomial((__.RANDOMLY, max_coeff, 1, 2))
08393 sum2 = Polynomial((__.RANDOMLY, max_coeff, 1, 2))
08394
08395 elif arg[1] == 'minus_polyn1_polyn1':
08396 sum1 = Sum(Monomial(('-', 1, 0)))
08397 sum2 = Sum(Expandable((__.RANDOMLY, 'polyn1_polyn1')))
08398
08399 else:
08400 raise error.UncompatibleType(arg[1],
08401 'monom0_polyn1|monom1_polyn1'\
08402 + '|polyn1_polyn1' \
08403 + 'minus_polyn1_polyn1')
08404
08405 else:
08406 raise error.UncompatibleType(arg,
08407 "(Exponented, Exponented)|" \
08408 + "(__.RANDOMLY, <type>)")
08409
08410 if 'reversed' in options \
08411 or ('randomly_reversed' in options \
08412 and is_.a_number(options['randomly_reversed']) \
08413 and randomly.decimal_0_1() <= options['randomly_reversed']):
08414
08415 self.element.append(sum2)
08416 self.element.append(sum1)
08417 else:
08418 self.element.append(sum1)
08419 self.element.append(sum2)
08420
08421
08422
08423 if len(self.factor[0]) == 1 \
08424 and self.factor[0].element[0].is_equivalent_to_a_single_1():
08425
08426 self.factor[1].set_force_inner_brackets_display(True)
08427
08428
08429
08430
08431
08432
08433
08434
08435 def is_expandable(self):
08436 return True
08437
08438
08439
08440
08441
08442
08443
08444
08445 def expand(self):
08446
08447 if len(self.factor[0]) == 1 \
08448 and isinstance(self.factor[0].term[0], Sum):
08449
08450 copy = Expandable(self)
08451 copy.element[0] = copy.factor[0].term[0]
08452 return copy.expand()
08453
08454 if len(self.factor[1]) == 1 \
08455 and isinstance(self.factor[1].term[0], Sum):
08456
08457 copy = Expandable(self)
08458 copy.element[1] = copy.factor[1].term[0]
08459 return copy.expand()
08460
08461
08462 terms_list = list()
08463
08464 for i in xrange(len(self.factor[0])):
08465 for j in xrange(len(self.factor[1])):
08466 terms_list.append(self.factor[0].term[i]
08467 .times(self.factor[1].term[j]))
08468
08469 if len(self.factor[0]) == 1 \
08470 and (self.factor[0].term[0].is_equivalent_to_a_single_minus_1() \
08471 or self.factor[0].term[0].is_equivalent_to_a_single_1()):
08472
08473 for i in xrange(len(terms_list)):
08474 terms_list[i] = terms_list[i].reduce_()
08475
08476 return Sum(terms_list)
08477
08478
08479
08480
08481
08482
08483
08484
08485
08486
08487
08488
08489
08490 def expand_and_reduce_(self):
08491 expanded_objct = self.expand()
08492
08493 terms_list = list()
08494
08495 for term in expanded_objct:
08496 terms_list.append(term.reduce_())
08497
08498 return Sum(terms_list)
08499
08500
08501
08502
08503
08504
08505
08506
08507 def expand_and_reduce_next_step(self, **options):
08508 copy = Expandable(self)
08509
08510 a_factor_at_least_has_been_modified = False
08511
08512
08513 if len(self.factor[0]) == 1 \
08514 and (self.factor[0].term[0].is_equivalent_to_a_single_1() \
08515 or self.factor[0].term[0].is_equivalent_to_a_single_minus_1()\
08516 ):
08517
08518 if isinstance(self.factor[1], Sum) \
08519 and len(self.factor[1]) > 1 \
08520 and self.factor[1].exponent.is_equivalent_to_a_single_1():
08521
08522 return self.expand()
08523
08524
08525 for i in xrange(len(copy)):
08526 test = copy.factor[i].expand_and_reduce_next_step(**options)
08527 if test != None:
08528 copy.element[i] = test
08529 a_factor_at_least_has_been_modified = True
08530
08531 if a_factor_at_least_has_been_modified:
08532 return copy
08533
08534
08535 else:
08536 return self.expand()
08537
08538
08539
08540
08541
08542
08543
08544
08545
08546
08547
08548
08549
08550
08551
08552
08553
08554
08555
08556
08557 class BinomialIdentity(Expandable):
08558
08559
08560
08561
08562
08563
08564
08565
08566
08567
08568
08569
08570
08571
08572
08573
08574
08575
08576
08577
08578
08579
08580 def __init__(self, arg, **options):
08581 if not (type(arg) == tuple and len(arg) == 2) \
08582 and not isinstance(arg, BinomialIdentity):
08583
08584 raise error.UncompatibleType(arg,
08585 "That should be a tuple of two" \
08586 + "elements or a BinomialIdentity")
08587
08588
08589 self.element = list()
08590
08591 self.compact_display = True
08592 self.info = [False, False]
08593
08594
08595 self.exponent = Value(1)
08596
08597 self.symbol = "×"
08598 self.str_openmark = "BI:: "
08599 self.str_closemark = " ::BI"
08600
08601
08602
08603
08604
08605 self.kind = ""
08606
08607
08608
08609 if isinstance(arg, BinomialIdentity):
08610 for i in xrange(len(arg.element)):
08611 self.element.append(arg.element[i].deep_copy())
08612 self.compact_display = arg.compact_display
08613 for i in xrange(len(arg.info)):
08614 self.info.append(arg.info[i])
08615 self.exponent = arg.exponent.deep_copy()
08616 self.kind = arg.kind
08617 self.a = arg.a.deep_copy()
08618 self.b = arg.b.deep_copy()
08619
08620
08621
08622 elif isinstance(arg[0], Exponented) and isinstance(arg[1], Exponented):
08623 a = arg[0].deep_copy()
08624 b = arg[1].deep_copy()
08625
08626 self.a = a
08627 self.b = b
08628
08629 self.element.append(Sum([a, b]))
08630
08631 if b.get_sign() == '+':
08632 self.kind = 'sum_square'
08633 else:
08634 self.kind = 'difference_square'
08635
08636 if 'squares_difference' in options:
08637
08638
08639 b = Product([Item(-1), b]).reduce_()
08640 self.kind = 'squares_difference'
08641
08642 self.element.append(Sum([a, b]))
08643
08644
08645
08646 elif arg[0] == __.RANDOMLY:
08647
08648 if arg[1] == 'numeric_sum_square'\
08649 or arg[1] == 'numeric_difference_square' \
08650 or arg[1] == 'numeric_squares_difference':
08651
08652 a_list = [20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 300, 400,
08653 500, 600, 700, 800, 1000]
08654
08655 b_list = [1, 2, 3]
08656
08657 a_choice = randomly.pop(a_list)
08658
08659 if a_choice >= 200:
08660 b_list = [1, 2]
08661
08662 a = Monomial(('+',
08663 a_choice,
08664 0))
08665
08666 b_choice = randomly.pop(b_list)
08667
08668 b = Monomial(('+',
08669 b_choice,
08670 0))
08671
08672 else :
08673 degrees_list = [0, 1]
08674 coeff_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
08675
08676 a = Monomial(('+',
08677 randomly.pop(coeff_list),
08678 randomly.pop(degrees_list)))
08679
08680 b = Monomial(('+',
08681 randomly.pop(coeff_list),
08682 randomly.pop(degrees_list)))
08683
08684 self.a = a
08685 self.b = b
08686
08687
08688 if arg[1] == 'sum_square' or arg[1] == 'numeric_sum_square':
08689 self.element.append(Sum([a, b]))
08690 self.element.append(Sum([a, b]))
08691 self.kind = 'sum_square'
08692
08693 elif arg[1] == 'difference_square' \
08694 or arg[1] == 'numeric_difference_square':
08695
08696 b.set_sign('-')
08697 self.element.append(Sum([a, b]))
08698 self.element.append(Sum([a, b]))
08699 self.kind = 'difference_square'
08700
08701 elif arg[1] == 'squares_difference' \
08702 or arg[1] == 'numeric_squares_difference':
08703
08704 sums_list = list()
08705 sums_list.append(Sum([a, b]))
08706 minus_b = Monomial(b)
08707 minus_b.set_sign('-')
08708 sums_list.append(Sum([a, minus_b]))
08709 self.element.append(randomly.pop(sums_list))
08710 self.element.append(randomly.pop(sums_list))
08711 self.kind = 'squares_difference'
08712
08713
08714 elif arg[1] == 'any':
08715 if randomly.heads_or_tails():
08716 a.set_sign(randomly.sign())
08717 b.set_sign(randomly.sign())
08718 self.a = a
08719 self.b = b
08720 self.element.append(Sum([a, b]))
08721 self.element.append(Sum([a, b]))
08722 if b.get_sign() == '+':
08723 self.kind = 'sum_square'
08724 else:
08725 self.kind = 'difference_square'
08726
08727 else:
08728 a.set_sign(randomly.sign())
08729 b.set_sign(randomly.sign())
08730 self.a = a
08731 self.b = b
08732 self.element.append(Sum([a, b]))
08733 minus_b = Monomial(b)
08734 minus_b.set_sign(lib.sign_of_product(['-', b.sign]))
08735 self.element.append(Sum([a, minus_b]))
08736 self.kind = 'squares_difference'
08737
08738 else:
08739 raise error.UncompatibleType(arg[1],
08740 'sum_square|difference_square|' \
08741 + 'squares_difference|' \
08742 + 'numeric_{sum_square|differen' \
08743 + 'ce_square|' \
08744 + 'squares_difference}|any')
08745
08746 else:
08747 raise error.UncompatibleType(arg,
08748 "(Exponented, Exponented)|" \
08749 + "(__.RANDOMLY, <type>)")
08750
08751
08752
08753
08754
08755
08756
08757
08758
08759 def expand(self):
08760
08761
08762 debug.write( \
08763 "\nEntering :\n[expand][BinomialIdentity]\n" \
08764 + "self.kind = " + str(self.kind) \
08765 + "\n",
08766 case=debug.expand_in_special_identity)
08767
08768 if self.kind == 'sum_square':
08769 square_a = Product(self.a)
08770 square_a.set_exponent(2)
08771 double_product = Product([2, self.a, self.b])
08772 square_b = Product(self.b)
08773 square_b.set_exponent(2)
08774 return Sum([square_a,
08775 double_product,
08776 square_b])
08777
08778 elif self.kind == 'difference_square':
08779 square_a = Product(self.a)
08780 square_a.set_exponent(2)
08781 b = self.b
08782 b.set_sign('+')
08783 double_product = Product([-2, self.a, b])
08784 square_b = Product(b)
08785 square_b.set_exponent(2)
08786 return Sum([square_a,
08787 double_product,
08788 square_b])
08789
08790 elif self.kind == 'squares_difference':
08791 square_a = Product(self.a)
08792 square_a.set_exponent(2)
08793 b = self.b
08794 b.set_sign('+')
08795 square_b = Product(b)
08796 square_b.set_exponent(2)
08797 square_b = Product([Item(-1), square_b])
08798 return Sum([square_a,
08799 square_b])
08800
08801
08802
08803
08804
08805
08806
08807
08808 def expand_and_reduce_next_step(self, **options):
08809 return self.expand()
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820
08821 def make_string(self, markup, **options):
08822 global expression_begins
08823
08824
08825
08826
08827
08828
08829
08830 if self.kind == 'squares_difference':
08831 return Product(self.factor).make_string(markup, **options)
08832
08833 else:
08834 squared_sum = Sum([self.a, self.b])
08835 squared_sum.set_exponent(2)
08836 return squared_sum.make_string(markup, **options)
08837
08838
08839
08840
08841