Loading a problem from the rddlrepository.

Loading a problem from the rddlrepository.#

This basic example illustrates how to load a problem from the rddlrepository.

First install and import the required packages:

%pip install --quiet --upgrade pip
%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.

Import the required packages:

from rddlrepository.core.manager import RDDLRepoManager

Listing available contexts, domains and instances.#

Problems in rddlrepository are grouped into contexts:

manager = RDDLRepoManager(rebuild=True)
manager.list_contexts()
['arcade',
 'ippc2011',
 'ippc2014',
 'ippc2018',
 'ippc2023',
 'gym',
 'mycontext',
 'or',
 'rddlsim',
 'standalone']

As you can infer from the names, contexts of the form ippcxxxx refer to domains in prior years’ international planning competitions, gym refers to RDDL implementations of domains from the original OpenAI gym, and so on.

To list all the domains in a given context, e.g. ippc2014:

manager.list_problems_by_context('ippc2014')
['AcademicAdvising_MDP_ippc2014',
 'AcademicAdvising_POMDP_ippc2014',
 'CrossingTraffic_MDP_ippc2014',
 'CrossingTraffic_POMDP_ippc2014',
 'Elevators_MDP_ippc2014',
 'Elevators_POMDP_ippc2014',
 'SkillTeaching_MDP_ippc2014',
 'SkillTeaching_POMDP_ippc2014',
 'Tamarisk_MDP_ippc2014',
 'Tamarisk_POMDP_ippc2014',
 'Traffic_MDP_ippc2014',
 'Traffic_POMDP_ippc2014',
 'TriangleTireworld_MDP_ippc2014',
 'TriangleTireworld_POMDP_ippc2014',
 'Wildfire_MDP_ippc2014',
 'Wildfire_POMDP_ippc2014']

To list all the instances in a given domain, e.g. Wildfire_MDP_ippc2014:

info = manager.get_problem('Wildfire_MDP_ippc2014')
info.list_instances()
['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

As you can see, there are 10 instances available for the Wildfire domain, ranging from 1 to 10.

Loading domains and instances.#

Now that you understand how to extract information about domains and instances, let’s load the actual domain and instance RDDL specification, as well as the default visualizer object assigned to the domain:

print(info.get_domain())
print(info.get_instance('1'))
print(info.get_visualizer())
C:\Python\lib\site-packages\rddlrepository\archive\competitions\IPPC2014\Wildfire\MDP\domain.rddl
C:\Python\lib\site-packages\rddlrepository\archive\competitions\IPPC2014\Wildfire\MDP\instance1.rddl
<class 'rddlrepository.archive.competitions.IPPC2014.Wildfire.MDP.WildfireViz.WildfireVisualizer'>

This provides the paths to the domain and instance RDDL files on the system, as well as the Visualizer instance that can be passed to the pyRDDLGym environment.

Finally, let’s inspect the content of the domain specification:

with open(info.get_domain()) as file:
    print(file.read())
///////////////////////////////////////////////////////////////////////////////
//
// A boolean version of the wildfire fighting domain.
//
// Author: Zhenyu Yu (fry3721@gmail.com)
//
// General reference:
// 
//   Karafyllidis, I., & Thanailakis, A. (1997). 
//   A model for predicting forest fire spreading using gridular automata. 
//   Ecological Modelling, 99(1), 87-97.
//   http://www.dpi.inpe.br/gilberto/cursos/st-society-2013/Kara1997.pdf
//
// In a general wildfire scenario, its spread is mostly determined by 
// the weather (i.e. wind), terrain slope, and fuel type (i.e. grass, wood).
// In this scenario, a map is represented with grids, size of n*n.
// Each grid has some attributes, including fuel type, terrain elevation.
// Furthermore, the fuel type and terrain elevation will affect the fire 
// spreading speed.  Some fuel type is more easily on fire than other, 
// and higher grids are always easier to catch fire.  Cell features and
// effects of wind are not modeled in this simplified version.
//
// In this version, whether a cell would be on fire is determined by its 
// neighbor grids, and the fire spreading law is simplified with this function
//
//   p(burning(xi, yj)=true) = 1 / (1 + exp(4.5 - k))
//
// where k is the number of neighbors on fire.
//
// The decision task to a emergency manager is to control the fire 
// and keep it away from important targets.
//
// Modified for competition and translation purposes by Scott Sanner.
//  
///////////////////////////////////////////////////////////////////////////////

domain wildfire_mdp {

	types {
		x_pos : object;
		y_pos : object;
	};
	
	pvariables {
	
		// Action costs and penalties
		COST_CUTOUT            : {non-fluent, real, default =   -5 }; // Cost to cut-out fuel from a cell
		COST_PUTOUT            : {non-fluent, real, default =  -10 }; // Cost to put-out a fire from a cell
		PENALTY_TARGET_BURN    : {non-fluent, real, default = -100 }; // Penalty for each target cell that is burning  
		PENALTY_NONTARGET_BURN : {non-fluent, real, default =   -5 }; // Penalty for each non-target cell that is burning
	
		// Topology of the cells (can be any neighborhood topology, not necessarily rectangular)
		NEIGHBOR(x_pos, y_pos, x_pos, y_pos) : { non-fluent, bool, default = false };
		
		// High value cells that should be protected from fire 
		TARGET(x_pos, y_pos) : {non-fluent, bool, default = false }; 
		
		// State fluents
		burning(x_pos, y_pos)     : { state-fluent, bool, default = false }; // cell currently on fire
		out-of-fuel(x_pos, y_pos) : { state-fluent, bool, default = false }; // cell does not have fuel to burn (i.e., cut-out or already burned)
		
		// Action fluents
		put-out(x_pos, y_pos) : { action-fluent, bool, default = false }; // actions to put-out out the fire
		cut-out(x_pos, y_pos) : { action-fluent, bool, default = false }; // cut-out out the fuel
			
	};

	cpfs {
		
		burning'(?x, ?y) = 
			if ( put-out(?x, ?y) ) // Intervention to put out fire?
				then false
            // Modification: targets can only start to burn if at least one neighbor is on fire
            else if (~out-of-fuel(?x, ?y) ^ ~burning(?x, ?y)) // Ignition of a new fire? Depends on neighbors.
              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 persists
		
		// Modification: only allow non-target cells to be cut-out (cannot remove fuel from targets, e.g., housing)
		out-of-fuel'(?x, ?y) = out-of-fuel(?x, ?y) | burning(?x,?y) | (~TARGET(?x, ?y) ^ cut-out(?x, ?y));
						
	};
    	
	reward = 
 	    [sum_{?x: x_pos, ?y: y_pos} [ COST_CUTOUT*cut-out(?x, ?y) ]]
 	  + [sum_{?x: x_pos, ?y: y_pos} [ COST_PUTOUT*put-out(?x, ?y) ]]
 	    // Modification: if a target is out-of-fuel, it was burnt so still penalize (since it could not have been cut-out)
 	  + [sum_{?x: x_pos, ?y: y_pos} [ PENALTY_TARGET_BURN*[ (burning(?x, ?y) | out-of-fuel(?x, ?y)) ^ TARGET(?x, ?y) ]]]
 	  + [sum_{?x: x_pos, ?y: y_pos} [ PENALTY_NONTARGET_BURN*[ burning(?x, ?y) ^ ~TARGET(?x, ?y) ]]];

}