From 200eec49effd93286a1c09f45eb8985f7649d0ff Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Thu, 22 Nov 2018 18:44:33 +0000 Subject: [PATCH 1/5] Added some documentation, fixed some bugs and partial negative polynomial support --- polimani.pl | 177 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 113 insertions(+), 64 deletions(-) diff --git a/polimani.pl b/polimani.pl index 448bfb9..24b7506 100644 --- a/polimani.pl +++ b/polimani.pl @@ -84,6 +84,8 @@ term(L * R) :- %@ false. %% ?- term(a). %@ false. +%% ?- term(-1*x). +%@ true . %% ?- term((-3)*x^2). %@ true . %% ?- term(3.2*x). @@ -178,8 +180,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]). @@ -268,13 +279,16 @@ 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), + polynomial_to_list(P2, L11), !. %% Tests: %% ?- simplify_polynomial(1, X). @@ -285,19 +299,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 !. @@ -306,107 +344,118 @@ 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(+L1,-L3) is det % % Simplifies a list of polynomials % -simplify_polynomial_list([L1], L3) :- - simplify_polynomial(L1, L2), - L3 = [L2]. -simplify_polynomial_list([L1|L2],L3) :- - simplify_polynomial(L1, P1), - simplify_polynomial_list(L2, P2), - L3 = [P1|P2], - % There is nothing further to compute at this point - !. +simplify_polynomial_list(L, L2) :- + maplist(simplify_polynomial, L, L2). %% 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. -%% % 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 +%% 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 % From 8c722af8e9ad512a4dbf29b36309dbb4f713faaf Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Thu, 22 Nov 2018 20:00:44 +0000 Subject: [PATCH 2/5] Re-add list_to_polynomial TODO: implement - --- polimani.pl | 20 ++++++++++++++++++++ teste.pl | 0 2 files changed, 20 insertions(+) create mode 100644 teste.pl diff --git a/polimani.pl b/polimani.pl index 24b7506..06e7e9f 100644 --- a/polimani.pl +++ b/polimani.pl @@ -432,6 +432,26 @@ polynomial_to_list(T, [T]) :- %@ % Execution Aborted %@ 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 + %% negate_term(T, T2) is det % % Negate the coeficient of a term and return the negated term diff --git a/teste.pl b/teste.pl new file mode 100644 index 0000000..e69de29 From a4c231f1eb6a7c53ef503b82d0de642d671eeca0 Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Thu, 22 Nov 2018 21:10:20 +0000 Subject: [PATCH 3/5] discreetly fixes the code --- polimani.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polimani.pl b/polimani.pl index 06e7e9f..cdd7054 100644 --- a/polimani.pl +++ b/polimani.pl @@ -288,7 +288,7 @@ simplify_polynomial(P, P2) :- maplist(term_to_list, L9, L8), delete(L9, 0, L10), sort(0, @=<, L10, L11), - polynomial_to_list(P2, L11), + list_to_polynomial(L11, P2), !. %% Tests: %% ?- simplify_polynomial(1, X). From ad892c971150d8b9a7fbe24d41f4f0b9138583c7 Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Thu, 22 Nov 2018 21:11:10 +0000 Subject: [PATCH 4/5] discreetly fixes the code --- teste.pl | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 teste.pl diff --git a/teste.pl b/teste.pl deleted file mode 100644 index e69de29..0000000 From b00566901740c297d9d6088caa18ce89b258fb7b Mon Sep 17 00:00:00 2001 From: Diogo Cordeiro Date: Thu, 22 Nov 2018 23:13:32 +0000 Subject: [PATCH 5/5] Add support for - in list_to_polynomial --- polimani.pl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/polimani.pl b/polimani.pl index cdd7054..f63c06e 100644 --- a/polimani.pl +++ b/polimani.pl @@ -272,7 +272,6 @@ 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) :- !. @@ -399,7 +398,6 @@ simplify_polynomial_list(L, L2) :- %% 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), @@ -435,13 +433,21 @@ polynomial_to_list(T, [T]) :- %% 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 + ( + 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 ),