# Path: planner/operators.py
# def derive_predicates(state, axioms):
#   if not axioms:
#     return state, []
#   is_strips = 'strips' in axioms[0].__class__.__module__ # TODO: clean this up
#   if is_strips:
#     from strips.operators import derive_state
#     return derive_state(state, axioms)
#   return derive_predicates_slow(state, axioms)
# 
# class MacroOperator(object):
#   def __init__(self, *operators):
#     self.operators = tuple(operators)
#     self.cost = sum(operator.cost for operator in operators)
#   def __contains__(self, state):
#     return self(state) is not None
#   def __call__(self, state):
#     states = [state]
#     for operator in self.operators:
#       new_state = operator(states[-1])
#       if new_state is None: return None
#       states.append(new_state)
#     return states
#   def __iter__(self):
#     return (operator for operator in self.operators)
#   def __len__(self):
#     return len(self.operators)
#   def __eq__(self, other):
#     if type(self) != type(other): return False
#     return self.operators == other.operators
#   def __ne__(self, other):
#     return not self == other
#   def __hash__(self):
#     return hash((self.__class__, self.operators))
#   def __str__(self):
#     return self.__class__.__name__ + str_object(self.operators)
#   __repr__ = __str__
# 
# Path: misc/functions.py
# def elapsed_time(start_time):
#   return time.time() - start_time
# 
# def safe_remove(sequence, item):
#   try:
#     sequence.remove(item)
#     return True
#   except ValueError:
#     return False
# 
# def implies(a, b):
#   return not a or b
# 
# Path: misc/numerical.py
# INF = float('inf')
# 
# Path: misc/objects.py
# def str_line(*args):
#   return ''.join(str_object(item) for item in args)


from collections import namedtuple
from .operators import derive_predicates, MacroOperator
from misc.functions import elapsed_time, safe_remove, implies
from misc.numerical import INF
from misc.objects import str_line
import time
        self.start = start
        self.operators = operators
    @property
    def cost(self):
        if not self.operators:
            return 0
        return sum(operator.cost for operator in self.operators)
    @property
    def length(self):
        return len(self.operators)
    @property
    def priority(self):
        return Priority(self.cost, self.length)
    def __iter__(self):
        return iter(self.operators)
    def get_states(self):
        states = [self.start]
        for operator in self.operators:
            #assert states[-1] in operator
            #states.append(operator(states[-1]))
            states.append(operator.apply(states[-1]))
        return states
    def get_derived_states(self, axioms):
        states = [self.start]
        derived_state, axiom_plan = derive_predicates(states[-1], axioms)
        derived_states = [derived_state]
        axiom_plans = [axiom_plan]
        for operator in self.operators:
            assert derived_states[-1] in operator
            states.append(operator.apply(states[-1]))

# Path: planner/operators.py
# def derive_predicates(state, axioms):
#   if not axioms:
#     return state, []
#   is_strips = 'strips' in axioms[0].__class__.__module__ # TODO: clean this up
#   if is_strips:
#     from strips.operators import derive_state
#     return derive_state(state, axioms)
#   return derive_predicates_slow(state, axioms)
# 
# class MacroOperator(object):
#   def __init__(self, *operators):
#     self.operators = tuple(operators)
#     self.cost = sum(operator.cost for operator in operators)
#   def __contains__(self, state):
#     return self(state) is not None
#   def __call__(self, state):
#     states = [state]
#     for operator in self.operators:
#       new_state = operator(states[-1])
#       if new_state is None: return None
#       states.append(new_state)
#     return states
#   def __iter__(self):
#     return (operator for operator in self.operators)
#   def __len__(self):
#     return len(self.operators)
#   def __eq__(self, other):
#     if type(self) != type(other): return False
#     return self.operators == other.operators
#   def __ne__(self, other):
#     return not self == other
#   def __hash__(self):
#     return hash((self.__class__, self.operators))
#   def __str__(self):
#     return self.__class__.__name__ + str_object(self.operators)
#   __repr__ = __str__
# 
# Path: misc/functions.py
# def elapsed_time(start_time):
#   return time.time() - start_time
# 
# def safe_remove(sequence, item):
#   try:
#     sequence.remove(item)
#     return True
#   except ValueError:
#     return False
# 
# def implies(a, b):
#   return not a or b
# 
# Path: misc/numerical.py
# INF = float('inf')
# 
# Path: misc/objects.py
# def str_line(*args):
#   return ''.join(str_object(item) for item in args)


# Path: planner/state_space.py
from collections import namedtuple
from .operators import derive_predicates, MacroOperator
from misc.functions import elapsed_time, safe_remove, implies
from misc.numerical import INF
from misc.objects import str_line
import time

        self.start = start
        self.operators = operators
    @property
    def cost(self):
        if not self.operators:
            return 0
        return sum(operator.cost for operator in self.operators)
    @property
    def length(self):
        return len(self.operators)
    @property
    def priority(self):
        return Priority(self.cost, self.length)
    def __iter__(self):
        return iter(self.operators)
    def get_states(self):
        states = [self.start]
        for operator in self.operators:
            #assert states[-1] in operator
            #states.append(operator(states[-1]))
            states.append(operator.apply(states[-1]))
        return states
    def get_derived_states(self, axioms):
        states = [self.start]
        derived_state, axiom_plan = derive_predicates(states[-1], axioms)
        derived_states = [derived_state]
        axiom_plans = [axiom_plan]
        for operator in self.operators:
            assert derived_states[-1] in operator
            states.append(operator.apply(states[-1]))

            derived_state, axiom_plan = derive_predicates(states[-1], axioms)