Q: PDDL doesn't compile problem and domain - planning
I don't know why it doesn't work. here is my code:
Domain
(define (domain tren_mover)
(:requirements :adl)
(:predicates
(conectado ?x ?y)
(en ?x ?y)
(movil ?x)
)
(:action mover
:parameters (?tren ?origen ?destino)
:precondition
(and
(movil ?tren)
(en ?origen ?destino)
(conectado ?origen ?destino)
)
:effect
(and
(en ?tren ?destino)
(not (en ?tren ?origen))
)
)
)
Problem
(define (problem tren_en_movimiento)
(:domain tren_mover)
(:objects
T - tren
F1- Fábrica1
F2 - Fábrica2
A - almacén
P - puerto
)
(:init
(en puerto tren)
(mover tren)
(conectado A P)
(conectado P F2)
(conectado F2 F1)
(conectado F1 A)
(conectado A F1)
(conectado F1 F2)
(conectado F2 P)
(conectado P A)
)
(:goal (and
(en F1 T)
)
)
)
The Error message that appears is:
Failed to parse the problem -- invalid syntax (, line 37)
/tmp/solver_planning_domains_tmp_4C4oEmiiY8B3Q/domain.pddl:
syntax error in line 16, '':
domain definition expected
There are several logical and syntactical mistakes in your code:
Logical
(en ?origen ?destino) how can you put two positions in the same place! it should be the tren who has to be in the origin position.
Syntactical
The objects in the problem, you have to understand the difference between types and objects, you are mixing between them!
There is a typo in the initial state, you are using mover instead of movil.
in the goal, you are using and() which is not needed, and moreover causes an error as you don't have two predicates to combine!
Domain
(define (domain tren_mover)
(:requirements :adl)
(:predicates
(conectado ?x ?y)
(en ?x ?y)
(movil ?x)
)
(:action mover
:parameters (?tren ?origen ?destino)
:precondition
(and
(movil ?tren)
(en ?tren ?origen)
(conectado ?origen ?destino)
)
:effect
(and
(en ?tren ?destino)
(not (en ?tren ?origen))
)
)
)
Problem
(define (problem tren_en_movimiento)
(:domain tren_mover)
(:objects tren Fabrica1 Fabrica2 almacen puerto)
(:init
(en tren puerto)
(movil tren)
(conectado almacen puerto)
(conectado puerto Fabrica2)
(conectado Fabrica2 Fabrica1)
(conectado Fabrica1 almacen)
(conectado almacen Fabrica1)
(conectado Fabrica1 Fabrica2)
(conectado Fabrica2 puerto)
(conectado puerto almacen)
)
(:goal
(en tren Fabrica1)
)
)
Solution Test
I think you should consider including the requirement :typing to categorize the parameters used in predicates and actions. Due to this error, the :objects in the problem file can't be parsed correctly.
Please refer to this link: https://planning.wiki/ref/pddl/requirements#typing
and try to rectify errors.
Also, You can use VS Code plugin available for PDDL to avoid syntax errors and solve the plan. It can be found here: https://marketplace.visualstudio.com/items?itemName=jan-dolejsi.pddl
Best Regards!
Related
Petri net encoding into PDDL
I am a beginner in PDDL. I am trying to write a domain file for Petri net with a fire transaction function. (define (domain newpetri) (:requirements :strips :typing :fluents) (:types place transition) (:predicates (incoming ?p - place ?t - transition) (outgoing ?t - transition ?p - place) ) (:functions (number-of-tokens ?p) ) (:action fire-transition :parameters (?t - transition) :preconditions (forall (?p - place) (or (not (incoming ?p ?t)) (> (number-of-tokens ?p) 0))) :effects (forall (?p - place) (when (incoming ?p ?t) (decrease (number-of-tokens ?p)))) (forall (?p - place) (when (outgoing ?t ?p) (increase (number-of-tokens ?p)))) ) it gives me an error in the following part: (forall (?p - place) (or (not (incoming ?p ?t)) (> (number-of-tokens ?p) 0))) should I define the place and the transition in predicate?? Thanks. I already wrote a domain and problem (define (domain petri) (:requirements :strips :typing :fluents) (:types token place ) (:predicates (at ?v - token ?p - place) (connected ?v - token ?p1 ?p2 - place) ) (:functions (initial-token ?v - token) (required-token ?p1 ?p2 - place) (total-tokens-used) ) (:action move :parameters (?v - token ?from ?to - place) :precondition (and (at ?v ?from) (connected ?v ?from ?to) (>= (initial-token ?v) (required-token ?from ?to))) :effect (and (not (at ?v ?from)) (at ?v ?to) (decrease (initial-token ?v) (required-token ?from ?to)) (increase (total-tokens-used) (required-token ?from ?to)) ) ) ) -------------------------------------------------- (define (problem petriproblem) (:domain petri) (:objects token - token spring summer fall winter - place ) (:init (at token spring) (= (initial-token token) 3) (connected token spring summer) (connected token summer fall) (connected token fall winter) (connected token winter spring) (= (required-token spring summer) 1) (= (required-token summer fall) 1) (= (required-token fall winter) 1) (= (total-tokens-used) 0) ) (:goal (at token winter) ) (:metric minimize (total-tokens-used) ) ) I am trying to use the same logic, by replacing the total-tokens-used with number-of-tokens and comparing the number-of-tokens between the incoming and outgoing transitions to determine whether the fire transition condition is valid or not. but I didn't know exactly how to do that.
CTL fomula until contains implication
when I use NuSMV tools to verify if my CTL is right, I encounter a problem that make me so confused. My model is and here's the NuSMV code: MODULE main VAR state : {ROOT, A1, B1, C1, D1, F1, M1}; ASSIGN init(state) := ROOT; next(state) := case state = ROOT : A1; state = A1 : {B1, C1}; state = B1 : D1; state = D1 : F1; TRUE : state; esac; CTLSPEC AG( state=A1 -> AX ( A [ state=B1 U ( state=D1 -> EX state=F1 ) ] ) ); CTLSPEC AG( state=A1 -> AX ( A [ state=B1 U ( state=F1 -> EX state=C1 ) ] ) ); CTLSPEC AG( state=A1 -> AX ( A [ state=M1 U ( state=F1 -> EX state=C1 ) ] ) ); My CTL formula is as follows: "AG( A1 -> AX ( A [ B1 U ( D1 -> EX ( F1) ) ] ) )" "AG( A1 -> AX ( A [ B1 U ( F1 -> EX ( C1) ) ] ) )" "AG( A1 -> AX ( A [ M1 U ( F1 -> EX ( C1) ) ] ) )" NuSMV verified the above three formulas all of which turns out to be true . So my question is that why the formula 2 and formula 3 turn out to be true?
This question is old, but I think it's still worth an answer, as the issue might be misleading for other people. M, s ⊨ A[ϕUψ] iff for all paths (s, s2,s3, s4, . ..) s.t. si Rt si+1 there is a state sj s.t. M, sj ⊨ ψ and M, si ⊨ ϕ for all i < j. So, for the property to be verified, ϕ must be true up until when ψ fires. Notice that if ψ fires immediately then the value of ϕ is not relevant. It is easy to see that all three formulas are trivially verified because ψ is true in the first state of each path starting from B1 and C1. This is the case because ψ is an implication which, in states B1 and C1, has a false premise. Since we know that A [ ANYTHING U TRUE ] is verified for any state, we conclude that all three properties are satisfiable.
Music intervals graphic with TIKZ
I am drawing a picture showing how to position segments for the natural music scale. My trigonometry lessons are long ago forgotten, so I apologize for this is going to be a very dummy question. Consider the followintìg tikz picture. I need to place the segment re-D so that its measure will be 8/9 the measure of the segment ut-C. Now I just placed it at a random distance of 8/9 between ut and ut'. What mathematical function should I use (sen, cos...???) and how do I write it down for tikz? \documentclass{article} \usepackage{tikz} \usetikzlibrary{calc} \begin{document} \begin{tikzpicture}[scale=2] \coordinate (o) at (0,0); \coordinate [label=below:ut] (ut) at (2,0); \coordinate [label=below:ut'] (ut') at (4,0); \coordinate [label=above:C] (C) at (2, 2.4); \coordinate [label=above:c] (c) at (4, 1.2); \coordinate (O) at ($ (c)!2!(C) $); \draw (ut) -- (ut'); \draw (ut) -- (C); \draw (C) -- (c); \draw (ut') -- (c); \coordinate [label=below:re] (re) at ($ (ut)!8.0/9!(ut') $); \coordinate [label=above:D] (D) at ($ (C)!8.0/9!(c) $); \draw (re) --(D); \node [fill=black, inner sep=1pt] (c') at ($ (ut)!1.0/6!(C) $) {}; \node [fill=black, inner sep=1pt] (c') at ($ (ut)!2.0/6!(C) $) {}; \node [fill=black, inner sep=1pt] (c') at ($ (ut)!3.0/6!(C) $) {}; \node [fill=black, inner sep=1pt] (c') at ($ (ut)!4.0/6!(C) $) {}; \node [fill=black, inner sep=1pt] (c') at ($ (ut)!5.0/6!(C) $) {}; \node [fill=black, inner sep=1pt] (c') at ($ (ut')!1.0/3!(c) $) {}; \node [fill=black, inner sep=1pt] (c') at ($ (ut')!2.0/3!(c) $) {}; \draw (ut') -- (c); \end{tikzpicture} \end{document} Thank you, A
If you are still interested, here is an answer to your question. In the following code, I assumed that c is always half as high as C on the diagram. You may change the fraction for the position of D. Right now it is set at 8/9. No trigonometry was required. I removed the code defining the origin (o). It was not used in any way. \begin{tikzpicture}[scale=1] \newlength{\height}\setlength{\height}{2.4cm} \newlength{\width}\setlength{\width}{4cm} \def\fraction{0.889} %8/9 \coordinate [label=below:ut] (ut) at (0,0); \coordinate [label=below:ut'] (ut') at (\width,0); \coordinate [label=above:C] (C) at ($(ut) + (0,\height)$); \coordinate [label=above:c] (c) at ($(ut') + (0,0.5\height)$); \draw (ut) -- (ut') -- (c) -- (C) -- cycle; \draw let \p{C} = (C), \p{c} = (c), \n{y_D} = {\fraction*\y{C}}, \n{x_D} = {\x{c}*2*(1-\fraction)} in (\n{x_D},\n{y_D}) coordinate[label=above:D] (D) -- (\n{x_D},0) coordinate[label=below:re] (re); %you could replace the previous line by %(\n{x_D},\n{y_D}) -- (\n{x_D},0); %because (D) and (re) aren't used later \foreach \x in {1,...,5}{ \fill[black] ($ (ut)!\x/6!(C) - (1pt,1pt)$) rectangle ++(2pt,2pt); } \foreach \x in {1,2}{ \fill[black] ($ (ut')!\x/3!(c) - (1pt,1pt)$) rectangle ++(2pt,2pt); } \end{tikzpicture} \end{document}
How to solve 15-puzzle paradigm in Prolog with Manhattan & Hamming Heuristics
I have this implementation of the 15-puzzle game, using Prolog (Swipl). I have already implemented the A* search using Manhattan heuristic, but now I need to add hamming heuristic. Do yo know how to implement it? :- op(400,yfx,'#'). resolver(Estado,MovimientosSolucion) :- evaluar(Estado,0,F), buscarSolucion([Estado#0#F#[]],S), reverse(S,MovimientosSolucion). evaluar(Estado,Profundidad,F) :- evaluarCoste(Estado,Coste), F is Profundidad + Coste. buscarSolucion([Estado#_#_#MovimientosSolucion|_], MovimientosSolucion) :- solucion(Estado). buscarSolucion([B|R],S) :- expandir(B,Sucesores), insertarTodos(Sucesores,R,ListaAbiertos), buscarSolucion(ListaAbiertos,S). insertarUno(B,ListaAbiertos,ListaAbiertos) :- nodoRepetido(B,ListaAbiertos), ! . insertarUno(B,[C|R],[B,C|R]) :- costeMenor(B,C), ! . insertarUno(B,[B1|R],[B1|S]) :- insertarUno(B,R,S), !. insertarUno(B,[],[B]). insertarTodos([F|R],ListaAbiertos1,ListaAbiertos2) :- insertarUno(F,ListaAbiertos1,ListaAbiertos3), insertarTodos(R,ListaAbiertos3,ListaAbiertos2). insertarTodos([],ListaAbiertos,ListaAbiertos). nodoRepetido(Estado#_#_#_, [Estado#_#_#_|_]). costeMenor( _#_#F1#_ , _#_#F2#_ ) :- F1 < F2. expandir(Estado#Profundidad#_#S,Sucesores) :- findall(Sucesor#Profundidad1#F#[Movimiento|S], (Profundidad1 is Profundidad+1, mover(Estado,Sucesor,Movimiento), evaluar(Sucesor,Profundidad1,F)), Sucesores). solucion(1/2/3/4/5/6/7/8/9/10/11/12/13/14/15/0). manhattan(A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P, Coste) :- a(A,CosteA), b(B,CosteB), c(C,CosteC), d(D, CosteD), e(E,CosteE), f(F,CosteF), g(G,CosteG), h(H,CosteH), i(I,CosteI), j(J,CosteJ), k(K,CosteK), l(L,CosteL), m(M,CosteM), n(N,CosteN), o(O,CosteO), p(P,CosteP), Coste is CosteA + CosteB + CosteC + CosteD + CosteE + CosteF + CosteG + CosteH + CosteI + CosteJ + CosteK + CosteL + CosteM + CosteN + CosteO + CosteP. evaluarCoste(Tablero,Coste) :- hamming_distance(Tablero,Coste). mover(TableroInicial,TableroFinal,moverArriba) :- moverArriba(TableroInicial,TableroFinal). mover(TableroInicial,TableroFinal,moverAbajo) :- moverAbajo(TableroInicial,TableroFinal). mover(TableroInicial,TableroFinal,moverDerecha) :- moverDerecha(TableroInicial,TableroFinal). mover(TableroInicial,TableroFinal,moverIzquierda) :- moverIzquierda(TableroInicial,TableroFinal). moverArriba(A/B/C/D/0/F/G/H/I/J/K/L/M/N/O/P,0/B/C/D/A/F/G/H/I/J/K/L/M/N/O/P). moverArriba(A/B/C/D/E/0/G/H/I/J/K/L/M/N/O/P,A/0/C/D/E/B/G/H/I/J/K/L/M/N/O/P). moverArriba(A/B/C/D/E/F/0/H/I/J/K/L/M/N/O/P,A/B/0/D/E/F/C/H/I/J/K/L/M/N/O/P). moverArriba(A/B/C/D/E/F/G/0/I/J/K/L/M/N/O/P,A/B/C/0/E/F/G/D/I/J/K/L/M/N/O/P). moverArriba(A/B/C/D/E/F/G/H/0/J/K/L/M/N/O/P,A/B/C/D/0/F/G/H/E/J/K/L/M/N/O/P). moverArriba(A/B/C/D/E/F/G/H/I/0/K/L/M/N/O/P,A/B/C/D/E/0/G/H/I/F/K/L/M/N/O/P). moverArriba(A/B/C/D/E/F/G/H/I/J/0/L/M/N/O/P,A/B/C/D/E/F/0/H/I/J/G/L/M/N/O/P). moverArriba(A/B/C/D/E/F/G/H/I/J/K/0/M/N/O/P,A/B/C/D/E/F/G/0/I/J/K/H/M/N/O/P). moverArriba(A/B/C/D/E/F/G/H/I/J/K/L/0/N/O/P,A/B/C/D/E/F/G/H/0/J/K/L/I/N/O/P). moverArriba(A/B/C/D/E/F/G/H/I/J/K/L/M/0/O/P,A/B/C/D/E/F/G/H/I/0/K/L/M/J/O/P). moverArriba(A/B/C/D/E/F/G/H/I/J/K/L/M/N/0/P,A/B/C/D/E/F/G/H/I/J/0/L/M/N/K/P). moverArriba(A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/0,A/B/C/D/E/F/G/H/I/J/K/0/M/N/O/L). moverAbajo(0/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P,E/B/C/D/0/F/G/H/I/J/K/L/M/N/O/P). moverAbajo(A/0/C/D/E/F/G/H/I/J/K/L/M/N/O/P,A/F/C/D/E/0/G/H/I/J/K/L/M/N/O/P). moverAbajo(A/B/0/D/E/F/G/H/I/J/K/L/M/N/O/P,A/B/G/D/E/F/0/H/I/J/K/L/M/N/O/P). moverAbajo(A/B/C/0/E/F/G/H/I/J/K/L/M/N/O/P,A/B/C/H/E/F/G/0/I/J/K/L/M/N/O/P). moverAbajo(A/B/C/D/0/F/G/H/I/J/K/L/M/N/O/P,A/B/C/D/I/F/G/H/0/J/K/L/M/N/O/P). moverAbajo(A/B/C/D/E/0/G/H/I/J/K/L/M/N/O/P,A/B/C/D/E/J/G/H/I/0/K/L/M/N/O/P). moverAbajo(A/B/C/D/E/F/0/H/I/J/K/L/M/N/O/P,A/B/C/D/E/F/K/H/I/J/0/L/M/N/O/P). moverAbajo(A/B/C/D/E/F/G/0/I/J/K/L/M/N/O/P,A/B/C/D/E/F/G/L/I/J/K/0/M/N/O/P). moverAbajo(A/B/C/D/E/F/G/H/0/J/K/L/M/N/O/P,A/B/C/D/E/F/G/H/M/J/K/L/0/N/O/P). moverAbajo(A/B/C/D/E/F/G/H/I/0/K/L/M/N/O/P,A/B/C/D/E/F/G/H/I/N/K/L/M/0/O/P). moverAbajo(A/B/C/D/E/F/G/H/I/J/0/L/M/N/O/P,A/B/C/D/E/F/G/H/I/J/O/L/M/N/0/P). moverAbajo(A/B/C/D/E/F/G/H/I/J/K/0/M/N/O/P,A/B/C/D/E/F/G/H/I/J/K/P/M/N/O/0). moverDerecha(0/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P,B/0/C/D/E/F/G/H/I/J/K/L/M/N/O/P). moverDerecha(A/0/C/D/E/F/G/H/I/J/K/L/M/N/O/P,A/C/0/D/E/F/G/H/I/J/K/L/M/N/O/P). moverDerecha(A/B/0/D/E/F/G/H/I/J/K/L/M/N/O/P,A/B/D/0/E/F/G/H/I/J/K/L/M/N/O/P). moverDerecha(A/B/C/D/0/F/G/H/I/J/K/L/M/N/O/P,A/B/C/D/F/0/G/H/I/J/K/L/M/N/O/P). moverDerecha(A/B/C/D/E/0/G/H/I/J/K/L/M/N/O/P,A/B/C/D/E/G/0/H/I/J/K/L/M/N/O/P). moverDerecha(A/B/C/D/E/F/0/H/I/J/K/L/M/N/O/P,A/B/C/D/E/F/H/0/I/J/K/L/M/N/O/P). moverDerecha(A/B/C/D/E/F/G/H/0/J/K/L/M/N/O/P,A/B/C/D/E/F/G/H/J/0/K/L/M/N/O/P). moverDerecha(A/B/C/D/E/F/G/H/I/0/K/L/M/N/O/P,A/B/C/D/E/F/G/H/I/K/0/L/M/N/O/P). moverDerecha(A/B/C/D/E/F/G/H/I/J/0/L/M/N/O/P,A/B/C/D/E/F/G/H/I/J/L/0/M/N/O/P). moverDerecha(A/B/C/D/E/F/G/H/I/J/K/L/0/N/O/P,A/B/C/D/E/F/G/H/I/J/K/L/N/0/O/P). moverDerecha(A/B/C/D/E/F/G/H/I/J/K/L/M/0/O/P,A/B/C/D/E/F/G/H/I/J/K/L/M/O/0/P). moverDerecha(A/B/C/D/E/F/G/H/I/J/K/L/M/N/0/P,A/B/C/D/E/F/G/H/I/J/K/L/M/N/P/0). moverIzquierda(A/0/C/D/E/F/G/H/I/J/K/L/M/N/O/P,0/A/C/D/E/F/G/H/I/J/K/L/M/N/O/P). moverIzquierda(A/B/0/D/E/F/G/H/I/J/K/L/M/N/O/P,A/0/B/D/E/F/G/H/I/J/K/L/M/N/O/P). moverIzquierda(A/B/C/0/E/F/G/H/I/J/K/L/M/N/O/P,A/B/0/C/E/F/G/H/I/J/K/L/M/N/O/P). moverIzquierda(A/B/C/D/E/0/G/H/I/J/K/L/M/N/O/P,A/B/C/D/0/E/G/H/I/J/K/L/M/N/O/P). moverIzquierda(A/B/C/D/E/F/0/H/I/J/K/L/M/N/O/P,A/B/C/D/E/0/F/H/I/J/K/L/M/N/O/P). moverIzquierda(A/B/C/D/E/F/G/0/I/J/K/L/M/N/O/P,A/B/C/D/E/F/0/G/I/J/K/L/M/N/O/P). moverIzquierda(A/B/C/D/E/F/G/H/I/0/K/L/M/N/O/P,A/B/C/D/E/F/G/H/0/I/K/L/M/N/O/P). moverIzquierda(A/B/C/D/E/F/G/H/I/J/0/L/M/N/O/P,A/B/C/D/E/F/G/H/I/0/J/L/M/N/O/P). moverIzquierda(A/B/C/D/E/F/G/H/I/J/K/0/M/N/O/P,A/B/C/D/E/F/G/H/I/J/0/K/M/N/O/P). moverIzquierda(A/B/C/D/E/F/G/H/I/J/K/L/M/0/O/P,A/B/C/D/E/F/G/H/I/J/K/L/0/M/O/P). moverIzquierda(A/B/C/D/E/F/G/H/I/J/K/L/M/N/0/P,A/B/C/D/E/F/G/H/I/J/K/L/M/0/N/P). % coste en distancias de cada posicion a(0,6). a(1,0). a(2,1). a(3,2). a(4,3). a(5,1). a(6,2). a(7,3). a(8,4). a(9,2). a(10,3). a(11,4). a(12,5). a(13,3). a(14,4). a(15,5). b(0,5). b(1,1). b(2,0). b(3,1). b(4,2). b(5,2). b(6,1). b(7,2). b(8,3). b(9,3). b(10,2). b(11,3). b(12,4). b(13,4). b(14,3). b(15,4). c(0,4). c(1,2). c(2,1). c(3,0). c(4,1). c(5,3). c(6,2). c(7,1). c(8,2). c(9,4). c(10,3). c(11,2). c(12,3). c(13,5). c(14,4). c(15,3). d(0,3). d(1,3). d(2,2). d(3,1). d(4,0). d(5,4). d(6,3). d(7,2). d(8,1). d(9,5). d(10,4). d(11,3). d(12,2). d(13,6). d(14,5). d(15,4). e(0,5). e(1,1). e(2,2). e(3,3). e(4,4). e(5,0). e(6,1). e(7,2). e(8,3). e(9,1). e(10,2). e(11,3). e(12,4). e(13,2). e(14,3). e(15,4). f(0,4). f(1,2). f(2,1). f(3,2). f(4,3). f(5,1). f(6,0). f(7,1). f(8,2). f(9,2). f(10,1). f(11,2). f(12,3). f(13,3). f(14,2). f(15,3). g(0,3). g(1,3). g(2,2). g(3,1). g(4,2). g(5,2). g(6,1). g(7,0). g(8,1). g(9,3). g(10,2). g(11,1). g(12,2). g(13,4). g(14,3). g(15,2). h(0,2). h(1,4). h(2,3). h(3,2). h(4,1). h(5,3). h(6,2). h(7,1). h(8,0). h(9,4). h(10,3). h(11,2). h(12,1). h(13,5). h(14,4). h(15,3). i(0,4). i(1,2). i(2,3). i(3,4). i(4,5). i(5,1). i(6,2). i(7,3). i(8,4). i(9,0). i(10,1). i(11,2). i(12,3). i(13,1). i(14,2). i(15,3). j(0,3). j(1,3). j(2,2). j(3,3). j(4,4). j(5,2). j(6,1). j(7,2). j(8,3). j(9,1). j(10,0). j(11,1). j(12,2). j(13,2). j(14,1). j(15,2). k(0,2). k(1,4). k(2,3). k(3,2). k(4,3). k(5,3). k(6,2). k(7,1). k(8,2). k(9,2). k(10,1). k(11,0). k(12,1). k(13,3). k(14,2). k(15,1). l(0,1). l(1,5). l(2,4). l(3,3). l(4,2). l(5,4). l(6,3). l(7,2). l(8,1). l(9,3). l(10,2). l(11,1). l(12,0). l(13,4). l(14,3). l(15,2). m(0,3). m(1,3). m(2,4). m(3,5). m(4,6). m(5,2). m(6,3). m(7,4). m(8,5). m(9,1). m(10,2). m(11,3). m(12,4). m(13,0). m(14,1). m(15,2). n(0,2). n(1,4). n(2,3). n(3,4). n(4,5). n(5,3). n(6,2). n(7,3). n(8,4). n(9,2). n(10,1). n(11,2). n(12,3). n(13,1). n(14,0). n(15,1). o(0,1). o(1,5). o(2,4). o(3,3). o(4,4). o(5,4). o(6,3). o(7,2). o(8,3). o(9,3). o(10,2). o(11,1). o(12,2). o(13,2). o(14,1). o(15,0). p(0,0). p(1,6). p(2,5). p(3,4). p(4,3). p(5,5). p(6,4). p(7,3). p(8,2). p(9,4). p(10,3). p(11,2). p(12,1). p(13,3). p(14,2). p(15,1). Thanks a lot
Here is the solver for 8-puzzle, extended... maybe it will use too much memory. It implements simply a greedy heuristic. Could be interesting to extend it with A*... /* File: fifteen_puzzle.pl Author: Carlo,,, Created: Jul 9 2014 Purpose: solve 15-puzzle */ :- module(fifteen_puzzle, [fifteen_puzzle/3 ]). :- use_module(library(nb_set)). :- use_module(library(plunit)). %% fifteen_puzzle(+Target, +Start, -Moves) is nondet. % % public interface to solver % fifteen_puzzle(Target, Start, Moves) :- empty_nb_set(E), solve(E, Target, Start, Moves). %% -- private here -- solve(_, Target, Target, []) :- !. solve(S, Target, Current, [Move|Ms]) :- add_to_seen(S, Current), setof(Dist-M-Update, ( get_move(Current, P, M), apply_move(Current, P, M, Update), distance(Target, Update, Dist) ), Moves), member(_-Move-U, Moves), solve(S, Target, U, Ms). %% get_move(+Board, +P, -Q) is semidet % % based only on coords, get next empty cell % get_move(Board, P, Q) :- nth0(P, Board, 0), coord(P, R, C), ( R < 3, Q is P + 4 ; R > 0, Q is P - 4 ; C < 3, Q is P + 1 ; C > 0, Q is P - 1 ). %% apply_move(+Current, +P, +M, -Update) % % swap elements at position P and M % apply_move(Current, P, M, Update) :- assertion(nth0(P, Current, 0)), % constrain to this application usage ( P > M -> (F,S) = (M,P) ; (F,S) = (P,M) ), nth0(S, Current, Sv, A), nth0(F, A, Fv, B), nth0(F, C, Sv, B), nth0(S, Update, Fv, C). %% coord(+P, -R, -C) % % from linear index to row, col % size fixed to 4*4 % coord(P, R, C) :- R is P // 4, C is P mod 4. %% distance(+Current, +Target, -Dist) % % compute Manatthan distance between equals values % distance(Current, Target, Dist) :- aggregate_all(sum(D), ( nth0(P, Current, N), coord(P, Rp, Cp), nth0(Q, Target, N), coord(Q, Rq, Cq), D is abs(Rp - Rq) + abs(Cp - Cq) ), Dist). %% add_to_seen(+S, +Current) % % fail if already in, else store % add_to_seen(S, L) :- %term_to_atom(L, A), findall(C, (nth0(I, L, D), C is D*10^I), Cs), sum_list(Cs, A), add_nb_set(A, S, true). :- begin_tests(fifteen_puzzle). show_square(R) :- findall(Row, (between(1,4,_), length(Row, 4)), Rows), append(Rows, R), nl, maplist(show_row, Rows). show_row(R) :- format('~t~d~3+~t~d~3+~t~d~3+~t~d~3+~n', R). show_solution(P, []) :- show_square(P). show_solution(P, [M|Ms]) :- show_square(P), nth0(C, P, 0), apply_move(P, C, M, U), show_solution(U, Ms). target( [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]). start(0, [1,2,3,4,5,6,7,8,9,10,11,12,0,13,14,15]). start(1, [1,2,3,4,5,6,7,8,0,10,11,12,9,13,14,15]). test(0) :- runtest(0). test(1) :- runtest(1). runtest(N) :- target(T), start(N, S), fifteen_puzzle(T, S, R), format('solution of ~d: ~w~n', [N, R]), show_solution(S, R). :- end_tests(fifteen_puzzle). you can use ?- run_tests(fifteen_puzzle). for a simple test.
Aggregating Facts in the CLIPS Expert System to Find a Maximum
I'm trying to clarify my understanding of semantics in the Clips expert system, so I'm trying to write some simple rules to aggregate a list of facts to find the fact with the highest slot value. The metaphor I'm using is that of a simple agent trying to decide whether it should eat or sleep. Facts describing the agent's states are expanded into potential actions, and then a rule tries to find the final action with the highest utility. This is my code: (clear) (deftemplate state (slot name) (slot level (type NUMBER)) ) (deftemplate action (slot name) (slot utility (type NUMBER)) (slot final (type INTEGER) (default 0)) ) (defrule eat-when-hungry "" (state (name hungry) (level ?level)) => (assert (action (name eat) (utility ?level))) ) (defrule sleep-when-sleepy "" (state (name sleepy) (level ?level)) => (assert (action (name sleep) (utility ?level))) ) (defrule find-final-action "" ?current_final <- (action (name ?current_final_action) (utility ? current_final_utility) (final 1)) (action (name ?other_action) (utility ?other_utility) (final 0)) (neq ?current_final_action ?other_action) (< ?current_final_action ?other_action) => (modify ?current_final (name ?other_action) (utility ? other_utility)) ) (assert (action (name none) (utility 0.0) (final 1))) (assert (state (name hungry) (level 0.5))) (assert (state (name sleepy) (level 0.1))) (run) (facts) After running this, I would expect the final action to be: (action (name eat) (utility 0.5) (final 1)) However, Clips evaluates it to: (action (name none) (utility 0.0) (final 1)) indicating the find-final-action rule never activates. Why is this? How would you iterate over a group of facts and find the one with the min/max slot value?
Your rule had a couple of errors in it. Here is the corrected version: (defrule find-final-action "" ?current_final <- (action (name ?current_final_action) (utility ?current_final_utility) (final 1)) (action (name ?other_action) (utility ?other_utility) (final 0)) (test (neq ?current_final_action ?other_action)) (test (< ?current_final_utility ?other_utility)) => (modify ?current_final (name ?other_action) (utility ?other_utility))) An alternate method which does not require storing intermediate computations and multiple rule firings is this: (defrule find-final-action-2 "" (declare (salience -10)) ; lower salience to allow all actions to be asserted first (action (name ?action) (utility ?utility)) (not (action (utility ?other_utility&:(> ?other_utility ?utility)))) => (printout t "Final action is " ?action crlf))