diff --git a/polimani.pl b/polimani.pl index d636d4f..c85711a 100644 --- a/polimani.pl +++ b/polimani.pl @@ -150,6 +150,8 @@ term(L * R) :- %@ false. %% ?- term(a). %@ false. +%% ?- term(-1*x). +%@ true . %% ?- term((-3)*x^2). %@ true . %% ?- term(3.2*x). @@ -244,8 +246,17 @@ term_to_list(P, [P2]) :- %% Tests: %% ?- term_to_list(1, X). %@ X = [1] . +%% ?- term_to_list(-1, X). +%@ X = [-1] . %% ?- term_to_list(1*2*y*z*23*x*y*x^3*x, X). %@ X = [x^1, x^3, y^1, x^1, 23, z^1, y^1, 2, 1] . +%% ?- term_to_list(X, [-1]). +%@ X = -1 . +%% ?- term_to_list(X, [x^1, -1]). +%@ X = -1*x . +%% ?- term_to_list(X, [- 1, x^1]). +%@ false. +%@ X = x* -1 . %% ?- term_to_list(X, [y^1, x^1]). %@ X = x*y . %% ?- term_to_list(X, [x^4]). @@ -327,20 +338,22 @@ join_similar_parts_of_term([], []). %% simplify_polynomial(+P:atom, -P2:atom) is det % % Simplifies a polynomial. -% TODO: not everything is a +, there are - % simplify_polynomial(0, 0) :- !. simplify_polynomial(P, P2) :- polynomial_to_list(P, L), maplist(term_to_list, L, L2), - maplist(join_similar_parts_of_term, L2, L3), - maplist(sort(0, @=<), L3, L4), - join_similar_terms(L4, L5), - transform_list(sort(0, @>=), L5, L6), - transform_list(term_to_list, L7, L6), - delete(L7, 0, L8), - polynomial_to_list(P2, L8), + maplist(sort(0, @>=), L2, L3), + sort(0, @>=, L3, L4), + maplist(join_similar_parts_of_term, L4, L5), + maplist(sort(0, @=<), L5, L6), + join_similar_terms(L6, L7), + maplist(reverse, L7, L8), + maplist(term_to_list, L9, L8), + delete(L9, 0, L10), + sort(0, @=<, L10, L11), + list_to_polynomial(L11, P2), !. %% Tests: %% ?- simplify_polynomial(1, X). @@ -351,19 +364,43 @@ simplify_polynomial(P, P2) :- %@ X = x. %% ?- simplify_polynomial(x*x, X). %@ X = x^2. +%% ?- simplify_polynomial(2 + 2, X). +%@ X = 2*2. +%% ?- simplify_polynomial(x + x, X). +%@ X = 2*x. %% ?- simplify_polynomial(0 + 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. +%% ?- simplify_polynomial(x^2*x + 3*x^3 + x^3 + x*x*4 + z, X). +%@ X = 5*x^3+4*x^2+z. +%% ?- simplify_polynomial(x + 1 + x, X). +%@ X = 2*x+1. +%% ?- simplify_polynomial(x + 1 + x + 1 + x + 1 + x, X). +%@ X = 4*x+3*1. +%% join_similar_terms(+P:ListList, -P2:ListList) is det +% +% Joins similar sublists representing terms by using +% `add_terms` to check if they can be merged and perform +% the addition. Requires the list of list be sorted with +% `maplist(sort(0, @>=), L, L2), +% sort(0, @>=, L2, L3)` +% and that the sublists to be sorted with +% `sort(0, @=<)` since that is inherited from `add_terms` +% join_similar_terms([TL, TR | L], L2) :- + %% Check if terms can be added and add them add_terms(TL, TR, T2), + %% Recurse, accumulation on the first element join_similar_terms([T2 | L], L2), %% Give only first result. Red cut !. join_similar_terms([X | L], [X | L2]) :- + %% If a pair of elements can't be added, skip one + %% and recurse join_similar_terms(L, L2), %% Give only first result. Red cut !. @@ -372,46 +409,51 @@ join_similar_terms([], []). %% ?- join_similar_terms([[2, x^3], [3, x^3], [x^3]], L). %@ L = [[6, x^3]]. -term_to_canon([T], [1, T]) :- +%% term_to_canon(+T:List, -T2:List) is det +% +% Adds a 1 if there's no number in the list +% Requires the list to be sorted such that the +% numbers come first. For instance with +% `sort(0, @=<)` +% +term_to_canon([T | TS], [1, T | TS]) :- + %% Since the list is sorted, if the first element + %% is not a number, then we need to add the 1 + not(number(T)), %% Give only first result. Red cut !. term_to_canon(L, L). %% Tests: +%% ?- term_to_canon([2], T). +%@ T = [2]. %% ?- term_to_canon([x^3], T). %@ T = [1, x^3]. +%% ?- term_to_canon([x^3, z], T). +%@ T = [1, x^3, z]. %% ?- term_to_canon([2, x^3], T). %@ T = [2, x^3]. +%% add_terms(+L:List, +R:List, -Result:List) is det +% +% Adds two terms represented as list by adding +% the coeficients if the power is the same. +% Requires the list of terms to be simplified. +% 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([1], [1], R). +%@ R = [2]. +%% ?- add_terms([x], [x], R). +%@ R = [2, x]. %% ?- 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(+L:list, -S:list) is det % % Simplifies a polynomial represented as a list @@ -424,31 +466,91 @@ simplify_polynomial_list(L, S) :- %% polynomial_to_list(+P:polynomial, -L:List) % % Converts a polynomial in a list. -% TODO: not everything is a +, there are - % +polynomial_to_list(L - T, [T2 | LS]) :- + term(T), + negate_term(T, T2), + polynomial_to_list(L, LS). polynomial_to_list(L + T, [T | LS]) :- term(T), polynomial_to_list(L, LS). - % The others computations are semantically meaningless - %% !. polynomial_to_list(T, [T]) :- term(T). %% Tests: -%%?- polynomial_to_list(2, S). +%% ?- polynomial_to_list(2, S). %@ S = [2] . -%%?- polynomial_to_list(x^2, S). +%% ?- polynomial_to_list(x^2, S). %@ S = [x^2] . -%%?- polynomial_to_list(x^2 + x^2, S). +%% ?- polynomial_to_list(x^2 + x^2, S). %@ S = [x^2, x^2] . -%%?- polynomial_to_list(2*x^2+5+y*2, S). +%% ?- polynomial_to_list(2*x^2+5+y*2, S). %@ S = [y*2, 5, 2*x^2] . -%%?- polynomial_to_list(P, [2]). +%% ?- polynomial_to_list(2*x^2+5-y*2, S). +%@ S = [-2*y, 5, 2*x^2] . +%% ?- polynomial_to_list(2*x^2-5-y*2, S). +%@ S = [-2*y, -5, 2*x^2] . +%% ?- polynomial_to_list(P, [2]). %@ P = 2 . -%%?- polynomial_to_list(P, [x]). +%% ?- polynomial_to_list(P, [x]). %@ P = x . -%%?- polynomial_to_list(P, [x^2, x, -2.3]). +%% ?- polynomial_to_list(P, [x^2, x, 2.3]). +%@ Action (h for help) ? abort +%@ % Execution Aborted %@ P = -2.3+x+x^2 . +%% list_to_polynomial(+P:polynomial, -L:List) +% +% Converts a list in a polynomial. +% +list_to_polynomial([T1|T2], P) :- + list_to_polynomial(T2, L1), + ( + not(L1 = []), + ( + term_string(T1, S1), + string_chars(S1, [First|_]), + First = -, + term_string(L1, S2), + string_concat(S2,S1,S3), + term_string(P, S3) + ; + P = L1+T1 + ) + ; + P = T1 + ), + % The others computations are semantically meaningless + !. +list_to_polynomial(T, P) :- + P = T. +%% Tests: +%% TODO + +%% negate_term(T, T2) is det +% +% Negate the coeficient of a term and return the negated term +% +negate_term(T, T2) :- + term_to_list(T, L), + sort(0, @=<, L, L2), + term_to_canon(L2, L3), + [N | R] = L3, + %% (-)/1 is an operator, needs to be evaluated, otherwise + %% it gives a symbolic result, which messes with further processing + N2 is -N, + reverse([N2 | R], L4), + term_to_list(T2, L4), + !. +%% Tests: +%% ?- negate_term(1, R). +%@ R = -1. +%% ?- negate_term(x, R). +%@ R = -1*x. +%% ?- negate_term(x^2, R). +%@ R = -1*x^2. +%% ?- negate_term(3*x*y^2, R). +%@ R = -3*x*y^2. + %% append_two_atoms_with_star(+V1, +V2, -R) is det % % Returns R = V1 * V2 @@ -481,73 +583,3 @@ scale_polynomial(P, C, S) :- %% Tests: %% ?- scale_polynomial(3*x^2, 2, S). %@ S = 2*3*x^2. - - - -/* CENAS DO PROF: */ - - - - -%% monomial_parts(X, Y, Z) -% -% TODO Maybe remove -% Separate monomial into it's parts. Given K*X^N, gives K and N -% -monomial_parts(X, 1, X) :- - power(X), - !. -monomial_parts(X^N, 1, X^N) :- - power(X^N), - !. -monomial_parts(K * M, K, M) :- - number(K), - !. -monomial_parts(K, K, indep) :- - number(K), - !. - - -delete_monomial(M, X, M, 0) :- - term(M), - monomial_parts(M, _, X), - !. -delete_monomial(M + M2, X, M, M2) :- - term(M2), - term(M), - monomial_parts(M, _, X), - !. -delete_monomial(P + M, X, M, P) :- - term(M), - monomial_parts(M, _, X), - !. -delete_monomial(P + M2, X, M, P2 + M2) :- - delete_monomial(P, X, M, P2). - -add_monomial(K1, K2, K3) :- - number(K1), - number(K2), !, - K3 is K1 + K2. -add_monomial(M1, M2, M3) :- - monomial_parts(M1, K1, XExp), - monomial_parts(M2, K2, XExp), - K3 is K1 + K2, - p_aux_add_monomial(K3, XExp, M3). - -p_aux_add_monomial(K, indep, K) :- - !. -p_aux_add_monomial(0, _, 0) :- - !. -p_aux_add_monomial(1, XExp, XExp) :- - !. -p_aux_add_monomial(K, XExp, K * XExp). - -closure_simplify_polynomial(P, P) :- - simplify_polynomial(P, P2), - P==P2, - !. -closure_simplify_polynomial(P, P3) :- - simplify_polynomial(P, P2), - closure_simplify_polynomial(P2, P3), - !. -