Skip to content

Commit

Permalink
Add get_dependencies(expr) to RDDL class
Browse files Browse the repository at this point in the history
Signed-off-by: Thiago P. Bueno <thiago.pbueno@gmail.com>
  • Loading branch information
thiagopbueno committed Dec 11, 2019
1 parent d40a7e9 commit bde0513
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 178 deletions.
4 changes: 2 additions & 2 deletions pyrddl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = '0.1.9'
__release__ = 'v0.1.9-alpha'
__version__ = '0.1.10'
__release__ = 'v0.1.10-alpha'
18 changes: 18 additions & 0 deletions pyrddl/rddl.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,3 +283,21 @@ def _param_types_to_shape(self, param_types: Optional[str]) -> Sequence[int]:
param_types = [] if param_types is None else param_types
shape = tuple(self.object_table[ptype]['size'] for ptype in param_types)
return shape

def get_dependencies(self, expr):
deps = set()

expressions = [expr]
while expressions:
expr = expressions.pop()

for name in expr.scope:
fluent, _ = self.fluent_table[name]

if fluent.is_intermediate_fluent():
cpf = self.domain.get_intermediate_cpf(name)
expressions.append(cpf.expr)
else:
deps.add(fluent)

return deps
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def read(filename):
author_email='thiago.pbueno@gmail.com',
description='RDDL lexer/parser in Python3.',
long_description=read('README.md'),
long_description_content_type='text/markdown',
license='GNU General Public License v3.0',
keywords=['rddl', 'parser', 'mdp', 'dbn'],
url='https://github.com/thiagopbueno/pyrddl',
Expand All @@ -38,4 +39,4 @@ def read(filename):
'Programming Language :: Python :: 3',
'Topic :: Scientific/Engineering :: Artificial Intelligence'
],
)
)
242 changes: 67 additions & 175 deletions tests/test_rddl.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,178 +14,70 @@
# along with pyrddl. If not, see <http://www.gnu.org/licenses/>.


from pyrddl.parser import RDDLParser
from pyrddl.pvariable import PVariable

import unittest


class TestRDDL(unittest.TestCase):

@classmethod
def setUpClass(cls):
with open('rddl/Reservoir.rddl', mode='r') as file:
RESERVOIR = file.read()

with open('rddl/Mars_Rover.rddl', mode='r') as file:
MARS_ROVER = file.read()

parser = RDDLParser()
parser.build()

cls.rddl1 = parser.parse(RESERVOIR)
cls.rddl1.build()
cls.rddl2 = parser.parse(MARS_ROVER)
cls.rddl2.build()
cls.rddls = [cls.rddl1, cls.rddl2]

def test_build_object_table(self):
self.assertIn('res', self.rddl1.object_table)
size = self.rddl1.object_table['res']['size']
idx = self.rddl1.object_table['res']['idx']
self.assertEqual(size, 8)
objs = ['t1', 't2', 't3', 't4', 't5', 't6', 't7', 't8']
for i, obj in enumerate(objs):
self.assertIn(obj, idx)
self.assertEqual(idx[obj], i)

def test_build_fluent_table(self):
self.assertEqual(len(self.rddl1.fluent_table), 16)
for name, (fluent, size) in self.rddl1.fluent_table.items():
self.assertIsInstance(name, str)
self.assertIn(fluent.name, name)
self.assertIsInstance(fluent, PVariable)
self.assertIsInstance(size, tuple)
self.assertEqual(len(size), fluent.arity)

def test_state_fluent_variables(self):
rddls = [self.rddl1, self.rddl2]
fluent_variables = [
{
'rlevel/1': ['rlevel(t1)', 'rlevel(t2)', 'rlevel(t3)', 'rlevel(t4)', 'rlevel(t5)', 'rlevel(t6)', 'rlevel(t7)', 'rlevel(t8)']
},
{
'picTaken/1': ['picTaken(p1)', 'picTaken(p2)', 'picTaken(p3)'],
'time/0': ['time'],
'xPos/0': ['xPos'],
'yPos/0': ['yPos']
}
]
for rddl, expected_variables in zip(rddls, fluent_variables):
fluent_variables = rddl.state_fluent_variables
self.assertEqual(len(fluent_variables), len(expected_variables))
for name, actual_variables in fluent_variables:
self.assertIn(name, expected_variables)
self.assertListEqual(actual_variables, expected_variables[name])

