Overture Tool

Formal Modelling in VDM

Overture Tool

Go to our GitHub Profile

Follow @overturetool

PlannerSL

Author: T.L. McCluskey and Pat Diskin

The specification is of the input language, and the central operations, of a domain-independent, partial order, constraint posting goal directed planner. It is essentially a model-based version of Chapman’s TWEAK (1), and is used as a case study on VDM courses at the Univ. of Huddersfield. It is described fully, and prototyped in Prolog, in (2).

Planning for Conjunctive Goals, D.Chapman, AI Journal no 32, 1987.

The Construction of Formal Specifications: an Introduction to the Model-Based and Algebraic Approaches, J.Turner and McCluskey, McGraw-Hill Software Engineering Series, London. ISBN 0-07-707735-0.

Properties Values
Language Version: classic

planner.vdmsl

types

    Literal = seq of token; 
    State = set of Literal;
    Goal = set of Literal;
    Action :: name : Literal
        pra  : set of Literal
        add  : set of Literal
        del  : set of Literal;

    Planning_Problem :: AS : set of Action
                  I : State
                  G : Goal

    inv  mk_Planning_Problem ( AS, I, G) ==
    forall l in set G &
         (l in set I or 
        exists A in set AS & l in set
         A.add)
    and                                              
    not (G subset I) and
    forall A in set AS & not (exists p : Literal & p in set A.add and
        p in set A.del); 

Action_id = token;
Action_instances = map Action_id to Action;

Arc ::
      source    : Action_id
          dest      : Action_id;

Bounded_Poset = set of Arc
inv  p ==
    forall x, y in set get_nodes(p) & 
    not (before(x, y, p) and before(y, x, p)) and
    x <> mk_token("pinit") => before(mk_token("pinit"), x, p) and 
    x <> mk_token("goal") => before(x, mk_token("goal"), p);

 Goal_instance :: 
           gl : Literal
           ai : Action_id;

Goal_instances = set of Goal_instance

state Partial_Plan of
    pp: Planning_Problem
    Os: Action_instances
    Ts: Bounded_Poset
    Ps: Goal_instances
    As: Goal_instances
inv  mk_Partial_Plan(pp, Os, Ts, Ps, As)== 
    (Os(mk_token("pinit")) = mk_Action([mk_token("pinit")], { }, pp.I, { })) and
    (Os(mk_token("goal")) = mk_Action([mk_token("goal")], pp.G, { }, { })) and
    rng Os subset pp.AS union {Os(mk_token("pinit")), Os(mk_token("goal"))} and
    dom Os = get_nodes(Ts) and
    As inter Ps = {} and
    forall A in set dom Os & (forall p in set Os(A).pra &  
            mk_Goal_instance(p, A) in set (Ps union As)) and
    forall gi in set As & exists A in set dom Os & achieve(Os, Ts, A, gi)
end

functions

get_nodes : set of Arc -> set of Action_id
get_nodes(p) ==
    {a.source | a in set p} union {a.dest | a in set p};

before : Action_id * Action_id * set of Arc -> bool 
before(x, z, p) ==
    mk_Arc(x, z) in set p or
    exists y in set get_nodes(p) & before(x, y, p) and before(y, z, p);

possibly_before : Action_id * Action_id * set of Arc -> bool 
possibly_before(x, z, p) ==
    x <> z and not before(z, x, p);

completion_of : Bounded_Poset * Bounded_Poset -> bool 
completion_of(p, q) ==
    (forall x, y in set get_nodes(p) & before(x, y, q) and before(x, y, p));

initposet: () -> Bounded_Poset
initposet() ==
    {mk_Arc(mk_token("pinit"), mk_token("goal"))};

add_node : Action_id * Bounded_Poset -> Bounded_Poset
add_node(u, p) ==
    p union {mk_Arc(mk_token("pinit"), u), mk_Arc(u, mk_token("goal"))};

make_before : Action_id * Action_id * Bounded_Poset -> Bounded_Poset
make_before(u, v, p) ==
    if possibly_before(u, v, p) and {u, v} subset get_nodes(p)
    then p union {mk_Arc(u, v)} else p;


newid(isa : set of Action_id) i: Action_id 
post i not in set isa;

achieve : Action_instances * Bounded_Poset * Action_id * Goal_instance -> bool 
achieve(Os, Ts, A, mk_Goal_instance(p, O)) ==
    before(A, O, Ts) and
    p in set Os(A).add and
    not (exists C in set dom Os & 
    possibly_before(C, O, Ts) and 
    possibly_before(A, C, Ts) and
    p in set Os(C).del); 

declobber:Action_instances * Bounded_Poset * Action_id * Goal_instance -> bool 
declobber(Os, Ts, NewA, mk_Goal_instance(q, C)) ==
    before(C, NewA, Ts) or
    not(q in set Os(NewA).del) or
    exists W in set dom Os & 
    (before(NewA, W, Ts) and
    before(W, C, Ts) and
    q in set Os(W).add)

operations

INIT (ppi : Planning_Problem)
ext wr pp : Planning_Problem
    wr Os : Action_instances
    wr Ts : Bounded_Poset
    wr Ps : Goal_instances
    wr As : Goal_instances
post    pp = ppi and
    Os =  {mk_token("pinit") |->  mk_Action([mk_token("pinit")], { }, 
            ppi.I, { }), 
             mk_token("goal") |->
                 mk_Action([mk_token ("goal")], ppi.G, { }, { })} and
    Ts = initposet( ) and
    Ps = {mk_Goal_instance(g, mk_token("goal")) | g in set ppi.G} and
    As = { };


ACHIEVE_1(gi : Goal_instance)
ext rd Os : Action_instances
    wr Ts : Bounded_Poset
    wr Ps : Goal_instances
    wr As : Goal_instances
pre gi in set Ps
post    exists A in set dom Os & achieve(Os, Ts, A, gi) and
    completion_of (Ts, Ts~) and 
    Ps = Ps~ \{gi} and 
    As = As~ union {gi};


ACHIEVE_2(gi: Goal_instance)
ext rd pp : Planning_Problem
    wr Os : Action_instances
    wr Ts : Bounded_Poset
    wr Ps : Goal_instances
    wr As : Goal_instances
pre gi in set Ps
post    let NewA = newid(dom Os~) in
    exists A in set pp.AS & Os = Os~ ++ {NewA |-> A} and
    achieve(Os, Ts, NewA, gi) and
    forall gj in set As~ & declobber(Os, Ts, NewA, gj) and
    completion_of(Ts, add_node(NewA, Ts~)) and 
    Ps = (Ps~ \ {gi}) union {mk_Goal_instance(p, NewA) | p in set A.pra} and
    As = As~ union {gi}