# Path: retired/discrete/blocks_world/operators.py
# class Pick(Action):
#   def __init__(self, obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): ('table', False),
#       ('clear', obj): (True, None),
#       'holding': (False, obj),
#     })
# 
# class Place(Action):
#   def __init__(self, obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): (None, 'table'),
#       'holding': (obj, False),
#     })
# 
# class Stack(Action):
#   def __init__(self, obj, base_obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): (None, base_obj),
#       'holding': (obj, False),
#       ('clear', base_obj): (True, False),
#     })
# 
# class Unstack(Action):
#   def __init__(self, obj, base_obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): (base_obj, False),
#       ('clear', obj): (True, None),
#       'holding': (False, obj),
#       ('clear', base_obj): (None, True),
#     })
# 
# Path: retired/discrete/schedulers.py
# class InitDiscreteScheduler(Scheduler):
#   def __init__(self, rg, operators):
#     super(self.__class__, self).__init__(rg)
#     self.rg.goal.intermediates.update(self.rg.goal.connectors) # NOTE - marks as intermediates to prevent growing
#     connect_discrete_conditions(self.rg, self.rg.goal)
#     for operator in operators:
#       if not is_discrete_operator(operator):
#         raise RuntimeError(self.__class__.__name__ + ' passed non-discrete operator')
#       edge = self.rg.edge(operator)
#       edge.intermediates.update(edge.connectors)
#       connect_discrete_operator(self.rg, edge)
#   def __call__(self, start_vertex, goal_connector):
#     return []
# 
# Path: planner/states.py
# class State(Substate):
#   def __init__(self, values):
#     super(self.__class__, self).__init__({var: value for var, value in values.items() if value is not False})
#   def __getitem__(self, var):
#     if var not in self.__dict__[HASH_DICT]: return False
#     return self.__dict__[HASH_DICT][var]
#   def substate(self, variables):
#     return Substate({var: self[var] for var in variables})
#   def __call__(self, variables):
#     return self.substate(variables)
# 
# class Substate(DictPrintObject, Mapping):
#   def __init__(self, values):
#     HashObject.__init__(self)
#     self.__dict__[HASH_DICT] = values
#   def variables(self):
#     return set(self.__dict__[HASH_DICT].keys())
#   def includes(self, other):
#     return all(var in self and self[var] == other[var] for var in other.variables()) # TODO - test if state
#   def __getitem__(self, var):
#     return self.get(var)
#   def __iter__(self):
#     return self.__dict__[HASH_DICT].items()
#   def __len__(self):
#     return len(self.__dict__[HASH_DICT])
#   def __str__(self):
#     return 'SS' + str_args(self.__dict__[HASH_DICT])
# 
# class PartialState(SinglePrintObject):
#   #__slots__ = ('conditions',)
#   def __init__(self, conditions):
#     HashObject.__init__(self)
#     self.conditions = tuple(conditions)
#   def __contains__(self, state):
#     return all(state in condition for condition in self.conditions)
#   def __iter__(self):
#     for condition in self.conditions:
#       yield condition
#   def __len__(self):
#     return len(self.conditions)
# 
# Path: planner/conditions.py
# class SubstateCondition(Condition):
#   def __init__(self, substate):
#     super(self.__class__, self).__init__()
#     self.substate = substate
#     self.variables = frozenset(substate.variables())
#   def __contains__(self, substate):
#     return all(var in substate and substate[var] == value for var, value in self.substate)
#   def __str__(self):
#     return 'SC' + str_args(self.substate.__dict__['__hash_dict'])
#   __repr__ = __str__
# 
# Path: misc/functions.py
# def merge_dicts(*args):
#   result = {}
#   for d in args:
#     result.update(d)
#   return result
#   # return dict(reduce(operator.add, [d.items() for d in args]))


from .operators import Pick, Place, Stack, Unstack
from retired.discrete.schedulers import InitDiscreteScheduler
from planner.states import State, Substate, PartialState
from planner.conditions import SubstateCondition
from misc.functions import merge_dicts
from itertools import permutations

