es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo hacer recursión en un sistema de reescritura inspirado en L-sistemas, sin DCG.

Estoy tratando de escribir un pequeño sistema de reescritura recursiva inspirado en el Sistema L de Aristid Lindenmayer, básicamente para aprender Prolog así como para pensar en conceptos generativos en Prolog. Me gustaría lograr esto sin DCG. Debido a los efectos secundarios del predicado inicial generate. y output, no es una idea de Prolog 100% pura. No dudes en descomponer el concepto.

Mi principal problema está al final de la lista. Hacer coincidir la regla para cada elemento de la lista original y crear una nueva lista con el resultado de cada sustitución.

[a] El axioma se convierte en [a,b] se convierte en [a,b,a] y así sucesivamente. O mejor aún como una lista de listas [[a,b],[a]] para mantenerlo más flexible y comprensible, ¿y luego aplanarlo más adelante?

Un ejemplo básico sin constantes, que se podría agregar de manera similar. El axioma se utiliza solo una vez al principio. La idea es codificar el nombre o símbolo de la regla a intercambiar y los símbolos con los que se debe intercambiar, como un hecho/relación. Comenzar con generate. lo repetiría 20 veces con un contador.

% Las reglas
axiom(a, [a]).
rule(a, [a, b]).
rule(b, [a]).

% Comienza el programa
generate :-
axiom(a, G),
next_generation(20, G).

% Repetirlo hasta que el contador sea 0.
next_generation(0, _) :- !.
next_generation(N, G) :-
output(G),
linden(G, Next),
succ(N1, N),
next_generation(N1, Next).

% Concatena la lista en una cadena para la salida
output(G) :-
atomic_list_concat(G,”,C),
writeln(C).

% Aquí estoy atascado, la búsqueda y el intercambio recursivo.
% ¿Cómo intercambio cada elemento con la sustitución correspondiente en una nueva lista?

linden([],[]). % La lista vacía devuelve lista vacía.
linden([R],Next) :- % Lista con solo un elemento, p. e., el axioma
rule(R, Next). % Busca la regla y devuelve la lista para intercambiar la corriente.
linden([H|T], Next) :- % Si hay más de un elemento en la lista original,
rule(H,E), % busque la regla para el Encabezado/Elemento de lista actual
% ????? % Concatene el resultado con el resultado de los elementos anteriores
linden(T, Next). % Recursión hasta que se procese la lista original.
% Una vez hecho esto, devuelve la nueva lista a next_generation/2

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Solución

    Para crear la nueva lista con la sustitución de cada elemento en la lista original, puede utilizar el predicado maplist/3 incorporado. Este predicado aplica un predicado dado a cada elemento de una lista y crea una nueva lista con los resultados.

    Primero, debe modificar el predicado linden/2 para aplicar la regla de sustitución a cada elemento en la lista. Esto se puede hacer utilizando maplist/3 de la siguiente manera:

    linden([], []).                               % La lista vacía devuelve una lista vacía.
    linden([R], Next) :-                           % Lista con solo un elemento, por ejemplo el axioma
       rule(R, Next).                              % Buscar la regla y la lista para intercambiar el actual
    linden([H|T], Next) :-                         % Si hay más de un elemento en la lista original
       maplist(aplicar_regla, [H|T], Result),      % Aplicar la regla a cada elemento de la lista
       append(Result, Next),                       % Concatenar los resultados para crear la nueva lista
       linden(Next, Next).                         % Llamada recursiva con la nueva lista.
    
    
    aplicar_regla(E, R) :-                         % Aplicar la regla R al elemento E
        rule(E, R) -> R = R ; [E].                 % Si hay una regla, aplicarla. De lo contrario, mantener E.
    

    El predicado aplicar_regla/2 aplica la regla al elemento si hay una regla definida para ese elemento, de lo contrario solo devuelve el elemento en sí.

    Luego, en el predicado next_generation/2, puede reemplazar la llamada a linden/2 con una llamada al predicado linden/2 actualizado:

    next_generation(N, G) :- 
        output(G),                     
        linden(G, Next),                           % Aplicar la regla del L-system para crear la nueva lista
        succ(N1, N),                              
        next_generation(N1, Next).
    

    Esto aplicará la regla de sustitución a cada elemento en la lista y creará una nueva lista con los resultados.

    Finalmente, para mantener la nueva lista como una lista de listas, puede modificar las definiciones de Axioma y regla:

        % Las reglas
        axiom([a], [[a]]).           
        rule([a], [[a], [b]]).
        rule([b], [[a]]). 
    

    Esto define el Axioma y las reglas como una lista de listas, donde cada elemento de la lista representa una rama separada.

    Con estas modificaciones, el programa debería poder crear y mostrar una nueva lista con la sustitución de cada elemento en la lista original.

    También tenga en cuenta que el predicado generate/0 no es seguro, ya que utiliza el predicado writeln/1, que es una operación de IO que puede fallar. Para hacerlo seguro, puede reemplazarlo con el predicado format/2, que devuelve verdadero independientemente de la operación de salida. Por ejemplo:

    generate :- 
        axiom([a], G), 
        next_generation(20, G).
    
    output(G) :- 
        format("~s~n", [[G]]).
    

    En este caso, el predicado format/2 se utiliza para mostrar la lista de listas como una cadena, que luego se puede analizar más tarde para recrear la lista de listas.

Comments are closed.