Esempio n. 1
0
def parseDomAndProb(domain_file, problem_file):
    """ Returns tuple 
			1) Operator Graphs
			2) Object Elements
			3) Init dummy Action
			4) Goal dummy Action
	"""
    parser = Parser(domain_file, problem_file)
    domain, dom = parser.parse_domain_drw()
    problem, v = parser.parse_problem_drw(dom)
    global args
    args, init, goal = problemToGraphs(problem)
    objects = set(args.values())

    addNegativeInitStates(domain.predicates.predicates, init, objects)

    domainAxiomsToGraphs(domain)
    Operators = domainToOperatorGraphs(domain)

    for op in Operators:
        for eff in op.effects:
            FlawLib.non_static_preds.add((eff.name, eff.truth))
            #update(op.effects)

    from GlobalContainer import GC
    GC.object_types.update(obTypesDict(domain.types))

    return Operators, objects, GC.object_types, init, goal
Esempio n. 2
0
def parse(domain_file, problem_file):
    # Parsing
    parser = Parser(domain_file, problem_file)
    domain = parser.parse_domain()
    problem = parser.parse_problem(domain)

    return problem
Esempio n. 3
0
def parse(domain_file, problem_file):
	# Parsing
	parser = Parser(domain_file, problem_file)
	domain = parser.parse_domain()
	problem = parser.parse_problem(domain)

	return problem
Esempio n. 4
0
def parseDomAndProb(domain_file, problem_file):
	""" Returns tuple 
			1) Operator Graphs
			2) Object Elements
			3) Init dummy Action
			4) Goal dummy Action
	"""
	parser = Parser(domain_file, problem_file)
	domain, dom = parser.parse_domain_drw()
	problem, v = parser.parse_problem_drw(dom)
	global args
	args, init, goal = problemToGraphs(problem)
	objects = set(args.values())

	addNegativeInitStates(domain.predicates.predicates, init, objects)

	domainAxiomsToGraphs(domain)
	Operators = domainToOperatorGraphs(domain)

	for op in Operators:
		for eff in op.effects:
			FlawLib.non_static_preds.add((eff.name,eff.truth))
				#update(op.effects)

	from GlobalContainer import GC
	GC.object_types.update(obTypesDict(domain.types))

	return Operators, objects, GC.object_types, init, goal
Esempio n. 5
0
def get_ground_task(domain_filepath, problem_filepath):
    parser = Parser(domain_filepath, problem_filepath)
    domain = parser.parse_domain()
    problem = parser.parse_problem(domain)
    task = grounding.ground(problem)

    return task
Esempio n. 6
0
 def __init__(self, domain_file, problem_file):
     """
         domain - domain pddl file
         problem - problem pddl file
     """
     #parse the domain and problem
     parser = Parser(domain_file, problem_file)
     domain = parser.parse_domain()
     self.problem = parser.parse_problem(domain)
class PlanRecognitionProblemParser:
    def __init__(self):
        self.parser = Parser(None)
        self.problem = None

    def _parse_domain(self,domain_file):
        self.parser.domFile = domain_file
        return self.parser.parse_domain()

    def _parse_observations(self,domain,observations_file):
        observations = []
        with open(observations_file, encoding='utf-8') as file:
            for obs in file:
                iter = parse_lisp_iterator(obs)
                act = parse_predicate_instance(self.parser._read_input(obs))
                observations.append(act)

            # iter = self.parser._read_input(file)
            # while not iter.empty():
            #     observations.append()
            # observations = parse_predicate_instance_list(iter)
        # TODO validate parsed actions

        return observations

    def _parse_hypotheses(self,domain,hypotheses_file):
        hypotheses = []
        with open(hypotheses_file, encoding="utf-8") as file:
            for hyp in file:
                preds = hyp.split(",")
                hyp_literals = [parse_predicate_instance(self.parser._read_input(p)) for p in preds]
                hypotheses.append(hyp_literals)
        # TODO validate hypotheses with domain
        return hypotheses

    def _parse_template(self,domain,template_file):
        self.parser.probFile = template_file
        template_content = ""
        with open(template_file, encoding="utf-8") as file:
            for line in file:
                if line.find("<HYPOTHESIS>")>=0:
                    line = ""
                template_content+=line+"\n"
        self.parser.probInput = template_content
        return self.parser.parse_problem(domain,read_from_file=False)

    def parse_pr_problem(self, domain_file, observations_file, hypotheses_file, template_file):
        parser = Parser(domain_file,template_file)
        domain = self._parse_domain(domain_file)
        observations = self._parse_observations(domain, observations_file)
        hypotheses = self._parse_hypotheses(domain,hypotheses_file)
        template = self._parse_template(domain, template_file)
        return PlanRecognitionProblem(domain,observations, hypotheses, template)
