He definido un predicado replace(word_to_be_replaced, replacement, [List_requires_replacement], [storing_List] )
y lo estoy usando para simplificar expresiones aritméticas como: -
simplify([Head|Tail], Simplified) :-
(replace(add(a,a), 2*a, [Head|Tail], L) ; L = [Head|Tail]), !, Simplified = L.
Ahora el problema es que me gustaría reemplazar términos comox+y+x
por 2*x+y
también. La expresión aritmética que ingresa el usuario será de la siguiente forma ejemplo add(x,div(1,z))
Por favor, ayuda tan pronto como sea posible. Gracias.
Respuestas
2 para la respuesta № 1Necesitas normalizar tus términos de alguna manera. Esto es un altamente incompleto Bosquejo de cómo me sentiría tentado de acercarme a él. Creo que el enfoque podría ser confirmado, pero tendrá que hacer una doble comprobación de que maneja todos los casos correctamente.
Primero, note como se ve en forma canónica:
?- write_canonical(x+y+x).
+(+(x,y),x)
true.
Ahí está el quid del problema. Uno x
está en lo profundo del árbol. El otro está en un nivel diferente. Necesitamos tenerlos a todos en el mismo lugar para que podamos procesarlos juntos. Esto significa que queremos moverlos a la misma lista de alguna manera. Creo que queremos [+, x, y, x]
porque entonces podemos clasificar eso en [+, x, x, y]
y luego procesarlo de forma recursiva.
?- x+y+x =.. Q.
Q = [+, x+y, x].
Mejor, pero no todo el camino todavía.
expand(Var, Var) :- number(Var) ; atom(Var).
expand(Term, Expanded) :-
(+ number(Var), + atom(Var)),
Term =.. Parts,
maplist(expand, Parts, Expanded).
?- expand(x+y+x, Q).
Q = [+, [+, x, y], x] ;
Mejor. Ahora tenemos que aplanarlo de alguna manera.
flatten_expr([Op, [Op|Inner] | Outer], Result) :-
append([Op|Inner], Outer, Result).
flatten_expr(Other, Other).
?- expand(x+y+x, Q), flatten_expr(Q, QFlat).
Q = [+, [+, x, y], x],
QFlat = [+, x, y, x]
Si clasificamos en el medio podemos seguir con la vida.
flatten_expr([Op, [Op|Inner] | Outer], Result) :-
append([Op|Inner], Outer, ResultU),
msort(ResultU, Result).
flatten_expr(A, A).
Ahora puedes aplicar tus patrones a estos y simplificarlos.
simplify([+, X, X | Rest0], [+, [*, 2, X] | Rest1]) :-
simplify([+, Rest0], [+, Rest1]).
?- expand(x+y+x, Q), flatten_expr(Q, QFlat), simplify(QFlat, Simplified).
Q = [+, [+, x, y], x],
QFlat = [+, x, x, y],
Simplified = [+, [*, 2, x], y]
Entonces solo necesitas una forma de volver a convertir a la representación algebraica. Si expand/2
un poco mejor, tal vez podría correr hacia atrás para hacer eso, pero este no lo es. Dejo esto como un ejercicio para el estudiante.