diff --git a/polimani.pl b/polimani.pl index 45f2af7..ce2f2a2 100644 --- a/polimani.pl +++ b/polimani.pl @@ -203,7 +203,7 @@ simplify_term(Term_In, Term_Out) :- Term_Out = Term_In ); exclude(==(1), L2, L3), - join_like_terms(L3, L4), + join_similar_parts_of_term(L3, L4), sort(0, @>=, L4, L5), term_to_list(Term_Out, L5) ), @@ -227,29 +227,35 @@ simplify_term(Term_In, Term_Out) :- %% ?- simplify_term(x^(-3), X). %@ false. -%% join_like_terms(+List, -List) +%% join_similar_parts_of_term(+List, -List) % % Combine powers of the same variable in the given list % -join_like_terms([P1, P2 | L], [B^N | L2]) :- +join_similar_parts_of_term([P1, P2 | L], L2) :- power(P1), power(P2), B^N1 = P1, B^N2 = P2, N is N1 + N2, - join_like_terms(L, L2). -join_like_terms([N1, N2 | L], [N | L2]) :- + join_similar_parts_of_term([B^N | L], L2). +join_similar_parts_of_term([N1, N2 | L], L2) :- number(N1), number(N2), N is N1 * N2, - join_like_terms(L, L2). -join_like_terms([X | L], [X | L2]) :- - join_like_terms(L, L2). -join_like_terms([], []). + join_similar_parts_of_term([N | L], L2). +join_similar_parts_of_term([X | L], [X | L2]) :- + join_similar_parts_of_term(L, L2). +join_similar_parts_of_term([], []). %% Tests: -%% ?- join_like_terms([2, 3, x^1, x^2], T). +%% ?- join_similar_parts_of_term([3], T). +%@ T = [3]. +%% ?- join_similar_parts_of_term([x^2], T). +%@ T = [x^2]. +%% ?- join_similar_parts_of_term([x^1, x^1, x^1, x^1], T). +%@ T = [x^4] . +%% ?- join_similar_parts_of_term([2, 3, x^1, x^2], T). %@ T = [6, x^3] . -%% ?- join_like_terms([2, 3, x^1, x^2, y^1, y^6], T). +%% ?- join_similar_parts_of_term([2, 3, x^1, x^2, y^1, y^6], T). %@ T = [6, x^3, y^7] . %% simplify_polynomial(+P:atom, -P2:atom) is det @@ -260,38 +266,85 @@ join_like_terms([], []). simplify_polynomial(M, M2) :- %% Are we dealing with a valid term? %is_term_valid_in_predicate(M, "simplify_polynomial(M, M2)"), - %% term(M), + term(M), %% If so, simplify it. simplify_term(M, M2), !. -simplify_polynomial(P + 0, P) :- - %% Ensure valid term - %is_term_valid_in_predicate(P, "simplify_polynomial(P + 0, P)"), - term(P), +simplify_polynomial(P, P2) :- + polynomial_to_list(P, L), + transform_list(term_to_list, L, L2), + transform_list(join_similar_parts_of_term, L2, L3), + transform_list(sort(0, @=<), L3, L4), + join_similar_terms(L4, L5), + transform_list(sort(0, @>=), L5, L6), + transform_list(term_to_list, L7, L6), + polynomial_to_list(P2, L7), !. -simplify_polynomial(0 + P, P) :- - %% Ensure valid term - %is_term_valid_in_predicate(P, "simplify_polynomial(0 + P, P)"), - term(P), - !. -simplify_polynomial(P + M, P2 + M2) :- - simplify_polynomial(P, P2), - simplify_term(M, M2). -simplify_polynomial(P + M, P2 + M3) :- - monomial_parts(M, _, XExp), - delete_monomial(P, XExp, M2, P2), - !, - add_monomial(M, M2, M3). -simplify_polynomial(P + M, P2 + M2) :- - simplify_polynomial(P, P2), - simplify_term(M, M2). %% Tests: %% ?- simplify_polynomial(1, X). -%@ false. -%@ false. -%@ Invalid term in simplify_polynomial(M, M2): 1 -%@ false. +%@ X = 1. +%% ?- simplify_polynomial(x, X). +%@ X = x. +%% ?- simplify_polynomial(x*x, X). +%@ X = x^2. +%% ?- simplify_polynomial(x^2*x + 3*x^3, X). +%@ X = 4*x^3. +%% ?- simplify_polynomial(x^2*x + 3*x^3 + x^3 + x*x*x, X). +%@ X = 6*x^3. +join_similar_terms([TL, TR | L], L2) :- + add_terms(TL, TR, T2), + join_similar_terms([T2 | L], L2), + %% Give only first result. Red cut + !. +join_similar_terms([X | L], [X | L2]) :- + join_similar_terms(L, L2), + %% Give only first result. Red cut + !. +join_similar_terms([], []). +%% Tests: +%% ?- join_similar_terms([[2, x^3], [3, x^3], [x^3]], L). +%@ L = [[6, x^3]]. + +term_to_canon([T], [1, T]) :- + %% Give only first result. Red cut + !. +term_to_canon(L, L). +%% Tests: +%% ?- term_to_canon([x^3], T). +%@ T = [1, x^3]. +%% ?- term_to_canon([2, x^3], T). +%@ T = [2, x^3]. + +add_terms([NL | TL], [NR | TR], [N2 | TL2]) :- + term_to_canon([NL | TL], [NL2 | TL2]), + term_to_canon([NR | TR], [NR2 | TR2]), + TL2 == TR2, + number(NL2), + number(NR2), + N2 is NL2 + NR2. +%% Tests +%% ?- add_terms([2, x^3], [x^3], R). +%@ R = [3, x^3]. +%% ?- add_terms([2, x^3], [3, x^3], R). +%@ R = [5, x^3]. + +%% transform_list(+Pred, +L, -R) is det +% +% Apply predicate to each of the elements of L, producing R +% +transform_list(_, [], []). +transform_list(Pred, [L | LS], [R | RS]) :- + call(Pred, L, R), + transform_list(Pred, LS, RS), + !. +%% Tests: +%% ?- transform_list(term_to_list, [x, 2], L). +%@ L = [[x^1], [2]]. +%% ?- transform_list(term_to_list, [x, x, 2], L). +%@ L = [[x^1], [x^1], [2]]. +%% ?- transform_list(term_to_list, L, [[x^1], [x^1], [2]]). +%@ L = [x, x, 2]. %% simplify_polynomial_list(+L1,-L3) is det % @@ -312,36 +365,48 @@ simplify_polynomial_list([L1|L2],L3) :- % Converts a polynomial in a list. % TODO: not everything is a +, there are - % -polynomial_to_list(T1 + T2, L) :- - polynomial_to_list(T1, L1), - L = [T2|L1], +polynomial_to_list(L + T, [T | LS]) :- + term(T), + polynomial_to_list(L, LS). % The others computations are semantically meaningless - !. -polynomial_to_list(P, L) :- - L = [P]. + %% !. +polynomial_to_list(T, [T]) :- + term(T). %% Tests: +%%?- polynomial_to_list(2, S). +%@ S = [2] . +%%?- polynomial_to_list(x^2, S). +%@ S = [x^2] . +%%?- polynomial_to_list(x^2 + x^2, S). +%@ S = [x^2, x^2] . %%?- polynomial_to_list(2*x^2+5+y*2, S). -%@S = [y*2, 5, 2*x^2]. +%@ S = [y*2, 5, 2*x^2] . +%%?- polynomial_to_list(P, [2]). +%@ P = 2 . +%%?- polynomial_to_list(P, [x]). +%@ P = x . +%%?- polynomial_to_list(P, [x^2, x, -2.3]). +%@ P = -2.3+x+x^2 . -%% list_to_polynomial(+P:polynomial, -L:List) -% -% Converts a list in a polynomial. -% TODO: not everything is a +, there are - -% -list_to_polynomial([T1|T2], P) :- - list_to_polynomial(T2, L1), - ( - not(L1 = []), - P = L1+T1 - ; - P = T1 - ), - % The others computations are semantically meaningless - !. -list_to_polynomial(T, P) :- - P = T. -%% Tests: -%% TODO +%% %% list_to_polynomial(+P:polynomial, -L:List) +%% % +%% % Converts a list in a polynomial. +%% % TODO: not everything is a +, there are - +%% % +%% list_to_polynomial([T1|T2], P) :- +%% list_to_polynomial(T2, L1), +%% ( +%% not(L1 = []), +%% P = L1+T1 +%% ; +%% P = T1 +%% ), +%% % The others computations are semantically meaningless +%% !. +%% list_to_polynomial(T, P) :- +%% P = T. +%% %% Tests: +%% %% TODO %% append_two_atoms_with_star(+V1, +V2, -R) is det %