Esempio n. 8
0
def _parse(domain_file, problem_file):
    # Parsing
    parser = Parser(domain_file, problem_file)
    logging.info("Parsing Domain {}".format(domain_file))
    domain = parser.parse_domain()
    logging.info("Parsing Problem {}".format(problem_file))
    problem = parser.parse_problem(domain)
    logging.debug(domain)
    logging.info("{} Predicates parsed".format(len(domain.predicates)))
    logging.info("{} Actions parsed".format(len(domain.actions)))
    logging.info("{} Objects parsed".format(len(problem.objects)))
    logging.info("{} Constants parsed".format(len(domain.constants)))
    return problem
def _parse(domain_file, problem_file):
    # Parsing
    parser = Parser(domain_file, problem_file)
    #logging.info('Parsing Domain {0}'.format(domain_file))
    domain = parser.parse_domain()
    #logging.info('Parsing Problem {0}'.format(problem_file))
    problem = parser.parse_problem(domain)
    #logging.debug(domain)
    #logging.info('{0} Predicates parsed'.format(len(domain.predicates)))
    #logging.info('{0} Actions parsed'.format(len(domain.actions)))
    #logging.info('{0} Objects parsed'.format(len(problem.objects)))
    #logging.info('{0} Constants parsed'.format(len(domain.constants)))
    return problem
Esempio n. 10
0
def test_lm_cut_blocksworld_initial_state():
    parser = Parser('')
    parser.domInput = blocks_dom
    parser.probInput = blocks_problem_1

    domain = parser.parse_domain(False)
    problem = parser.parse_problem(domain, False)

    task = grounding.ground(problem)

    heuristic = LmCutHeuristic(task)
    h_val = heuristic(make_root_node(task.initial_state))
    assert h_val == 6.
Esempio n. 11
0
def _parse(domain_file, problem_file):
    # Parsing
    parser = Parser(domain_file, problem_file)
    logging.info('Parsing Domain {0}'.format(domain_file))
    domain = parser.parse_domain()
    logging.info('Parsing Problem {0}'.format(problem_file))
    problem = parser.parse_problem(domain)
    logging.debug(domain)
    logging.info('{0} Predicates parsed'.format(len(domain.predicates)))
    logging.info('{0} Actions parsed'.format(len(domain.actions)))
    logging.info('{0} Objects parsed'.format(len(problem.objects)))
    logging.info('{0} Constants parsed'.format(len(domain.constants)))
    return problem
Esempio n. 12
0
def parse(domain_file, problem_file):
    """
    unmodified pyperplan function
    """
    parser = Parser(domain_file, problem_file)
    logging.info('Parsing Domain {0}'.format(domain_file))
    domain = parser.parse_domain()
    logging.info('Parsing Problem {0}'.format(problem_file))
    problem = parser.parse_problem(domain)
    logging.debug(domain)
    logging.info('{0} Predicates parsed'.format(len(domain.predicates)))
    logging.info('{0} Actions parsed'.format(len(domain.actions)))
    logging.info('{0} Objects parsed'.format(len(problem.objects)))
    logging.info('{0} Constants parsed'.format(len(domain.constants)))
    return problem
 def parse_pr_problem(self, domain_file, observations_file, hypotheses_file, template_file):
     parser = Parser(domain_file,template_file)
     domain = self._parse_domain(domain_file)
     observations = self._parse_observations(domain, observations_file)
     hypotheses = self._parse_hypotheses(domain,hypotheses_file)
     template = self._parse_template(domain, template_file)
     return PlanRecognitionProblem(domain,observations, hypotheses, template)
