Tutorial 3.5: Advanced Features in PDSketch#

Part 1: Using PyObjValueType#

PDSketch supports customized object types for object features. Meanwhile, they can also be inputs to functions and return values. Internally, they will be represented as integer values, indicating their index in executor.py_obj_store. However, this feature is very expensive, because it the py_obj_store needs to keep track of all intermediate values (no GC works for it). So we do not recommend using this feature for now.

[1]:
from typing import List

import concepts.dm.pdsketch as pds
[2]:
DOMAIN_STRING = """
(define (domain test)
    (:requirements :pdsketch-v3)
    (:types
        item - object
        pose - pyobject
        traj - pyobject
    )
    (:predicates
        (pose-of [return_type=pose] ?item - item)
        (traj-spose [return_type = pose] ?traj - traj)
        (traj-epose [return_type = pose] ?traj - traj)
    )

    (:action move
        :parameters (?item - item ?spose - pose ?epose - pose ?traj - traj)
        :precondition (and
            (equal (pose-of ?item) ?spose)
            (equal (traj-spose ?traj) ?spose)
            (equal (traj-epose ?traj) ?epose)
        )
        :effect (and
            (assign (pose-of ?item) ?epose)
        )
    )
)
"""
[3]:
class Pose(object):
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y

    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

    def __hash__(self):
        return hash((self.x, self.y))

    def __repr__(self):
        return 'Pose({}, {})'.format(self.x, self.y)


class Traj(object):
    def __init__(self, list_of_pose: List[Pose]):
        self.list_of_pose = list_of_pose

    @property
    def spose(self):
        return self.list_of_pose[0]

    @property
    def epose(self):
        return self.list_of_pose[-1]

    def __eq__(self, other):
        return (
            len(self.list_of_pose) == len(other.list_of_pose) and
            all([self.list_of_pose[i] == other.list_of_pose[i] for i in range(len(self.list_of_pose))])
        )

    def __hash__(self):
        return hash(tuple(self.list_of_pose))

    def __repr__(self):
        return 'Traj[{}]'.format(self.list_of_pose)


def pose_equal(p1, p2):
    return p1 == p2


def traj_spose(traj):
    return traj.spose


def traj_epose(traj):
    return traj.epose
[4]:
domain = pds.load_domain_string(DOMAIN_STRING)
executor = pds.PDSketchExecutor(domain)

executor.register_function('type::pose::equal', pose_equal)
executor.register_function('predicate::traj-spose', traj_spose)
executor.register_function('predicate::traj-epose', traj_epose)

state, ctx = executor.new_state({
    'a': domain.t_item,
    'b': domain.t_item,
}, create_context=True)
ctx.define_pyobj_feature('pose-of', [Pose(1, 1), Pose(2, 2)])

op: pds.Operator = domain.op_move
action = op('a', Pose(1, 1), Pose(2, 2), Traj([Pose(1, 1), Pose(2, 2)]))
succ, next_state = executor.apply(action, state)

print(state)
print(succ)
print(next_state)
State{
  states:
    - pose-of: Value[pose, axes=[?item], tdtype=pose, tdshape=(2,)]{TensorizedPyObjValues[pose, shape=(2,)]}
  objects: a - item, b - item
}
True
State{
  states:
    - pose-of: Value[pose, axes=[?item], tdtype=pose, tdshape=(2,)]{TensorizedPyObjValues[pose, shape=(2,)]}
  objects: a - item, b - item
}