2
votes

Comment simplifier les équations d'algèbre représentées sous forme de liste de liste

Avec Prolog, je souhaite simplifier l ' expression algébrique représentée sous forme de liste de liste:

équation d'algèbre

f = 5x+3
[[5,1],[3,0]]

liste de liste

f = 3x+2x+1+2
[[3,1],[2,1],[1,0],[2,0]]

3 et 2 sont des coefficients
1 et 0 sont des exposants

Cela devrait être évident.

Je cherche des conseils ou des suggestions sur la façon de coder les simplifications pour cet exemple:

[[3,1],[2,0]]

simplifié:

f = 3x+2

J'ai essayé des fonctions intégrées mais je n'ai pas obtenu le une bonne idée sur la façon de les utiliser.


5 commentaires

Y a-t-il une erreur dans votre exemple? f = 3x + 2x + 1 + 2 doit être [[3,1], [2,1], [1,0], [2,0]] au lieu de [[1,3], [2,1], [1,0], [2,0]] ?


oui merci, corrigé


Voulez-vous également résoudre des systèmes d'équations?


S'agit-il uniquement d'expressions polynomiales d'une variable?


oui il ne s'agit que d'une seule variable, résoudre le systéme je l'ai fait, mais est-ce que je peux me déranger avec une solution manipulant uniquement des listes?


3 Réponses :


2
votes

Vous pouvez résoudre votre problème de cette manière:

simplify(_,_,S,S,[]):- !.
simplify(L,I,Sum,NTot,[[I,S]|T]):-
    Sum =< NTot,
    findall(X,member([X,I],L),LO),
    length(LO,N),
    S1 is Sum + N,
    sum_list(LO,S),
    I1 is I+1,
    simplify(L,I1,S1,NTot,T).           

write_function([]).
write_function([[D,V]|T]):-
    write(' + '),write(V),write('x^'),write(D),
    write_function(T).

test:-
    L = [[3,1],[2,1],[1,0],[2,0]],
    length(L,N),
    simplify(L,0,0,N,LO), 
    LO = [[D,V]|T],
    write('f='),write(V),write('x^'),write(D),
    write_function(T).

Le prédicat principal est simplify / 5 qui utilise findall / 3 pour trouver tous les coefficients de même degré puis les additionner à l'aide de sum_list / 2 . Ensuite, vous pouvez écrire le résultat d'une manière sophistiquée en utilisant write_function/1.


1 commentaires

merci beaucoup, mais pouvez-vous m'offrir une solution utilisant uniquement la manipulation de liste?



2
votes

Dans SWI-Prolog, vous pouvez utiliser l'agrégat:

?- simplify([[3,1],[2,1],[1,0],[2,0]], Out).
Out = [[5, 1], [3, 0]] ;
false.

Par exemple:

pred(>, [_,X], [_,Y]) :- X > Y.
pred(<, [_,X], [_,Y]) :- X < Y.
pred(=, [_,X], [_,X]).

simplify(In, Out) :-
    aggregate(set([S,X]), aggregate(sum(P), member([P,X], In), S), Temp),
    predsort(pred, Temp, Out).


1 commentaires

merci beaucoup, mais pouvez-vous m'offrir une solution utilisant uniquement la manipulation de liste?



3
votes

Une doublure, similaire à ce qui est proposé par joel76:

simplify(I,O) :-
    bagof([S,E],L^(bagof(C,member([C,E],I),L),sum_list(L,S)),O).

Le bagof intérieur collecte C (coefficients) donné E (exposants ), la liste résultante L est additionnée en S , et associée à E devient [S, E] , un élément (monôme) de O. Si vous omettez le spécificateur de quantification universel (c'est-à-dire L ^ ), vous obtenez des monômes uniques lors du retour en arrière.


2 commentaires

J'ai utilisé un pré-tri pour obtenir Out = [[5, 1], [3, 0]]; , vous obtenez Out = [[3, 0], [5, 1]] . Je ne sais pas si c'est important!


L'ordre des monômes devrait être sans importance, je pense. L'agrégat BTW est basé sur setof, etc., donc la commande est déjà implicite