def test_interm_fluent_variables(self):
rddls = [self.rddl1, self.rddl2]
fluent_variables = [
{
'evaporated/1': ['evaporated(t1)', 'evaporated(t2)', 'evaporated(t3)', 'evaporated(t4)', 'evaporated(t5)', 'evaporated(t6)', 'evaporated(t7)', 'evaporated(t8)'],
'rainfall/1': ['rainfall(t1)', 'rainfall(t2)', 'rainfall(t3)', 'rainfall(t4)', 'rainfall(t5)', 'rainfall(t6)', 'rainfall(t7)', 'rainfall(t8)'],
'overflow/1': ['overflow(t1)', 'overflow(t2)', 'overflow(t3)', 'overflow(t4)', 'overflow(t5)', 'overflow(t6)', 'overflow(t7)', 'overflow(t8)'],
'inflow/1': ['inflow(t1)', 'inflow(t2)', 'inflow(t3)', 'inflow(t4)', 'inflow(t5)', 'inflow(t6)', 'inflow(t7)', 'inflow(t8)']
},
{}
]
for rddl, expected_variables in zip(rddls, fluent_variables):
fluent_variables = rddl.interm_fluent_variables
self.assertEqual(len(fluent_variables), len(expected_variables))
for name, actual_variables in fluent_variables:
self.assertIn(name, expected_variables)
self.assertListEqual(actual_variables, expected_variables[name])

def test_action_fluent_variables(self):
rddls = [self.rddl1, self.rddl2]
fluent_variables = [
{
'outflow/1': ['outflow(t1)', 'outflow(t2)', 'outflow(t3)', 'outflow(t4)', 'outflow(t5)', 'outflow(t6)', 'outflow(t7)', 'outflow(t8)']
},
{
'snapPicture/0': ['snapPicture'],
'xMove/0': ['xMove'],
'yMove/0': ['yMove']
}
]
for rddl, expected_variables in zip(rddls, fluent_variables):
fluent_variables = rddl.action_fluent_variables
self.assertEqual(len(fluent_variables), len(expected_variables))
for name, actual_variables in fluent_variables:
self.assertIn(name, expected_variables)
self.assertListEqual(actual_variables, expected_variables[name])

def test_state_size(self):
rddls = [self.rddl1, self.rddl2]
for i, rddl in enumerate(rddls):
state_size = rddl.state_size
self.assertIsInstance(state_size, tuple)
for shape in state_size:
self.assertIsInstance(shape, tuple)

state_fluent_ordering = rddl.domain.state_fluent_ordering
next_state_fluent_ordering = rddl.domain.next_state_fluent_ordering
self.assertEqual(len(state_size), len(state_fluent_ordering))
self.assertEqual(len(state_size), len(next_state_fluent_ordering))

def test_action_size(self):
rddls = [self.rddl1, self.rddl2]
for rddl in rddls:
action_size = rddl.action_size
action_fluent_ordering = rddl.domain.action_fluent_ordering
self.assertIsInstance(action_size, tuple)
self.assertEqual(len(action_size), len(action_fluent_ordering))
for shape in action_size:
self.assertIsInstance(shape, tuple)

def test_interm_size(self):
rddls = [self.rddl1, self.rddl2]
for rddl in rddls:
interm_size = rddl.interm_size
interm_ordering = rddl.domain.interm_fluent_ordering
self.assertIsInstance(interm_size, tuple)
self.assertEqual(len(interm_size), len(interm_ordering))
for shape in interm_size:
self.assertIsInstance(shape, tuple)

def test_state_range_type(self):
rddls = [self.rddl1, self.rddl2]
for rddl in rddls:
state_range_type = rddl.state_range_type
state_fluents = rddl.domain.state_fluents
state_fluent_ordering = rddl.domain.state_fluent_ordering
self.assertIsInstance(state_range_type, tuple)
self.assertEqual(len(state_range_type), len(state_fluents))
self.assertEqual(len(state_range_type), len(state_fluent_ordering))
for name, range_type in zip(state_fluent_ordering, state_range_type):
fluent = state_fluents[name]
self.assertIsInstance(range_type, str)
self.assertEqual(range_type, fluent.range)