Esempio n. 14
0
 def __init__(self, domain_file, problem_file):
     """
         domain - domain pddl file
         problem - problem pddl file
     """
     #parse the domain and problem
     with open(DOM_TEMPL) as d_fd:
         self.domain_template = '\n'.join(
             [line.strip() for line in d_fd.readlines()])
     with open(PROB_TEMPL) as p_fd:
         self.prob_template = '\n'.join(
             [line.strip() for line in p_fd.readlines()])
     parser = Parser(domain_file, problem_file)
     domain = parser.parse_domain()
     problem = parser.parse_problem(domain)
     self.task = grounding.ground(problem)
Esempio n. 15
0
def gen_heuristic_test(dom, prob, search_class, heuristic_class, h_values_plan,
                       plan_length=None):
    parser = Parser('')
    parser.domInput = dom
    parser.probInput = prob

    domain = parser.parse_domain(False)
    problem = parser.parse_problem(domain, False)

    task = grounding.ground(problem)

    heuristic = heuristic_class(task)
    plan = search_class(task, heuristic)
    if plan_length:
        assert len(plan) == plan_length
    # run through plan and validate heuristic value
    # the true_h_values are taken from fast downward with astar and lm cut
    # heuristic
    computed_h_values = list(_gen_h_values(task.initial_state, plan, heuristic))
    assert h_values_plan == computed_h_values
Esempio n. 16
0
def parseDomAndProb(domain_file, problem_file):

	parser = Parser(domain_file, problem_file)
	domain, dom = parser.parse_domain_drw()
	problem, v = parser.parse_problem_drw(dom)

	GC.object_types.update(obTypesDict(domain.types))

	args, init, goal = problemToGraphs(problem)
	objects = set(args.values())

	addNegativeInitStates(domain.predicates.predicates, init, objects)

	domainAxiomsToGraphs(domain)
	Operators, DOperators = domainToOperatorGraphs(domain)

	addStatics(Operators)
	addStatics(DOperators)

	return Operators, DOperators, objects, GC.object_types, init, goal
Esempio n. 17
0
def gen_heuristic_test(dom,
                       prob,
                       search_class,
                       heuristic_class,
                       h_values_plan,
                       plan_length=None):
    parser = Parser('')
    parser.domInput = dom
    parser.probInput = prob

    domain = parser.parse_domain(False)
    problem = parser.parse_problem(domain, False)

    task = grounding.ground(problem)

    heuristic = heuristic_class(task)
    plan = search_class(task, heuristic)
    if plan_length:
        assert len(plan) == plan_length
    # run through plan and validate heuristic value
    # the true_h_values are taken from fast downward with astar and lm cut
    # heuristic
    computed_h_values = list(_gen_h_values(task.initial_state, plan,
                                           heuristic))
    assert h_values_plan == computed_h_values
Esempio n. 18
0
def test_lm_cut_blocksworld_initial_state():
    parser = Parser("")
    parser.domInput = blocks_dom
    parser.probInput = blocks_problem_1

    domain = parser.parse_domain(False)
    problem = parser.parse_problem(domain, False)

    task = grounding.ground(problem)

    heuristic = LmCutHeuristic(task)
    h_val = heuristic(make_root_node(task.initial_state))
    assert h_val == 6.0
Esempio n. 19
0
                   (clear ?y)
                   (not (clear ?x))
                   (not (handempty))
                   (not (on ?x ?y)))))
