sintaxis simbolos significa reglas que predicados negacion lenguaje corte prolog prolog-cut

simbolos - reglas en prolog



¿Cómo los puntos de elección de poda en el siguiente código lo hacen más eficiente(Prolog)? (1)

En el código que se proporciona a continuación, está el ! (corte) que poda el punto de elección para la eficiencia. Estoy bastante seguro de que el predicado reverse y el predicado agent_do_moves son esenciales.

solve_task(Task,Cost):- agent_current_position(oscar,P), solve_task_a(Task,[b(0,0,P)],[],R,Cost,_NewPos),!, % prune choice point for efficiency reverse(R,[_Init|Path]), agent_do_moves(oscar,Path).


El corte en los ejemplos anteriores tiene el siguiente efecto:

Idealmente, compromete la búsqueda que podría ocurrir dentro de solve_task_a/6 con la primera respuesta encontrada. Esto libera recursos para encontrar más respuestas que mejoren el consumo de espacio.

Problemas de alcance

Sin embargo, al mismo tiempo, también podría ocultar más respuestas a agent_current_position/2 . Por supuesto, no tiene mucho sentido tener más respuestas para este objetivo, pero podría ser un error que le ocurra dormir por un tiempo, solo para volverse activo pero aún no descubierto en la peor situación posible.

Por esta razón, sería preferible escribir en lugar del corte

..., once( solve_task_a( ... ) ), ...

Esto limita el alcance precisamente a lo que desea expresar.

Problema de estabilidad

Pero esta no es la única fuente posible de problemas. Veo esta variable Cost . ¿Se solve_task(Task, Cost) una instancia cuando llame a solve_task(Task, Cost) o no? Podría hacer muchas conjeturas aquí. Pero al menos esta variable podría influir en la respuesta con la que Prolog se comprometerá. Así que solve_task(Task, 99) y solve_task(Task, Cost), Cost = 99 pueden producir respuestas diferentes. De hecho, este último podría incluso fallar. Se dice que los predicados que tienen tales problemas carecen de constancia .

Para ilustrar cómo la constancia se pierde fácilmente en una situación así, considere este bosquejo (ejecutable) de su programa (ya mejorado):

solve_task(Task,Cost):- % agent_current_position(oscar,P), once(solve_task_a(Task,[b(0,0,P)],[],R,Cost,_NewPos)), true. solve_task_a(_, _, _, _, 20, _). solve_task_a(_, _, _, _, 30, _).

Ahora

?- solve_task(a, Cost). Cost = 20. ?- solve_task(a, 30). true. ?- solve_task(a, Cost), Cost = 30. false.

Habría una forma fácil de salir de este problema al evaluar limpiamente el Cost variable, por ejemplo, Cost >= 0 que produce un error de instanciación si el Cost fuera una variable no ejecutada. Pero si quiere (como lo indica en su comentario) determinar el costo, debe expresarlo de la siguiente manera:

solve_task(Task,Cost):- % agent_current_position(oscar,P), once(solve_task_a(Task,[b(0,0,P)],[],R,CostX,_NewPos)), CostX = Cost true.

De esta manera, podemos estar seguros de que Cost no puede influir en el resultado de solve_task_a/6 (euh, siempre que no haya alias entre Cost y Task , pero supongamos que por el momento). También se dice que las unificaciones de salida se ponen detrás de la confirmación .

Muchas personas le dirán que tal cuidado adicional no es necesario, ya que nunca usará solve_task(Task, Cost) con un costo dado. Ese podría ser el caso, pero ¿estás seguro de que lo recordarás? ¿Y está seguro de que el código fuente lo recordará (sin ningún control dinámico)? Tales suposiciones implícitas se acumulan fácilmente en un grado en que sus capacidades mentales están sobrecargadas.

No siempre hay una salida fácil. Pero a menudo es posible apegarse a la pureza lógica de la pureza lógica . En ese caso, no tiene que recordar ninguna de esas suposiciones.

En cualquier caso, le recomendaría que no entre en estas partes de Prolog por el momento. Más bien se adhieren a sucesor-aritmética , clpfd y otros programas limpios y monótonos que preservan la pureza lógica . ¡Hay mucho que aprender!