def test_interm_range_type(self):
rddls = [self.rddl1, self.rddl2]
for rddl in rddls:
interm_range_type = rddl.interm_range_type
interm_fluents = rddl.domain.intermediate_fluents
interm_fluent_ordering = rddl.domain.interm_fluent_ordering
self.assertIsInstance(interm_range_type, tuple)
self.assertEqual(len(interm_range_type), len(interm_fluents))
self.assertEqual(len(interm_range_type), len(interm_fluent_ordering))
for name, range_type in zip(interm_fluent_ordering, interm_range_type):
fluent = interm_fluents[name]
self.assertIsInstance(range_type, str)
self.assertEqual(range_type, fluent.range)

def test_action_range_type(self):
rddls = [self.rddl1, self.rddl2]
for rddl in rddls:
action_range_type = rddl.action_range_type
action_fluents = rddl.domain.action_fluents
action_fluent_ordering = rddl.domain.action_fluent_ordering
self.assertIsInstance(action_range_type, tuple)
self.assertEqual(len(action_range_type), len(action_fluents))
self.assertEqual(len(action_range_type), len(action_fluent_ordering))
for name, range_type in zip(action_fluent_ordering, action_range_type):
fluent = action_fluents[name]
self.assertIsInstance(range_type, str)
self.assertEqual(range_type, fluent.range)
import pytest

import rddlgym

from pyrddl.expr import Expression
from pyrddl.rddl import RDDL


@pytest.fixture(scope='module', params=['Reservoir-8', 'HVAC-3', 'Navigation-v3'])
def rddl(request):
yield rddlgym.make(request.param, mode=rddlgym.AST)


def test_build_object_table(rddl):
assert rddl.object_table is not None


def test_build_fluent_table(rddl):
assert rddl.fluent_table is not None


def test_get_dependencies(rddl):

if rddl.domain.name == 'reservoir':
shape = Expression(('pvar_expr', ('RAIN_SHAPE', ['?res'])))
scale = Expression(('pvar_expr', ('RAIN_SCALE', ['?res'])))
gamma = Expression(('randomvar', ('Gamma', (shape, scale))))

deps = rddl.get_dependencies(gamma)
assert isinstance(deps, set)
assert len(deps) == 2
deps = set(map(lambda fluent: str(fluent), deps))
assert deps == {'RAIN_SCALE/1', 'RAIN_SHAPE/1'}

elif rddl.domain.name == 'hvac_vav_fix':
mean = Expression(('pvar_expr', ('TEMP_OUTSIDE_MEAN', ['?s'])))
variance = Expression(('pvar_expr', ('TEMP_OUTSIDE_VARIANCE', ['?s'])))
normal = Expression(('randomvar', ('Normal', (mean, variance))))

deps = rddl.get_dependencies(normal)
assert isinstance(deps, set)
assert len(deps) == 2
deps = set(map(lambda fluent: str(fluent), deps))
assert deps == {'TEMP_OUTSIDE_MEAN/1', 'TEMP_OUTSIDE_VARIANCE/1'}

elif rddl.domain.name == 'Navigation':
location = Expression(('pvar_expr', ('location', ['?l'])))
move = Expression(('pvar_expr', ('move', ['?l'])))
deceleration = Expression(
('prod', (
('typed_var', ('?z', 'zone')),
Expression(('pvar_expr', ('deceleration', ['?z']))))))

mean = Expression(('+', (location, Expression(('*', (deceleration, move))))))
variance = Expression(('*',
(Expression(('pvar_expr', ('MOVE_VARIANCE_MULT', ['?l']))), move)))
normal = Expression(('randomvar', ('Normal', (mean, variance))))

deps = rddl.get_dependencies(normal)
assert isinstance(deps, set)
assert len(deps) == 5
deps = set(map(lambda fluent: str(fluent), deps))
assert deps == {
'location/1', 'move/1',
'DECELERATION_ZONE_CENTER/2', 'DECELERATION_ZONE_DECAY/1',
'MOVE_VARIANCE_MULT/1'
}
Loading

0 comments on commit bde0513

Please sign in to comment.