"""

_problem_input = """(define (problem BLOCKS-5-0)
(:domain BLOCKS)
(:story_objs B E A C D - block)
(:INIT (CLEAR D) (CLEAR C) (ONTABLE D) (ONTABLE A) (ON C E) (ON E B) (ON B A)
 (HANDEMPTY))
(:goal (AND (ON A E) (ON E B) (ON B D) (ON D C)))
)
"""

_parser = Parser('')

_parser.domInput = _domain_input
_parser.probInput = _problem_input

_domain = _parser.parse_domain(False)
_problem = _parser.parse_problem(_domain, False)


def test_default_pddl_visitor_domain():
    defaultVisitor = pddl_tree_visitor.PDDLVisitor()
    input = _domain_input.split('\n')
    iter = parse_lisp_iterator(input)
    domAST = parse_domain_def(iter)
    # and traverse the AST
    domAST.accept(defaultVisitor)
 def __init__(self):
     self.parser = Parser(None)
     self.problem = None
Esempio n. 21
0
    logging.basicConfig(level=getattr(logging, args.loglevel.upper()),
                        format='%(asctime)s %(levelname)-8s %(message)s',
                        stream=sys.stdout)

    args.problem = os.path.abspath(args.problem)
    if args.domain is None:
        args.domain = find_domain(args.problem)
    else:
        args.domain = os.path.abspath(args.domain)

    problem = parse(args.domain, args.problem)
    task = ground(problem)

    if args.graphtype == 'relatedness' and args.diameter == 'true':
        build_graph_related(task, static=True, draw=True, diameter=True)
    elif args.graphtype == 'relatedness' and args.diameter == 'false':
        build_graph_related(task, static=True, draw=True, diameter=False)
    elif args.graphtype == 'rel_simple':
        if args.grounding == 'original':
            raise Exception(
                'The simple relatedness graph is only available with the new grounding'
            )
        parser = Parser(args.domain, args.problem)
        domain = parser.parse_domain(args.domain)
        if args.diameter == 'true':
            build_graph_rel_simple(domain, task, draw=True)
        elif args.diameter == 'false':
            build_graph_rel_simple(domain, task, draw=True, diameter=False)
    elif args.graphtype == 'causal':
        build_graph_causal(task)
Esempio n. 22
0
def parseDomain(domain_file):
	parser = Parser(domain_file)
	domain = parser.parse_domain_drw()
	return domain
Esempio n. 23
0
                   (clear ?y)
                   (not (clear ?x))
                   (not (handempty))
                   (not (on ?x ?y)))))
"""

_problem_input = """(define (problem BLOCKS-5-0)
(:domain BLOCKS)
(:objects B E A C D - block)
(:INIT (CLEAR D) (CLEAR C) (ONTABLE D) (ONTABLE A) (ON C E) (ON E B) (ON B A)
 (HANDEMPTY))
(:goal (AND (ON A E) (ON E B) (ON B D) (ON D C)))
)
"""

_parser = Parser("")

_parser.domInput = _domain_input
_parser.probInput = _problem_input

_domain = _parser.parse_domain(False)
_problem = _parser.parse_problem(_domain, False)


def test_default_pddl_visitor_domain():
    defaultVisitor = pddl_tree_visitor.PDDLVisitor()
    input = _domain_input.split("\n")
    iter = parse_lisp_iterator(input)
    domAST = parse_domain_def(iter)
    # and traverse the AST
    domAST.accept(defaultVisitor)
Esempio n. 24
0
			if ob.name == child_name:
				accumulated.add(ob.parent)
				rFollowHierarchy(object_types, ob.parent, accumulated)
	
import sys	
if __name__ ==  '__main__':
	num_args = len(sys.argv)
	if num_args >1:
		domain_file = sys.argv[1]
		if num_args > 2:
			problem_file = sys.argv[2]		
	else:
		domain_file = 'domains/mini-indy-domain.pddl'
		problem_file = 'domains/mini-indy-problem.pddl'
	
	parser = Parser(domain_file, problem_file)
	domain, dom = parser.parse_domain_drw()
	problem, v = parser.parse_problem_drw(dom)
	op_graphs = domainToOperatorGraphs(domain)
	for opgraph in op_graphs:
		opgraph.print_graph_names()
		print('\n')
	
	strucDict = problemToGraphs(problem)
	print('\nargs \n')
	Args = strucDict['args']
	for argElement in Args.values():
		print(argElement)
	print('\ninit\n')
	strucDict['init'].print_graph_names()
	print('\ngoal\n')
