aiplan4eu / up-lpg

LPG is a automated planner supporting classical and numeric state variables, and supports durative actions too. It computes plans using one-shoot and anytime operation mode.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

'utf-8' codec can't decode byte 0xe0

jrenoux opened this issue · comments

Hi

I have an issue with the LPG planner where I receive the following error message:

Traceback (most recent call last):
  File "/home/jennifer/work/projects/aiplan4eu/meritor/up-mer-usecase/tests_up/pddl_parse_lgp_solve.py", line 148, in <module>
    result = planner.solve(problem)
  File "/home/jennifer/.cache/pypoetry/virtualenvs/aiplan4eu-mer-F4EqWIfX-py3.10/lib/python3.10/site-packages/unified_planning/engines/mixins/oneshot_planner.py", line 81, in solve
    return self._solve(problem, heuristic, timeout, output_stream)
  File "/home/jennifer/.cache/pypoetry/virtualenvs/aiplan4eu-mer-F4EqWIfX-py3.10/lib/python3.10/site-packages/unified_planning/engines/pddl_planner.py", line 219, in _solve
    proc_out, proc_err = [[x.decode()] for x in out_err_bytes]
  File "/home/jennifer/.cache/pypoetry/virtualenvs/aiplan4eu-mer-F4EqWIfX-py3.10/lib/python3.10/site-packages/unified_planning/engines/pddl_planner.py", line 219, in <listcomp>
    proc_out, proc_err = [[x.decode()] for x in out_err_bytes]
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe0 in position 1006: invalid continuation byte

I attached a minimum breaking example.

The issue seems to be related with f_nb_elements_in_machine being 0. If I change to anything but 0 in set_initial_value or in the precondition of the operator, there is no error message but a warning:

UserWarning: We cannot establish whether <function LPGEngine.name at 0x7f2d9bf71990> can solve this problem!

If I remove any part of the operator in the example, the error disappears but the warning stays.

Operating system: Ubuntu 22.04
Environment: Poetry-managed virtual environment, python 3, IntelliJ IDEA

from collections import OrderedDict

import unified_planning as up
from unified_planning.shortcuts import *


def get_problem():
    mer_problem = up.model.Problem("mer_problem")

    env = up.environment.get_env()
    tm = env.type_manager

    ############################################
    # Defining types
    #############################################
    type_family = tm.UserType("type_family")
    type_machine = tm.UserType("type_machine")
    type_piece = tm.UserType("type_piece")
    type_step = tm.UserType("type_step")

    ############################################
    # Defining objects
    #############################################
    o_gear = up.model.Object("gear", type_piece)
    mer_problem.add_object(o_gear)

    o_family_17x = up.model.Object("17X", type_family)
    mer_problem.add_object(o_family_17x)

    o_machine_A4 = up.model.Object("A4", type_machine)
    mer_problem.add_object(o_machine_A4)

    o_annealing_step = up.model.Object("annealing", type_step)
    mer_problem.add_object(o_annealing_step)

    #############################################
    # Required fluents for the process
    #############################################
    # fluent describing the EDI/Batch to be produced
    # number of gears
    f_buff_start = up.model.Fluent("buffer_start",
                                   tm.IntType(),
                                   family = type_family,
                                   piece = type_piece)
    mer_problem.add_fluent(f_buff_start)
    mer_problem.set_initial_value(
        f_buff_start(o_family_17x, o_gear),
        10
    )

    # capacity of a machine for a given family and piece type
    f_has_capacity = up.model.Fluent("has_capacity",
                                     tm.IntType(),
                                     machine = type_machine,
                                     family = type_family,
                                     piece = type_piece
                                     )
    mer_problem.add_fluent(f_has_capacity)
    mer_problem.set_initial_value(
        f_has_capacity(
            o_machine_A4,
            o_family_17x,
            o_gear
        ),
        5
    )

    # number of elements currently processed in a given machine
    f_nb_elements_in_machine = up.model.Fluent("nb_elements_in_machine",
                                               tm.IntType(),
                                               machine=type_machine)
    mer_problem.add_fluent(f_nb_elements_in_machine)

    mer_problem.set_initial_value(f_nb_elements_in_machine(o_machine_A4), 0)


    # which machine is used for which step
    f_is_used_for_step = up.model.Fluent("is_used_for_step",
                                         tm.BoolType(),
                                         machine = type_machine,
                                         step = type_step,
                                         piece = type_piece)
    mer_problem.add_fluent(f_is_used_for_step)
    mer_problem.set_initial_value(f_is_used_for_step(o_machine_A4, o_annealing_step, o_gear), TRUE())


    #############################################
    # Process (simplified)
    #############################################
    # Buffer between the annealing and green turning (gear and pinion)
    f_buff_ann_tur = up.model.Fluent("buffer_annealing_turning",
                                     tm.IntType(), # the quantity of gears already annealed
                                     family = type_family,
                                     piece = type_piece
                                     )
    mer_problem.add_fluent(f_buff_ann_tur)
    mer_problem.set_initial_value(
        f_buff_ann_tur(o_family_17x, o_gear),
        0
    )

    #############################################
    # Operators / actions
    #############################################
    ####### Annealing
    a_annealing_capacity = up.model.DurativeAction(
        "annealing_capacity",
        machine=type_machine,
        family=type_family,
        piece=type_piece
    )
    ann_capacity_machine = a_annealing_capacity.parameter("machine")
    ann_capacity_family = a_annealing_capacity.parameter("family")
    ann_capacity_piece = a_annealing_capacity.parameter("piece")
    a_annealing_capacity.add_condition(
        StartTiming(),
        Equals(f_nb_elements_in_machine(ann_capacity_machine), 0),
    )
    a_annealing_capacity.add_effect(
        StartTiming(),
        f_nb_elements_in_machine(ann_capacity_machine),
        f_has_capacity(ann_capacity_machine, ann_capacity_family, ann_capacity_piece)
    )
    a_annealing_capacity.add_effect(
        EndTiming(),
        f_buff_ann_tur(ann_capacity_family, ann_capacity_piece),
        f_buff_ann_tur(ann_capacity_family, ann_capacity_piece) + f_has_capacity(ann_capacity_machine, ann_capacity_family, ann_capacity_piece)
    )
    mer_problem.add_action(a_annealing_capacity)


    ####### Goal
    mer_problem.add_goal(Equals(f_buff_ann_tur(o_family_17x, o_gear), 10))

    return mer_problem

problem = get_problem()
print(problem)
env = problem.env
factory = env.factory
factory.add_engine(name = "lpg", module_name = "up_lpg.lpg_planner", class_name = "LPGEngine")
with OneshotPlanner(name='lpg') as planner:
    result = planner.solve(problem)
    if result.status == up.engines.PlanGenerationResultStatus.SOLVED_SATISFICING:
        print("Pyperplan returned: %s" % result.plan)
    else:
        print("No plan found.")

Looks like LPG is outputting something not in UTF8...
@serivan any idea?

The UTF-8 error message indeed disappeared and all seems to be working as expected. The non-solvability is also normal since I reduced the problem as much as possible to isolate the problem.
Thanks for the reactivity!