def restack(n=10, height=5):
  blocks = ['B%d'%i for i in range(1, n+1)]
  start = State(merge_dicts(
      {('on', blocks[0]): 'table', ('clear', blocks[height-1]): True},
      {('on', blocks[i+1]): blocks[i] for i in range(height-1)},
      {('on', blocks[i]): 'table' for i in range(height, n)},
      {('clear', blocks[i]): True for i in range(height, n)}
  ))

  goal = PartialState([
    SubstateCondition(Substate({('on', blocks[i]): blocks[i+1]})) for i in range(height-1)] + [

# Path: retired/discrete/blocks_world/operators.py
# class Pick(Action):
#   def __init__(self, obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): ('table', False),
#       ('clear', obj): (True, None),
#       'holding': (False, obj),
#     })
# 
# class Place(Action):
#   def __init__(self, obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): (None, 'table'),
#       'holding': (obj, False),
#     })
# 
# class Stack(Action):
#   def __init__(self, obj, base_obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): (None, base_obj),
#       'holding': (obj, False),
#       ('clear', base_obj): (True, False),
#     })
# 
# class Unstack(Action):
#   def __init__(self, obj, base_obj):
#     super(self.__class__, self).__init__(arg_info(currentframe()))
#     add_operator_transitions(self, {
#       ('on', obj): (base_obj, False),
#       ('clear', obj): (True, None),
#       'holding': (False, obj),
#       ('clear', base_obj): (None, True),
#     })
# 
# Path: retired/discrete/schedulers.py
# class InitDiscreteScheduler(Scheduler):
#   def __init__(self, rg, operators):
#     super(self.__class__, self).__init__(rg)
#     self.rg.goal.intermediates.update(self.rg.goal.connectors) # NOTE - marks as intermediates to prevent growing
#     connect_discrete_conditions(self.rg, self.rg.goal)
#     for operator in operators:
#       if not is_discrete_operator(operator):
#         raise RuntimeError(self.__class__.__name__ + ' passed non-discrete operator')
#       edge = self.rg.edge(operator)
#       edge.intermediates.update(edge.connectors)
#       connect_discrete_operator(self.rg, edge)
#   def __call__(self, start_vertex, goal_connector):
#     return []
# 
# Path: planner/states.py
# class State(Substate):
#   def __init__(self, values):
#     super(self.__class__, self).__init__({var: value for var, value in values.items() if value is not False})
#   def __getitem__(self, var):
#     if var not in self.__dict__[HASH_DICT]: return False
#     return self.__dict__[HASH_DICT][var]
#   def substate(self, variables):
#     return Substate({var: self[var] for var in variables})
#   def __call__(self, variables):
#     return self.substate(variables)
# 
# class Substate(DictPrintObject, Mapping):
#   def __init__(self, values):
#     HashObject.__init__(self)
#     self.__dict__[HASH_DICT] = values
#   def variables(self):
#     return set(self.__dict__[HASH_DICT].keys())
#   def includes(self, other):
#     return all(var in self and self[var] == other[var] for var in other.variables()) # TODO - test if state
#   def __getitem__(self, var):
#     return self.get(var)
#   def __iter__(self):
#     return self.__dict__[HASH_DICT].items()
#   def __len__(self):
#     return len(self.__dict__[HASH_DICT])
#   def __str__(self):
#     return 'SS' + str_args(self.__dict__[HASH_DICT])
# 
# class PartialState(SinglePrintObject):
#   #__slots__ = ('conditions',)
#   def __init__(self, conditions):
#     HashObject.__init__(self)
#     self.conditions = tuple(conditions)
#   def __contains__(self, state):
#     return all(state in condition for condition in self.conditions)
#   def __iter__(self):
#     for condition in self.conditions:
#       yield condition
#   def __len__(self):
#     return len(self.conditions)
# 
# Path: planner/conditions.py
# class SubstateCondition(Condition):
#   def __init__(self, substate):
#     super(self.__class__, self).__init__()
#     self.substate = substate
#     self.variables = frozenset(substate.variables())
#   def __contains__(self, substate):
#     return all(var in substate and substate[var] == value for var, value in self.substate)
#   def __str__(self):
#     return 'SC' + str_args(self.substate.__dict__['__hash_dict'])
#   __repr__ = __str__
# 
# Path: misc/functions.py
# def merge_dicts(*args):
#   result = {}
#   for d in args:
#     result.update(d)
#   return result
#   # return dict(reduce(operator.add, [d.items() for d in args]))


# Path: retired/discrete/blocks_world/problems.py
from .operators import Pick, Place, Stack, Unstack
from retired.discrete.schedulers import InitDiscreteScheduler
from planner.states import State, Substate, PartialState
from planner.conditions import SubstateCondition
from misc.functions import merge_dicts
from itertools import permutations


def restack(n=10, height=5):
  blocks = ['B%d'%i for i in range(1, n+1)]
  start = State(merge_dicts(
      {('on', blocks[0]): 'table', ('clear', blocks[height-1]): True},
      {('on', blocks[i+1]): blocks[i] for i in range(height-1)},
      {('on', blocks[i]): 'table' for i in range(height, n)},
      {('clear', blocks[i]): True for i in range(height, n)}
  ))

  goal = PartialState([
    SubstateCondition(Substate({('on', blocks[i]): blocks[i+1]})) for i in range(height-1)] + [

    SubstateCondition(Substate({('on', blocks[height-1]): 'table'}))