def big_product(): s = Sum(['x', 3]) s.set_exponent(3) p = Product(Monomial((1, 2))) p.set_exponent(3) p1 = Product([2, 3]) p1.set_exponent(3) return Product([ Monomial((2, 1)), Monomial((-4, 2)), s, Item(5), p, Item(('+', -1, 2)), p1 ])
def test_sum_3squareplus5(): """Is this Sum correctly printed as 3^{2}+5?""" p = Product([Item(3)]) p.set_exponent(2) assert Sum([p, Item(5)]).printed == wrap_nb('3^{2}+5')
def level_03(q_subkind, **options): a = randomly.integer(1, 10) b = randomly.integer(1, 10) steps = [] if q_subkind in [ 'sum_square', 'sum_square_mixed', 'difference_square', 'difference_square_mixed' ]: # __ first_term = Monomial(('+', Item(('+', a, 2)).evaluate(), 2)) second_term = Monomial( ('+', Item(('+', Product([2, a, b]).evaluate(), 1)).evaluate(), 1)) third_term = Monomial(('+', Item(('+', b, 2)).evaluate(), 0)) if q_subkind in ['difference_square', 'difference_square_mixed']: second_term.set_sign('-') if q_subkind in ['sum_square_mixed', 'difference_square_mixed']: ordered_expression = Polynomial( [first_term, second_term, third_term]) [first_term, second_term, third_term] = randomly.mix([first_term, second_term, third_term]) steps.append(Polynomial([first_term, second_term, third_term])) if q_subkind in ['sum_square_mixed', 'difference_square_mixed']: steps.append(ordered_expression) sq_a_monom = Monomial(('+', a, 1)) sq_b_monom = Monomial(('+', b, 0)) let_a_eq = Equality([Item('a'), sq_a_monom]) let_b_eq = Equality([Item('b'), sq_b_monom]) steps.append( _("Let") + " " + let_a_eq.into_str(force_expression_markers=True) + " " + _("and") + " " + let_b_eq.into_str(force_expression_markers=True)) sq_a_monom.set_exponent(2) sq_b_monom.set_exponent(2) a_square_eq = Equality( [Item(('+', 'a', 2)), sq_a_monom, sq_a_monom.reduce_()]) b_square_eq = Equality( [Item(('+', 'b', 2)), sq_b_monom, sq_b_monom.reduce_()]) steps.append( _("then") + " " + a_square_eq.into_str(force_expression_markers=True)) steps.append( _("and") + " " + b_square_eq.into_str(force_expression_markers=True)) two_times_a_times_b_numeric = Product( [Item(2), Monomial(('+', a, 1)), Item(b)]) two_times_a_times_b_reduced = two_times_a_times_b_numeric.reduce_() two_times_a_times_b_eq = Equality([ Product([Item(2), Item('a'), Item('b')]), two_times_a_times_b_numeric, two_times_a_times_b_reduced ]) steps.append( _("and") + " " + two_times_a_times_b_eq.into_str(force_expression_markers=True)) steps.append(_("So it is possible to factorize:")) if q_subkind in ['difference_square', 'difference_square_mixed']: b = -b factorized_expression = Sum([Monomial(('+', a, 1)), Item(b)]) factorized_expression.set_exponent(2) steps.append(factorized_expression) elif q_subkind in ['squares_difference', 'squares_difference_mixed']: # To have some (ax)² - b² but also sometimes b² - (ax)²: degrees = [2, 0, 1, 0] if randomly.integer(1, 10) >= 8: degrees = [0, 2, 0, 1] first_term = Monomial(('+', Item(('+', a, 2)).evaluate(), degrees[0])) second_term = Monomial(('-', Item(('+', b, 2)).evaluate(), degrees[1])) sq_first_term = Monomial(('+', Item( ('+', a, 1)).evaluate(), degrees[2])) sq_second_term = Monomial(('-', Item( ('+', b, 1)).evaluate(), degrees[3])) # The 'mixed' cases are: -b² + (ax)² and -(ax)² + b² if q_subkind == 'squares_difference_mixed': [first_term, second_term] = randomly.mix([first_term, second_term]) [sq_first_term, sq_second_term] = randomly.mix([sq_first_term, sq_second_term]) positive_sq_first = sq_first_term.clone() positive_sq_first.set_sign('+') positive_sq_second = sq_second_term.clone() positive_sq_second.set_sign('+') steps.append(Polynomial([first_term, second_term])) first_inter = None second_inter = None if sq_second_term.is_negative(): first_inter = positive_sq_first.clone() first_inter.set_exponent(2) temp_second_inter = positive_sq_second.clone() temp_second_inter.set_exponent(2) second_inter = Product([-1, temp_second_inter]) else: temp_first_inter = positive_sq_first.clone() temp_first_inter.set_exponent(2) first_inter = Product([-1, temp_first_inter]) second_inter = positive_sq_second.clone() second_inter.set_exponent(2) steps.append(Sum([first_inter, second_inter])) if q_subkind == 'squares_difference_mixed': steps.append(Sum([second_inter, first_inter])) steps.append(_("So, this expression can be factorized:")) sum1 = None sum2 = None if sq_second_term.is_negative(): sum1 = Sum([sq_first_term, sq_second_term]) sq_second_term.set_sign('+') sum2 = Sum([sq_first_term, sq_second_term]) else: sum1 = Sum([sq_second_term, sq_first_term]) sq_first_term.set_sign('+') sum2 = Sum([sq_second_term, sq_first_term]) lil_box = [sum1, sum2] steps.append(Product([randomly.pop(lil_box), randomly.pop(lil_box)])) elif q_subkind in [ 'fake_01', 'fake_01_mixed', 'fake_02', 'fake_02_mixed', 'fake_03', 'fake_03_mixed', 'fake_04_A', 'fake_04_A_mixed', 'fake_04_B', 'fake_04_B_mixed', 'fake_04_C', 'fake_04_C_mixed', 'fake_04_D', 'fake_04_D_mixed' ]: # __ straight_cases = [ 'fake_01', 'fake_02', 'fake_03', 'fake_04_A', 'fake_04_B', 'fake_04_C', 'fake_04_D' ] match_pb_cases = [ 'fake_01', 'fake_02', 'fake_01_mixed', 'fake_02_mixed' ] sign_pb_cases = [ 'fake_03', 'fake_03_mixed', 'fake_04_A', 'fake_04_B', 'fake_04_C', 'fake_04_D', 'fake_04_A_mixed', 'fake_04_B_mixed', 'fake_04_C_mixed', 'fake_04_D_mixed' ] ax = Monomial(('+', a, 1)) b_ = Monomial(('+', b, 0)) ax_2 = ax.clone() ax_2.set_exponent(2) a2x2 = Monomial(('+', a * a, 2)) b_2 = Monomial(('+', b, 0)) b_2.set_exponent(2) b2 = Monomial(('+', b * b, 0)) two_ax_b = Product([Item(2), Monomial(('+', a, 1)), Item(b)]) twoabx = Monomial(('+', 2 * a * b, 1)) fake_twoabx = Monomial(('+', a * b, 1)) if randomly.integer(1, 10) >= 8: fake_twoabx = Monomial( ('+', 2 * a * b + randomly.pop([-1, 1]) * randomly.integer(1, 5), 1)) first_term = None second_term = None third_term = None ordered_expression = None mixed_expression = None if q_subkind == 'fake_03' or q_subkind == 'fake_03_mixed': first_term = a2x2.clone() second_term = b2.clone() ordered_expression = Polynomial([first_term, second_term]) mixed_expression = Polynomial([second_term, first_term]) else: first_term = a2x2.clone() third_term = b2.clone() if q_subkind in [ 'fake_01', 'fake_01_mixed', 'fake_02', 'fake_02_mixed' ]: # __ second_term = fake_twoabx.clone() else: second_term = twoabx.clone() if q_subkind == 'fake_02' or q_subkind == 'fake_02_mixed': second_term.set_sign('-') elif q_subkind == 'fake_04_A' or q_subkind == 'fake_04_A_mixed': third_term.set_sign('-') elif q_subkind == 'fake_04_B' or q_subkind == 'fake_04_B_mixed': first_term.set_sign('-') elif q_subkind == 'fake_04_C' or q_subkind == 'fake_04_C_mixed': second_term.set_sign('-') third_term.set_sign('-') elif q_subkind == 'fake_04_D' or q_subkind == 'fake_04_D_mixed': first_term.set_sign('-') second_term.set_sign('-') ordered_expression = Polynomial( [first_term, second_term, third_term]) mixed_expression = Polynomial( randomly.mix([first_term, second_term, third_term])) if q_subkind in straight_cases: steps.append(ordered_expression) elif q_subkind == 'fake_03_mixed': steps.append(mixed_expression) else: steps.append(mixed_expression) steps.append(ordered_expression) if q_subkind in match_pb_cases: let_a_eq = Equality([Item('a'), ax]) let_b_eq = Equality([Item('b'), b_]) steps.append( _("Let") + " " + let_a_eq.into_str(force_expression_markers=True) + " " + _("and") + " " + let_b_eq.into_str(force_expression_markers=True)) a_square_eq = Equality([Item(('+', 'a', 2)), ax_2, a2x2]) b_square_eq = Equality([Item(('+', 'b', 2)), b_2, b2]) steps.append( _("then") + " " + a_square_eq.into_str(force_expression_markers=True)) steps.append( _("and") + " " + b_square_eq.into_str(force_expression_markers=True)) two_times_a_times_b_eq = Equality([ Product([Item(2), Item('a'), Item('b')]), two_ax_b, twoabx, fake_twoabx ], equal_signs=['=', '=', 'neq']) steps.append( _("but") + " " + two_times_a_times_b_eq.into_str(force_expression_markers=True)) steps.append(_("So it does not match a binomial identity.")) steps.append(_("This expression cannot be factorized.")) elif q_subkind in sign_pb_cases: steps.append(_("Because of the signs,")) steps.append(_("it does not match a binomial identity.")) steps.append(_("This expression cannot be factorized.")) return steps
def level_02(q_subkind, **options): max_coeff = 20 if 'max_coeff' in options and is_.an_integer(options['max_coeff']): max_coeff = options['max_coeff'] attribute_a_minus_sign = 'randomly' if 'minus_sign' in options and options['minus_sign']: attribute_a_minus_sign = 'yes' elif 'minus_sign' in options and not options['minus_sign']: attribute_a_minus_sign = 'no' # Creation of the objects # The three Monomials: ax², bx and c # Maybe we don't need to keep the integer values... a_val = randomly.integer(1, max_coeff) b_val = randomly.integer(1, max_coeff) c_val = randomly.integer(1, max_coeff) if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1', 'type_1_C1' ]: # __ c_val = randomly.integer(2, max_coeff) ax2 = Monomial((randomly.sign(), a_val, 2)) bx = Monomial((randomly.sign(), b_val, 1)) c = Monomial((randomly.sign(), c_val, 0)) # deg1: mx + p # and we need two of them deg1 = [] for i in range(2): deg1_mx = Monomial((randomly.sign(), randomly.integer(1, max_coeff), 1)) deg1_p = None if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_A1', 'type_1_B1', 'type_1_D1', 'type_1_E1', 'type_1_G1', 'type_1_H1', 'type_4_A0' ]: # __ deg1_p = Monomial( (randomly.sign(), randomly.integer(1, max_coeff), 0)) else: deg1_p = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 0)) if not deg1_p.is_null(): lil_box = [deg1_mx, deg1_p] deg1.append( Polynomial([randomly.pop(lil_box), randomly.pop(lil_box)])) else: deg1.append(deg1_mx) # deg2: mx² + px + r # and we also need two of them deg2 = [] for i in range(2): deg2_mx2 = Monomial((randomly.sign(), randomly.integer(1, max_coeff), 2)) deg2_px = None deg2_r = None if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_A1', 'type_1_B1', 'type_1_D1', 'type_1_E1', 'type_1_G1', 'type_1_H1' ]: # __ if randomly.heads_or_tails(): deg2_px = Monomial( (randomly.sign(), randomly.integer(1, max_coeff), 1)) deg2_r = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 0)) else: deg2_px = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 1)) deg2_r = Monomial( (randomly.sign(), randomly.integer(1, max_coeff), 0)) else: deg2_px = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 1)) deg2_r = Monomial( (randomly.sign(), randomly.integer(0, max_coeff), 0)) lil_box = [deg2_mx2] if not deg2_px.is_null(): lil_box.append(deg2_px) if not deg2_r.is_null(): lil_box.append(deg2_r) monomials_list_for_deg2 = [] for i in range(len(lil_box)): monomials_list_for_deg2.append(randomly.pop(lil_box)) deg2.append(Polynomial(monomials_list_for_deg2)) # Let's attribute the common factor C according to the required type # (NB: expression ± C×F1 ± C×F2) C = None if q_subkind in [ 'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1' ]: # __ C = c elif q_subkind in [ 'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_D1', 'type_1_E1' ]: # __ C = bx elif q_subkind in [ 'type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_G1', 'type_1_H1' ]: # __ C = ax2 elif q_subkind in [ 'type_2_A0', 'type_2_B0', 'type_2_C0', 'type_2_A1', 'type_2_B1', 'type_4_A0' ]: # __ C = Polynomial([bx, c]) elif q_subkind in [ 'type_2_D0', 'type_2_E0', 'type_2_F0', 'type_2_D1', 'type_2_E1' ]: # __ C = Polynomial([ax2, c]) elif q_subkind in [ 'type_3_A0', 'type_3_B0', 'type_3_C0', 'type_3_A1', 'type_3_B1' ]: # __ C = Polynomial([ax2, bx, c]) # Let's attribute F1 and F2 according to the required type # (NB: expression ± C×F1 ± C×F2) F1 = None F2 = None if q_subkind in [ 'type_1_A0', 'type_1_A1', 'type_1_D0', 'type_1_D1', 'type_1_G0', 'type_1_G1', 'type_2_A0', 'type_2_A1', 'type_2_D0', 'type_2_D1', 'type_3_A0', 'type_3_A1' ]: # __ F1 = deg1[0] F2 = deg1[1] elif q_subkind in [ 'type_1_B0', 'type_1_B1', 'type_1_E0', 'type_1_E1', 'type_1_H0', 'type_1_H1', 'type_2_B0', 'type_2_B1', 'type_2_E0', 'type_2_E1', 'type_3_B0', 'type_3_B1' ]: # __ F1 = deg2[0] F2 = deg2[1] elif q_subkind in [ 'type_1_C0', 'type_1_F0', 'type_1_I0', 'type_2_C0', 'type_2_F0', 'type_3_C0' ]: # __ F1 = deg1[0] F2 = deg2[0] # The special case type_4_A0: (ax+b)² + (ax+b)×deg1' # aka C² + C×F1 elif q_subkind == 'type_4_A0': F1 = C.clone() F2 = deg1[0] # Let's put a "1" somewhere in the type_*_*1 if q_subkind in [ 'type_1_A1', 'type_1_D1', 'type_1_G1', 'type_2_A1', 'type_2_D1', 'type_3_A1', 'type_1_B1', 'type_1_E1' 'type_1_H1', 'type_2_B1', 'type_2_E1', 'type_3_B1' ]: # __ if randomly.heads_or_tails(): F1 = Item(1) else: F2 = Item(1) # Let's possibly attribute a minus_sign # (NB: expression ± C×F1 ± C×F2) minus_sign = None # this will contain the name of the factor having # a supplementary minus sign in such cases: # C×F1 - C×F2# - C×F1 + C×F2 # in all the following cases, it doesn't bring anything to attribute # a minus sign if ((q_subkind in ['type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1'] and c_val < 0) or ((q_subkind in ['type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_D1', 'type_1_E1']) and b_val < 0) or ((q_subkind in ['type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_G1', 'type_1_H1']) and a_val < 0)): # __ pass # here we let minus_sign equal to None # otherwise, let's attribute one randomly, # depending on attribute_a_minus_sign else: if attribute_a_minus_sign in ['yes', 'randomly']: # __ if (attribute_a_minus_sign == 'yes' or randomly.heads_or_tails()): # __ if randomly.heads_or_tails(): minus_sign = "F1" else: minus_sign = "F2" else: pass # here we let minus_sign equal to None # Now let's build the expression ! expression = None box_product1 = [C, F1] box_product2 = [C, F2] if q_subkind == 'type_4_A0': CF1 = Product([C]) CF1.set_exponent(Value(2)) else: CF1 = Product([randomly.pop(box_product1), randomly.pop(box_product1)]) CF2 = Product([randomly.pop(box_product2), randomly.pop(box_product2)]) if minus_sign == "F1": if len(F1) >= 2: CF1 = Expandable((Item(-1), CF1)) else: CF1 = Product([Item(-1), CF1]) elif minus_sign == "F2": if len(F2) >= 2: CF2 = Expandable((Item(-1), CF2)) else: CF2 = Product([Item(-1), CF2]) expression = Sum([CF1, CF2]) # Now let's build the factorization steps ! steps = [] steps.append(expression) F1F2_sum = None if minus_sign is None: F1F2_sum = Sum([F1, F2]) elif minus_sign == "F1": if len(F1) >= 2: F1F2_sum = Sum([Expandable((Item(-1), F1)), F2]) else: F1F2_sum = Sum([Product([Item(-1), F1]), F2]) elif minus_sign == "F2": if len(F2) >= 2: F1F2_sum = Sum([F1, Expandable((Item(-1), F2))]) else: F1F2_sum = Sum([F1, Product([Item(-1), F2])]) temp = Product([C, F1F2_sum]) temp.set_compact_display(False) steps.append(temp) F1F2_sum = F1F2_sum.expand_and_reduce_next_step() while F1F2_sum is not None: steps.append(Product([C, F1F2_sum])) F1F2_sum = F1F2_sum.expand_and_reduce_next_step() # This doesn't fit the need, because too much Products are # wrongly recognized as reducible ! if steps[len(steps) - 1].is_reducible(): steps.append(steps[len(steps) - 1].reduce_()) return steps
def complicated_product_01(): p1 = Product([Item(-2), Item(7)]) p1.set_exponent(2) return Product([Item(4), p1])
def neg3_by_neg5_exp_neg1_squared(): p = Product([Item(-3), Item(-5)]) p.set_exponent(Item(('+', -1, 2))) return p
def neg1_squared(): p = Product(Item(-1)) p.set_exponent(2) return p
def test_product_neg10x_next_step(): """Is this Product's calculation's next step correct?""" p = Product([Monomial(('-', 10, 1))]) p.set_exponent(2) assert p.calculate_next_step().printed == wrap_nb('100x^{2}')
def test_product_neg10x_printed(): """Is this Product correctly printed?""" p = Product([Monomial(('-', 10, 1))]) p.set_exponent(2) assert p.printed == wrap_nb('(-10x)^{2}')
def test_square_product_square_item_x_printed(): """Is this Product correctly printed?""" p = Product(Item(('+', 'x', 2))) p.set_exponent(2) assert p.printed == wrap_nb('(x^{2})^{2}')
def test_square_product_monom_x_printed(): """Is this Product correctly printed?""" p = Product(Monomial(('+', 1, 1))) p.set_exponent(2) assert p.printed == wrap_nb('x^{2}')
def product_1square(): p = Product(Item(1)) p.set_exponent(2) return p