Esempio n. 25
0
def test_add_del_effects():
    parser = Parser("")

    def parse_problem(domain, problem):
        parser.domInput = domain
        parser.probInput = problem
        domain = parser.parse_domain(False)
        return parser.parse_problem(domain, False)

    dom_pddl = """
    (define (domain dom)
      (:requirements :typing)
      (:predicates (ok ?v - object))

      (:action theaction
       :parameters (?x - object)
       :precondition {0}
       :effect {1}
      )
    )
    """

    prob_pddl = """
    ;; See domain file for description of this test.

    (define (problem prob)
      (:domain dom)
      (:objects y - object)
      (:init)
      (:goal (ok y)))
    """

    tests = [
        # Only add effect
        ("(and)", "(ok ?x)", set(), {"(ok y)"}, set()),
        # Only delete effect
        ("(and)", "(and (not (ok ?x)))", set(), set(), {"(ok y)"}),
        # Both add and delete effect
        ("(and)", "(and (ok ?x) (not (ok ?x)))", set(), {"(ok y)"}, set()),
        # Precondition and add effect
        ("(and (ok ?x))", "(ok ?x)", {"(ok y)"}, set(), set()),
        # Precondition and delete effect
        ("(and (ok ?x))", "(and (not (ok ?x)))", {"(ok y)"}, set(), {"(ok y)"}
         ),
        # Precondition and both add and delete effect
        ("(and (ok ?x))", "(and (ok ?x) (not (ok ?x)))", {"(ok y)"}, set(),
         set()),
    ]

    for pre_in, eff_in, pre_exp, add_exp, del_exp in tests:
        dom = dom_pddl.format(pre_in, eff_in)
        problem = parse_problem(dom, prob_pddl)

        domain = problem.domain
        actions = domain.actions.values()
        predicates = domain.predicates.values()

        # Objects
        objects = problem.objects
        objects.update(domain.constants)

        # Get the names of the static predicates
        statics = grounding._get_statics(predicates, actions)

        # Create a map from types to objects
        type_map = grounding._create_type_map(objects)

        # Transform initial state into a specific
        init = grounding._get_partial_state(problem.initial_state)

        # Ground actions
        operators = grounding._ground_actions(actions, type_map, statics, init)

        assert len(operators) == 1
        op = operators[0]
        assert op.preconditions == pre_exp
        assert op.add_effects == add_exp
        assert op.del_effects == del_exp
Esempio n. 26
0
                accumulated.add(ob.parent)
                rFollowHierarchy(object_types, ob.parent, accumulated)


import sys
if __name__ == '__main__':
    num_args = len(sys.argv)
    if num_args > 1:
        domain_file = sys.argv[1]
        if num_args > 2:
            problem_file = sys.argv[2]
    else:
        domain_file = 'domains/mini-indy-domain.pddl'
        problem_file = 'domains/mini-indy-problem.pddl'

    parser = Parser(domain_file, problem_file)
    domain, dom = parser.parse_domain_drw()
    problem, v = parser.parse_problem_drw(dom)
    op_graphs = domainToOperatorGraphs(domain)
    for opgraph in op_graphs:
        opgraph.print_graph_names()
        print('\n')

    strucDict = problemToGraphs(problem)
    print('\nargs \n')
    Args = strucDict['args']
    for argElement in Args.values():
        print(argElement)
    print('\ninit\n')
    strucDict['init'].print_graph_names()
    print('\ngoal\n')
Esempio n. 27
0
def parseDomain(domain_file):
    parser = Parser(domain_file)
    domain = parser.parse_domain_drw()
    return domain
Esempio n. 28
0
def problemInfo(domFile):
    parser = Parser(domFile)
    domain = parser.parse_domain()
    return len(domain.predicates), len(domain.actions)
