Grounding a problem in pyRDDLGym.#
This rudimentary example shows how to ground a domain and instance from lifted form.
First install and import the required packages:
%pip install --quiet --upgrade pip
%pip install --quiet git+https://github.com/pyrddlgym-project/pyRDDLGym.git
%pip install --quiet git+https://github.com/pyrddlgym-project/rddlrepository.git
Note: you may need to restart the kernel to use updated packages.
Note: you may need to restart the kernel to use updated packages.
Note: you may need to restart the kernel to use updated packages.
Import the required packages:
import pyRDDLGym
from pyRDDLGym.core.debug.decompiler import RDDLDecompiler
from pyRDDLGym.core.grounder import RDDLGrounder
We will use the Wildfire domain, instance 1, to illustrate how grounding works:
env = pyRDDLGym.make('Wildfire_MDP_ippc2014', '1')
Let’s take a look at the state-fluents and the conditional probability functions for them:
for fluent, expr in RDDLDecompiler().decompile_exprs(env.model)['cpfs'].items():
print(f'state-fluent {fluent} has the following cpf:')
print(expr)
print()
state-fluent burning' has the following cpf:
if (put-out(?x, ?y))
then false
else ( if (( ~out-of-fuel(?x, ?y) ) ^ ( ~burning(?x, ?y) ))
then ( if (TARGET(?x, ?y) ^ ( ~( exists_{?x2: x_pos, ?y2: y_pos} [ NEIGHBOR(?x, ?y, ?x2, ?y2) ^ burning(?x2, ?y2) ] ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( sum_{?x2: x_pos, ?y2: y_pos} [ NEIGHBOR(?x, ?y, ?x2, ?y2) ^ burning(?x2, ?y2) ] )] )) )
else burning(?x, ?y) )
state-fluent out-of-fuel' has the following cpf:
( out-of-fuel(?x, ?y) | burning(?x, ?y) ) | ( ( ~TARGET(?x, ?y) ) ^ cut-out(?x, ?y) )
There are two state fluent variables with parameterized expressions. The purpose of grounding is separate out this expression into a set of expressions, one per parameter evaluation, that is parameter-free. To do this, we will instantiate and call the grounder on the domain as follows:
grounded_model = RDDLGrounder(env.model.ast).ground()
Let’s decompile the new conditional probability functions and check that they are free of parameters:
for fluent, expr in RDDLDecompiler().decompile_exprs(grounded_model)['cpfs'].items():
print(f'state-fluent {fluent} has the following cpf:')
print(expr)
print()
state-fluent burning___x1__y1' has the following cpf:
if (put-out___x1__y1)
then false
else ( if (( ~out-of-fuel___x1__y1 ) ^ ( ~burning___x1__y1 ))
then ( if (TARGET___x1__y1 ^ ( ~( ( NEIGHBOR___x1__y1__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x1__y1__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x1__y1__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x1__y1__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x1__y1__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x1__y1__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x1__y1__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x1__y1__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x1__y1__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x1__y1__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x1__y1__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x1__y1__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x1__y1__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x1__y1__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x1__y1__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x1__y1__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x1__y1__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x1__y1__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x1__y1 )
state-fluent burning___x1__y2' has the following cpf:
if (put-out___x1__y2)
then false
else ( if (( ~out-of-fuel___x1__y2 ) ^ ( ~burning___x1__y2 ))
then ( if (TARGET___x1__y2 ^ ( ~( ( NEIGHBOR___x1__y2__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x1__y2__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x1__y2__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x1__y2__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x1__y2__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x1__y2__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x1__y2__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x1__y2__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x1__y2__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x1__y2__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x1__y2__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x1__y2__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x1__y2__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x1__y2__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x1__y2__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x1__y2__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x1__y2__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x1__y2__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x1__y2 )
state-fluent burning___x1__y3' has the following cpf:
if (put-out___x1__y3)
then false
else ( if (( ~out-of-fuel___x1__y3 ) ^ ( ~burning___x1__y3 ))
then ( if (TARGET___x1__y3 ^ ( ~( ( NEIGHBOR___x1__y3__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x1__y3__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x1__y3__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x1__y3__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x1__y3__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x1__y3__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x1__y3__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x1__y3__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x1__y3__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x1__y3__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x1__y3__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x1__y3__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x1__y3__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x1__y3__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x1__y3__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x1__y3__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x1__y3__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x1__y3__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x1__y3 )
state-fluent burning___x2__y1' has the following cpf:
if (put-out___x2__y1)
then false
else ( if (( ~out-of-fuel___x2__y1 ) ^ ( ~burning___x2__y1 ))
then ( if (TARGET___x2__y1 ^ ( ~( ( NEIGHBOR___x2__y1__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x2__y1__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x2__y1__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x2__y1__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x2__y1__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x2__y1__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x2__y1__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x2__y1__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x2__y1__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x2__y1__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x2__y1__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x2__y1__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x2__y1__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x2__y1__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x2__y1__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x2__y1__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x2__y1__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x2__y1__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x2__y1 )
state-fluent burning___x2__y2' has the following cpf:
if (put-out___x2__y2)
then false
else ( if (( ~out-of-fuel___x2__y2 ) ^ ( ~burning___x2__y2 ))
then ( if (TARGET___x2__y2 ^ ( ~( ( NEIGHBOR___x2__y2__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x2__y2__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x2__y2__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x2__y2__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x2__y2__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x2__y2__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x2__y2__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x2__y2__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x2__y2__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x2__y2__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x2__y2__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x2__y2__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x2__y2__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x2__y2__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x2__y2__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x2__y2__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x2__y2__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x2__y2__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x2__y2 )
state-fluent burning___x2__y3' has the following cpf:
if (put-out___x2__y3)
then false
else ( if (( ~out-of-fuel___x2__y3 ) ^ ( ~burning___x2__y3 ))
then ( if (TARGET___x2__y3 ^ ( ~( ( NEIGHBOR___x2__y3__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x2__y3__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x2__y3__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x2__y3__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x2__y3__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x2__y3__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x2__y3__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x2__y3__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x2__y3__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x2__y3__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x2__y3__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x2__y3__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x2__y3__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x2__y3__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x2__y3__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x2__y3__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x2__y3__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x2__y3__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x2__y3 )
state-fluent burning___x3__y1' has the following cpf:
if (put-out___x3__y1)
then false
else ( if (( ~out-of-fuel___x3__y1 ) ^ ( ~burning___x3__y1 ))
then ( if (TARGET___x3__y1 ^ ( ~( ( NEIGHBOR___x3__y1__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x3__y1__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x3__y1__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x3__y1__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x3__y1__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x3__y1__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x3__y1__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x3__y1__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x3__y1__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x3__y1__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x3__y1__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x3__y1__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x3__y1__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x3__y1__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x3__y1__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x3__y1__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x3__y1__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x3__y1__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x3__y1 )
state-fluent burning___x3__y2' has the following cpf:
if (put-out___x3__y2)
then false
else ( if (( ~out-of-fuel___x3__y2 ) ^ ( ~burning___x3__y2 ))
then ( if (TARGET___x3__y2 ^ ( ~( ( NEIGHBOR___x3__y2__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x3__y2__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x3__y2__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x3__y2__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x3__y2__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x3__y2__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x3__y2__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x3__y2__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x3__y2__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x3__y2__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x3__y2__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x3__y2__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x3__y2__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x3__y2__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x3__y2__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x3__y2__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x3__y2__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x3__y2__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x3__y2 )
state-fluent burning___x3__y3' has the following cpf:
if (put-out___x3__y3)
then false
else ( if (( ~out-of-fuel___x3__y3 ) ^ ( ~burning___x3__y3 ))
then ( if (TARGET___x3__y3 ^ ( ~( ( NEIGHBOR___x3__y3__x1__y1 ^ burning___x1__y1 ) | ( NEIGHBOR___x3__y3__x1__y2 ^ burning___x1__y2 ) | ( NEIGHBOR___x3__y3__x1__y3 ^ burning___x1__y3 ) | ( NEIGHBOR___x3__y3__x2__y1 ^ burning___x2__y1 ) | ( NEIGHBOR___x3__y3__x2__y2 ^ burning___x2__y2 ) | ( NEIGHBOR___x3__y3__x2__y3 ^ burning___x2__y3 ) | ( NEIGHBOR___x3__y3__x3__y1 ^ burning___x3__y1 ) | ( NEIGHBOR___x3__y3__x3__y2 ^ burning___x3__y2 ) | ( NEIGHBOR___x3__y3__x3__y3 ^ burning___x3__y3 ) ) ))
then false
else Bernoulli(1.0 / ( 1.0 + exp[4.5 - ( ( NEIGHBOR___x3__y3__x1__y1 ^ burning___x1__y1 ) + ( NEIGHBOR___x3__y3__x1__y2 ^ burning___x1__y2 ) + ( NEIGHBOR___x3__y3__x1__y3 ^ burning___x1__y3 ) + ( NEIGHBOR___x3__y3__x2__y1 ^ burning___x2__y1 ) + ( NEIGHBOR___x3__y3__x2__y2 ^ burning___x2__y2 ) + ( NEIGHBOR___x3__y3__x2__y3 ^ burning___x2__y3 ) + ( NEIGHBOR___x3__y3__x3__y1 ^ burning___x3__y1 ) + ( NEIGHBOR___x3__y3__x3__y2 ^ burning___x3__y2 ) + ( NEIGHBOR___x3__y3__x3__y3 ^ burning___x3__y3 ) )] )) )
else burning___x3__y3 )
state-fluent out-of-fuel___x1__y1' has the following cpf:
( out-of-fuel___x1__y1 | burning___x1__y1 ) | ( ( ~TARGET___x1__y1 ) ^ cut-out___x1__y1 )
state-fluent out-of-fuel___x1__y2' has the following cpf:
( out-of-fuel___x1__y2 | burning___x1__y2 ) | ( ( ~TARGET___x1__y2 ) ^ cut-out___x1__y2 )
state-fluent out-of-fuel___x1__y3' has the following cpf:
( out-of-fuel___x1__y3 | burning___x1__y3 ) | ( ( ~TARGET___x1__y3 ) ^ cut-out___x1__y3 )
state-fluent out-of-fuel___x2__y1' has the following cpf:
( out-of-fuel___x2__y1 | burning___x2__y1 ) | ( ( ~TARGET___x2__y1 ) ^ cut-out___x2__y1 )
state-fluent out-of-fuel___x2__y2' has the following cpf:
( out-of-fuel___x2__y2 | burning___x2__y2 ) | ( ( ~TARGET___x2__y2 ) ^ cut-out___x2__y2 )
state-fluent out-of-fuel___x2__y3' has the following cpf:
( out-of-fuel___x2__y3 | burning___x2__y3 ) | ( ( ~TARGET___x2__y3 ) ^ cut-out___x2__y3 )
state-fluent out-of-fuel___x3__y1' has the following cpf:
( out-of-fuel___x3__y1 | burning___x3__y1 ) | ( ( ~TARGET___x3__y1 ) ^ cut-out___x3__y1 )
state-fluent out-of-fuel___x3__y2' has the following cpf:
( out-of-fuel___x3__y2 | burning___x3__y2 ) | ( ( ~TARGET___x3__y2 ) ^ cut-out___x3__y2 )
state-fluent out-of-fuel___x3__y3' has the following cpf:
( out-of-fuel___x3__y3 | burning___x3__y3 ) | ( ( ~TARGET___x3__y3 ) ^ cut-out___x3__y3 )
As you can see, all state-fluents with parameters have been replaced by new state-fluents without parameters, and expressions are replaced with equivalent operations that are parameter-free.