Petri net encoding into PDDL - dsl

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.

Related

Q: PDDL doesn't compile problem and domain

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!

Clojure proxy multithreading issue

I'm trying to create a proxy for ArrayBlockingQueue that intercepts calls to it for monitoring
(ns clj-super-bug.core
(:import [java.util.concurrent ArrayBlockingQueue Executors]))
(let [thread-count 10
put-count 100
executor (Executors/newFixedThreadPool thread-count)
puts (atom 0)
queue (proxy [ArrayBlockingQueue] [1000]
(put [el]
(proxy-super put el)
(swap! puts inc)))]
(.invokeAll executor (repeat put-count #(.put queue 0)))
(assert (= (.size queue) put-count) "should have put in put-count items")
(println #puts))
I would expect this code to always print 100, but occaissonally it's something else like 51. Am I using proxy or proxy-super wrong?
I debugged this to the point that it seems that the proxy method is not actually called on some occasions, just the base method (the items show up in the queue, as indicated by the assert). Also, I suppose it's multithreading related because if I have thread-count = 1 it's always 100.
Turns out this is a known issue with proxy-super: https://dev.clojure.org/jira/browse/CLJ-2201
"If you have a proxy with method M, which invokes proxy-super, then while that proxy-super is running all calls to M on that proxy object will immediately invoke the super M not the proxied M." That's exactly what's happening.
I would not do the subclass via proxy.
If you subclass ArrayBlockingQueue, you are saying your code is an instance of ABQ. So, you are making a specialized version of ABQ, and must take responsibility for all of the implementation details of the ABQ source code.
However, you don't need to be an instance of ABQ. All you really need is to use an instance of ABQ, which is easily done by composition.
So, we write a wrapper function which delegates to an ABQ:
(ns tst.demo.core
(:use demo.core tupelo.core tupelo.test)
(:require
[clojure.string :as str]
[clojure.java.io :as io])
(:import [java.util.concurrent ArrayBlockingQueue Executors TimeUnit]) )
(dotest
(let [N 100
puts-done (atom 0)
abq (ArrayBlockingQueue. (+ 3 N))
putter (fn []
(.put abq 0)
(swap! puts-done inc))]
(dotimes [_ N]
(future (putter)))
(Thread/sleep 1000)
(println (format "N: %d puts-done: %d" N #puts-done))
(assert (= N #puts-done)
(format "should have put in puts-done items; N = %d puts-done = %d" N #puts-done))
))
result:
N: 100 puts-done: 100
Using the executor:
(dotest
(let [N 100
puts-done (atom 0)
thread-count 10
executor (Executors/newFixedThreadPool thread-count)
abq (ArrayBlockingQueue. (+ 3 N))
putter (fn []
(.put abq 0)
(swap! puts-done inc))
putters (repeat N #(putter)) ]
(.invokeAll executor putters)
(println (format "N: %d puts-done: %d" N #puts-done))
(assert (= N #puts-done)
(format "should have put in puts-done items; N = %d puts-done = %d" N #puts-done))))
result:
N: 100 puts-done: 100
Update #1
Regarding the cause, I'm not sure. I tried to fix the original version with locking, but no joy:
(def lock-obj (Object.))
(dotest
(let [N 100
puts-done (atom 0)
thread-count 10
executor (Executors/newFixedThreadPool thread-count)
abq (proxy [ArrayBlockingQueue]
[(+ 3 N)]
(put [el]
(locking lock-obj
(proxy-super put el)
(swap! puts-done inc))))]
(.invokeAll executor (repeat N #(.put abq 0)))
with results:
N: 100 puts-done: 46
N: 100 puts-done: 71
N: 100 puts-done: 85
N: 100 puts-done: 83
Update #2
Tried some more tests using a java subclass of ABQ:
package demo;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class Que<E> extends ArrayBlockingQueue<E> {
public static AtomicInteger numPuts = new AtomicInteger(0);
public static Que<Integer> queInt = new Que<>( 999 );
public Que(int size) { super(size); }
public void put(E element) {
synchronized (numPuts) {
try {
super.put(element);
numPuts.getAndIncrement();
} catch (Exception ex) {
System.out.println( "caught " + ex);
} } } }
...
(:import [java.util.concurrent Executors TimeUnit]
[demo Que] ) )
(dotest
(let [N 100
puts-done (atom 0)
thread-count 10
executor (Executors/newFixedThreadPool thread-count) ]
(.invokeAll executor (repeat N #(.put Que/queInt 0)))
(println (format "N: %d puts-done: %d" N (.get Que/numPuts)))))
results (repeated runs => accumulation):
N: 100 puts-done: 100
N: 100 puts-done: 200
N: 100 puts-done: 300
N: 100 puts-done: 400
N: 100 puts-done: 500
so it works great with a Java subclass. Get same results with/without the synchronized block.
So, it looks to be something in the Clojure proxy area.

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.

The more threads that changes the Clojure's ref are, the more does the rate of retries per threads rise?

I worry about this a little.
Imagine the simplest version controll way that programmers just copy all directory from the master repository and after changing a file do reversely if the master repository is still the same. If it has been changed by another, they must try again.
When the number of programmers increases, it is natural that retries also increase, but it might not be proportional to the number of programmers.
If ten programmers work and a work takes an hour per person, to complete all work ten hours are needed at least.
If they are earnest, about 9 + 8 + 7 + ... 1 = 45 man-hours come to nothing.
In a hundread of programmers, about 99 + 98 + ... 1 = 4950 man-hours come to nothing.
I tried to count the number of retries and got the results.
Source
(defn fib [n]
(if (or (zero? n) (= n 1))
1
(+ (fib (dec n) ) (fib (- n 2)))))
(defn calc! [r counter-A counter-B counter-C n]
(dosync
(swap! counter-A inc)
;;(Thread/sleep n)
(fib n)
(swap! counter-B inc)
(alter r inc)
(swap! counter-C inc)))
(defn main [thread-num n]
(let [r (ref 0)
counter-A (atom 0)
counter-B (atom 0)
counter-C (atom 0)]
(doall (pmap deref
(for [_ (take thread-num (repeat nil))]
(future (calc! r counter-A counter-B counter-C n)))))
(println thread-num " Thread. #ref:" #r)
(println "A:" #counter-A ", B:" #counter-B ", C:" #counter-C)))
CPU: 2.93GHz Quad-Core Intel Core i7
result
user> (time (main 10 25))
10 Thread. #ref: 10
A: 53 , B: 53 , C: 10
"Elapsed time: 94.412 msecs"
nil
user> (time (main 100 25))
100 Thread. #ref: 100
A: 545 , B: 545 , C: 100
"Elapsed time: 966.141 msecs"
nil
user> (time (main 1000 25))
1000 Thread. #ref: 1000
A: 5507 , B: 5507 , C: 1000
"Elapsed time: 9555.165 msecs"
nil
I changed the job to (Thread/sleep n) instead of (fib n) and got similar results.
user> (time (main 10 20))
10 Thread. #ref: 10
A: 55 , B: 55 , C: 10
"Elapsed time: 220.616 msecs"
nil
user> (time (main 100 20))
100 Thread. #ref: 100
A: 689 , B: 689 , C: 117
"Elapsed time: 2013.729 msecs"
nil
user> (time (main 1000 20))
1000 Thread. #ref: 1000
A: 6911 , B: 6911 , C: 1127
"Elapsed time: 20243.214 msecs"
nil
In Thread/sleep case, I think retries could increase more than this result because CPU is available.
Why don't retries increase?
Thanks.
Because you are not actually spawning 10, 100 or 1000 threads! Creating a future does not always create a new thread. It uses a thread pool behind the scenes where it keeps queuing the jobs (or Runnables to be technical). The thread pool is a cached thread pool which reuses the threads for running the jobs.
So in your case, you are not actually spawning a 1000 threads. If you want to see the retries in action, get a level below future - create your own thread pool and push Runnables into it.
self answer
I have modified main function not to use pmap and got results, which work out as calculated.
(defn main [thread-num n]
(let [r (ref 0)
counter-A (atom 0)
counter-B (atom 0)
counter-C (atom 0)]
(doall (map deref (doall (for [_ (take thread-num (repeat nil))]
(future (calc! r counter-A counter-B counter-C n))))))
(println thread-num " Thread. #ref:" #r)
(println "A:" #counter-A ", B:" #counter-B ", C:" #counter-C)))
fib
user=> (main 10 25)
10 Thread. #ref: 10
A: 55 , B: 55 , C: 10
nil
user=> (main 100 25)
100 Thread. #ref: 100
A: 1213 , B: 1213 , C: 100
nil
user=> (main 1000 25)
1000 Thread. #ref: 1000
A: 19992 , B: 19992 , C: 1001
nil
Thread/sleep
user=> (main 10 20)
10 Thread. #ref: 10
A: 55 , B: 55 , C: 10
nil
user=> (main 100 20)
100 Thread. #ref: 100
A: 4979 , B: 4979 , C: 102
nil
user=> (main 1000 20)
1000 Thread. #ref: 1000
A: 491223 , B: 491223 , C: 1008
nil

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))

Resources