if __name__ == "__main__":
    """
    This script uses the RelaxedPlanGraph class.
    First it parses the PDDL domain and problem files.
    Then it builds the relaxed plan graph.
    """

    # ground command line arguments
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument("domain", help="path to PDDL domain file")
    arg_parser.add_argument("problem", help="path to PDDL problem file")
    args = arg_parser.parse_args()

    # parse PDDL domain and problem files
    print("Parsing PDDL domain file...")
    pddl_parser = Parser()
    pddl_parser.parse_file(args.domain)
    pddl_parser.parse_file(args.problem)

    # build a relaxed plan graph
    print("Building relaxed plan graph...")
    start_time = time.time()
    rpg = RelaxedPlanGraph(pddl_parser.domain, pddl_parser.problem)
    layer_count = rpg.build_graph(stop_at_goal=True)
    relaxed_plan, action_count = rpg.get_relaxed_plan()
    print("Building relaxed plan graph took %.2f seconds." %
          (time.time() - start_time))

    # print the relaxed plan
    print("Relaxed plan graph has %d layers." % layer_count)
    print("Relaxed plan has %d actions." % action_count)
Esempio n. 30
0
def test_regression():
    parser = Parser("")

    def parse_problem(domain, problem):
        parser.domInput = domain
        parser.probInput = problem
        domain = parser.parse_domain(False)
        return parser.parse_problem(domain, False)

    prob_05 = """
    ;; See domain file for description of this test.

    (define (problem regression-test-05)
      (:domain regression-test)
      (:objects y - object)
      (:init)
      (:goal (the-predicate x y)))
    """

    dom_05 = """
    ;; Expected behaviour: plan of length one found
    ;; Observed behaviour (r265): plan of length zero found

    (define (domain regression-test)
      (:requirements :typing) ;; work around problem in regression test #4.
      (:predicates (the-predicate ?v1 ?v2 - object))
      (:constants x - object)

      (:action theaction
       :parameters (?x - object)
       :precondition (and)
       :effect (the-predicate x ?x)
      )
    )
    """

    prob_06 = """
    ;; See domain file for description of this test.

    (define (problem regression-test-06)
      (:domain regression-test)
      (:objects y - object)
      (:init)
      (:goal (the-predicate y y)))

    """
    dom_06 = """
    ;; Expected behaviour: planner proves that no plan exists
    ;; Observed behaviour (r265): plan of length one found

    (define (domain regression-test)
      (:requirements :typing) ;; work around problem in regression test #4.
      (:predicates (the-predicate ?v1 ?v2 - object))
      (:constants x - object)

      (:action theaction
       :parameters (?x - object)
       :precondition (and)
       :effect (the-predicate x ?x)
      )
    )
    """

    # problem / domain 07 contains a different action compared
    # to the actions of domain 5 & 6
    prob_07 = prob_06

    dom_07 = """
    (define (domain regression-test)
      (:requirements :typing) ;; work around problem in regression test #4.
      (:predicates (the-predicate ?v1 ?v2 - object))
      (:constants y - object)

      (:action theaction
       :parameters (?x - object)
       :precondition (and)
       :effect (the-predicate y ?x)
      )
    )
    """

    # action of problem / domain 8 differs only in the variable name compared
    # to the actions of problem 5 and 6: After grounding there should be no
    # difference between the grounded actions
    prob_08 = prob_05

    dom_08 = """
    (define (domain regression-test)
      (:requirements :typing) ;; work around problem in regression test #4.
      (:predicates (the-predicate ?v1 ?v2 - object))
      (:constants x - object)

      (:action theaction
       :parameters (?z - object)
       :precondition (and)
       :effect (the-predicate x ?z)
      )
    )
    """

    parsed_problem5 = parse_problem(dom_05, prob_05)
    parsed_problem6 = parse_problem(dom_06, prob_06)
    parsed_problem7 = parse_problem(dom_07, prob_07)
    parsed_problem8 = parse_problem(dom_08, prob_08)

    # coded input:
    type_object = Type("object", None)
    types = {"object": type_object}
    predicates = {
        "the_predicate":
        Predicate("the-predicate", [("v1", type_object), ("v2", type_object)])
    }
    constants = {"x": type_object}
    actions = {
        "theaction":
        get_action(
            "theaction",
            [("?x", [type_object])],
            [],
            [
                Predicate("the-predicate", [("x", type_object),
                                            ("?x", type_object)])
            ],
            [],
        )
    }
    domain = Domain("regression-test", types, predicates, actions, constants)
    problem5 = Problem(
        "regression-test-05",
        domain,
        {"y": type_object},
        [],
        [Predicate("the-predicate", [("x", type_object), ("y", type_object)])],
    )
    problem6 = Problem(
        "regression-test-06",
        domain,
        {"y": type_object},
        [],
        [Predicate("the-predicate", [("y", type_object), ("y", type_object)])],
    )

    parsed_task5 = grounding.ground(parsed_problem5)
    coded_task5 = grounding.ground(problem5)
    parsed_task6 = grounding.ground(parsed_problem6)
    coded_task6 = grounding.ground(problem6)
    parsed_task7 = grounding.ground(parsed_problem7)
    parsed_task8 = grounding.ground(parsed_problem8)

    expected = [
        (parsed_task5.operators, coded_task5.operators, True),
        (parsed_task6.operators, coded_task6.operators, True),
        (parsed_task5.operators, coded_task6.operators, False),
        (parsed_task5.operators, parsed_task7.operators, False),
        (parsed_task5.operators, parsed_task8.operators, True),
    ]

    for operator1, operator2, expected_result in expected:
        assert compare_operators(operator1, operator2) == expected_result
def test_writer_complex():
    test = [
        """
        (define (domain BLOCKS)
      (:requirements :strips :typing)
      (:types block)
      (:predicates (on ?x - block ?y - block)
                   (ontable ?x - block)
                   (clear ?x - block)
                   (handempty)
                   (holding ?x - block)
                   )

      (:action pick-up
                 :parameters (?x - block)
                 :precondition (and (clear ?x) (ontable ?x) (handempty))
                 :effect
                 (and (not (ontable ?x))
                       (not (clear ?x))
                       (not (handempty))
                       (holding ?x)))

      (:action put-down
                 :parameters (?x - block)
                 :precondition (holding ?x)
                 :effect
                 (and (not (holding ?x))
                       (clear ?x)
                       (handempty)
                       (ontable ?x)))
      (:action stack
                 :parameters (?x - block ?y - block)
                 :precondition (and (holding ?x) (clear ?y))
                 :effect
                 (and (not (holding ?x))
                       (not (clear ?y))
                       (clear ?x)
                       (handempty)
                       (on ?x ?y)))
      (:action unstack
                 :parameters (?x - block ?y - block)
                 :precondition (and (on ?x ?y) (clear ?x) (handempty))
                 :effect
                 (and (holding ?x)
                       (clear ?y)
                       (not (clear ?x))
                       (not (handempty))
                       (not (on ?x ?y)))))
        """, """
                (define (problem BLOCKS-4-0)
                (:domain BLOCKS)
                (:objects D B A C - block)
                (:INIT (CLEAR C) (CLEAR A) (CLEAR B) (CLEAR D) (ONTABLE C) (ONTABLE A)
                (ONTABLE B) (ONTABLE D) (HANDEMPTY))
                (:goal (AND (ON D C) (ON C B) (ON B A)))
                )
                """
    ]
    parser = Parser(None)
    parser.domInput = test[0]
    parser.probInput = test[1]
    domain = parser.parse_domain(False)
    problem = parser.parse_problem(domain, False)
    writer = PDDLWriter()
    domain_string = writer.write_domain(domain)
    # print(domain_string)
    parser.domInput = domain_string
    domain = parser.parse_domain(False)  # Checking if our output is valid pddl
    assert domain is not None
    # print(writer.write_domain(domain))
    # assert domain_string == writer.write_domain(domain)
    print(writer.write_problem(problem))