All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fr.uga.pddl4j.encoding.IntEncoding Maven / Gradle / Ivy

/*
 * Copyright (c) 2010 by Damien Pellier .
 *
 * This file is part of PDDL4J library.
 *
 * PDDL4J is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * PDDL4J is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with PDDL4J.  If not, see 
 */

package fr.uga.pddl4j.encoding;

import fr.uga.pddl4j.parser.DerivedPredicate;
import fr.uga.pddl4j.parser.Domain;
import fr.uga.pddl4j.parser.Exp;
import fr.uga.pddl4j.parser.NamedTypedList;
import fr.uga.pddl4j.parser.Op;
import fr.uga.pddl4j.parser.Problem;
import fr.uga.pddl4j.parser.Symbol;
import fr.uga.pddl4j.parser.TypedSymbol;
import fr.uga.pddl4j.util.IntExp;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * This class implements all the methods needed to encode operators, goal and initial state loaded
 * from the parser in its integer representation.
 *
 * @author D. Pellier
 * @version 1.0 - 08.06.2010
 */
final class IntEncoding implements Serializable {

    /**
     * The serial version id of the class.
     */
    private static final long serialVersionUID = 1L;

    /**
     * The default constructor with a private access to prevent instance creation.
     */
    private IntEncoding() {
    }

    /**
     * Collects composite type, i.e., type of the form (either t1 t2), through a specified domain and
     * problem and creates their respective domain.
     *
     * @param domain  the domain.
     * @param problem the problem.
     */
    static void encodeEitherTypes(final Domain domain, final Problem problem) {
        // Collect the types from the predicates declaration
        for (NamedTypedList predicate : domain.getPredicates()) {
            IntEncoding.encodeTypes(predicate.getArguments());
        }
        // Collect the types from the functions declaration
        for (NamedTypedList function : domain.getFunctions()) {
            IntEncoding.encodeTypes(function.getArguments());
        }
        // Collect the types from the constraints declaration of the domain
        if (domain.getConstraints() != null) {
            IntEncoding.encodeTypes(domain.getConstraints());
        }
        // Collect the types from the derived predicates
        for (DerivedPredicate axiom : domain.getDerivesPredicates()) {
            IntEncoding.encodeTypes(axiom.getHead().getArguments());
            IntEncoding.encodeTypes(axiom.getBody());
        }
        // Collect the type from the operators
        for (Op op : domain.getOperators()) {
            IntEncoding.encodeTypes(op.getParameters());
            if (op.getDuration() != null) {
                IntEncoding.encodeTypes(op.getDuration());
            }
            IntEncoding.encodeTypes(op.getPreconditions());
            IntEncoding.encodeTypes(op.getEffects());
        }
        // Collect the types from the constraints declaration of the problem
        if (problem.getConstraints() != null) {
            IntEncoding.encodeTypes(problem.getConstraints());
        }
        // Collect the types from the goal declaration of the problem
        IntEncoding.encodeTypes(problem.getGoal());

    }

    /**
     * Encodes all the types of a specified domain.
     *
     * @param domain the domain.
     */
    static void encodeTypes(final Domain domain) {
        final List types = domain.getTypes();
        final int nbTypes = types.size();
        Encoder.tableOfTypes = new ArrayList<>(nbTypes);
        Encoder.tableOfDomains = new ArrayList<>(nbTypes);
        for (TypedSymbol type : types) {
            Encoder.tableOfTypes.add(type.getImage());
            Encoder.tableOfDomains.add(new LinkedHashSet<>());
        }
    }

    /**
     * Encoded all the type from a specified list of typed symbols.
     *
     * @param list the list of typed symbol.
     */
    private static void encodeTypes(final List list) {
        for (TypedSymbol elt : list) {
            final List types = elt.getTypes();
            if (types.size() > 1) {
                String newType;
                Set newTypeDomain = new LinkedHashSet<>();
                StringBuilder buf = new StringBuilder();
                buf.append("either");
                for (Symbol type : types) {
                    final String image = type.getImage();
                    buf.append("~");
                    buf.append(image);
                    int typeIndex = Encoder.tableOfTypes.indexOf(image);
                    final Set typeDomain = Encoder.tableOfDomains.get(typeIndex);
                    newTypeDomain.addAll(typeDomain);
                }
                newType = buf.toString();
                int index = Encoder.tableOfTypes.indexOf(newType);
                if (index == -1) {
                    Encoder.tableOfDomains.add(new LinkedHashSet<>(newTypeDomain));
                    Encoder.tableOfTypes.add(newType);
                }
            }
        }
    }

    /**
     * Encodes all the type from a specified expression.
     *
     * @param exp the expression.
     */
    private static void encodeTypes(final Exp exp) {
        switch (exp.getConnective()) {
            case AND:
            case OR:
                exp.getChildren().forEach(IntEncoding::encodeTypes);
                break;
            case FORALL:
            case EXISTS:
                IntEncoding.encodeTypes(exp.getVariables());
                IntEncoding.encodeTypes(exp.getChildren().get(0));
                break;
            case F_EXP_T:
                if (!exp.getChildren().isEmpty()) {
                    IntEncoding.encodeTypes(exp.getChildren().get(0));
                }
                break;
            case EQUAL:
            case FN_ATOM:
            case WHEN:
            case DURATION_ATOM:
            case LESS:
            case LESS_OR_EQUAL:
            case GREATER:
            case GREATER_OR_EQUAL:
            case MUL:
            case DIV:
            case MINUS:
            case PLUS:
            case ASSIGN:
            case INCREASE:
            case DECREASE:
            case SCALE_UP:
            case SCALE_DOWN:
                IntEncoding.encodeTypes(exp.getChildren().get(0));
                IntEncoding.encodeTypes(exp.getChildren().get(1));
                break;
            case AT_START:
            case AT_END:
            case MINIMIZE:
            case MAXIMIZE:
            case UMINUS:
            case NOT:
            case ALWAYS:
            case OVER_ALL:
            case SOMETIME:
            case AT_MOST_ONCE:
            case F_EXP:
                IntEncoding.encodeTypes(exp.getChildren().get(0));
                break;
            case HOLD_AFTER:
            case WITHIN:
                IntEncoding.encodeTypes(exp.getChildren().get(1));
                break;
            case ALWAYS_WITHIN:
                IntEncoding.encodeTypes(exp.getChildren().get(1));
                IntEncoding.encodeTypes(exp.getChildren().get(2));
                break;
            case HOLD_DURING:
                IntEncoding.encodeTypes(exp.getChildren().get(2));
                break;
            case IS_VIOLATED:
            case NUMBER:
            case ATOM:
            case FN_HEAD:
            case TIME_VAR:
            default:
                //do nothing
        }
    }

    /**
     * Encodes all the constants of the specified domain and the problem.
     *
     * @param domain  the domain.
     * @param problem the problem.
     */
    static void encodeConstants(final Domain domain, final Problem problem) {
        final List constants = domain.getConstants();
        Encoder.tableOfConstants = new ArrayList<>(domain.getConstants().size());
        constants.addAll(problem.getObjects());
        for (TypedSymbol constant : constants) {
            int ic = Encoder.tableOfConstants.indexOf(constant.getImage());
            if (ic == -1) {
                ic = Encoder.tableOfConstants.size();
                Encoder.tableOfConstants.add(constant.getImage());
            }
            final LinkedList types = new LinkedList<>(constant.getTypes());
            while (!types.isEmpty()) {
                Symbol type = types.poll();
                final int it = Encoder.tableOfTypes.indexOf(type.getImage());
                types.addAll(domain.getType(type).getTypes());
                Encoder.tableOfDomains.get(it).add(ic);
            }
        }
    }

    /**
     * Encodes all the predicates of a specified domain.
     *
     * @param domain the domain.
     */
    static void encodePredicates(final Domain domain) {
        final List predicates = domain.getPredicates();
        final int nbPredicates = predicates.size();
        Encoder.tableOfPredicates = new ArrayList<>(nbPredicates);
        Encoder.tableOfTypedPredicates = new ArrayList<>(nbPredicates);
        for (NamedTypedList predicate : predicates) {
            Encoder.tableOfPredicates.add(predicate.getName().getImage());
            final List arguments = predicate.getArguments();
            final List argType = new ArrayList<>(arguments.size());
            for (TypedSymbol arg : arguments) {
                final List types = arg.getTypes();
                if (types.size() > 1) {
                    final StringBuilder image = new StringBuilder("either");
                    for (Symbol type : types) {
                        image.append("~");
                        image.append(type.getImage());
                    }
                    argType.add(Encoder.tableOfTypes.indexOf(image.toString()));
                } else {
                    argType.add(Encoder.tableOfTypes.indexOf(types.get(0).getImage()));
                }
            }
            Encoder.tableOfTypedPredicates.add(argType);
        }
    }

    /**
     * Encodes all the function of a specified domain.
     *
     * @param domain the domain.
     */
    static void encodeFunctions(final Domain domain) {
        final List functions = domain.getFunctions();
        Encoder.tableOfFunctions = new ArrayList<>(functions.size());
        Encoder.tableOfTypedFunctions = new ArrayList<>(functions.size());
        for (NamedTypedList function : functions) {
            Encoder.tableOfFunctions.add(function.getName().getImage());
            List arguments = function.getArguments();
            List argType = new ArrayList<>(arguments.size());
            for (TypedSymbol argument : arguments) {
                List types = argument.getTypes();
                if (types.size() > 1) {
                    StringBuilder type = new StringBuilder("either");
                    for (Symbol type1 : types) {
                        type.append("~").append(type1.getImage());
                    }
                    argType.add(Encoder.tableOfTypes.indexOf(type.toString()));
                } else {
                    argType.add(Encoder.tableOfTypes.indexOf(types.get(0).getImage()));
                }
            }
            Encoder.tableOfTypedFunctions.add(argType);

        }
    }

    /**
     * Encodes a specified list of operators into its integer representation.
     *
     * @param ops the list of operators to encode.
     * @return encoded the list of operators encoded.
     */
    static List encodeOperators(final List ops) {
        return ops.stream().map(IntEncoding::encodeOperator).collect(Collectors.toList());
    }

    /**
     * Encodes a specified initial state into its integer representation.
     *
     * @param init the initial state to encode.
     * @return the initial state encoded.
     */
    static Set encodeInit(final List init) {
        return init.stream().map(IntEncoding::encodeExp).collect(Collectors.toCollection(LinkedHashSet::new));
    }

    /**
     * Encodes functions and costs from initial state into its integer representation.
     *
     * @param init the initial state encoded.
     * @return the encoded functions and costs from initial state.
     */
    static Map encodeFunctionCostInit(final Set init) {
        Map intFunctionCost = new HashMap<>();
        for (IntExp intExp : init) {
            if (intExp.getConnective().getImage().equals("=")) {
                intFunctionCost.put(intExp.getChildren().get(0),
                    Double.parseDouble(StringEncoder.toString(intExp.getChildren().get(1),
                        Encoder.tableOfConstants,
                        Encoder.tableOfTypes,
                        Encoder.tableOfPredicates,
                        Encoder.tableOfFunctions, "")));
            }
        }
        return intFunctionCost;
    }
    //TODO make more clean method:
    //init.stream().filter(x -> x.getConnective().getImage().equals("="))
    // .collect(Collectors.toMap(x.getChildren().get(0)));

    /**
     * Removes functions and costs from initial state integer representation.
     *
     * @param init the initial state to encode.
     * @return the initial state encoded without functions and costs.
     */
    static Set removeFunctionCost(final Set init) {
        return init.stream().filter(x -> !x.getConnective().getImage().equals("="))
            .collect(Collectors.toCollection(LinkedHashSet::new));
    }

    /**
     * Encodes a specified goal into its integer representation.
     *
     * @param goal the goal to encode.
     * @return the goal encoded.
     */
    static IntExp encodeGoal(final Exp goal) {
        return IntEncoding.encodeExp(goal);
    }


    /**
     * Encode an operator into its integer representation.
     *
     * @param op the operator to encode.
     * @return encoded operator.
     */
    private static IntOp encodeOperator(final Op op) {
        final IntOp intOp = new IntOp(op.getName().getImage(), op.getArity());
        // Encode the parameters of the operator
        final List variables = new ArrayList<>(op.getArity());
        for (int i = 0; i < op.getArity(); i++) {
            final TypedSymbol parameter = op.getParameters().get(i);
            final String typeImage = IntEncoding.toStringType(parameter.getTypes());
            final int type = Encoder.tableOfTypes.indexOf(typeImage);
            intOp.setTypeOfParameter(i, type);
            variables.add(parameter.getImage());
        }
        // Encode the preconditions of the operator
        final IntExp preconditions = IntEncoding.encodeExp(op.getPreconditions(), variables);
        intOp.setPreconditions(preconditions);
        // Encode the effects of the operator
        final IntExp effects = IntEncoding.encodeExp(op.getEffects(), variables);
        intOp.setEffects(effects);
        return intOp;
    }

    /**
     * Encodes an specified expression into its integer representation.
     *
     * @param exp the expression to encode.
     * @return the integer representation of the specified expression.
     */
    private static IntExp encodeExp(final Exp exp) {
        return IntEncoding.encodeExp(exp, new ArrayList<>());
    }

    /**
     * Encodes an specified expression into its integer representation.
     *
     * 

Notes: *

    *
  • equal predicate used specified value of -1.
  • *
  • variables used negative values in [-1,-infinity[.
  • *
*

* * @param exp the expression to encode. * @param variables the list of variable already encoded. * @return the integer representation of the specified expression. */ private static IntExp encodeExp(final Exp exp, final List variables) { final IntExp intExp = new IntExp(exp.getConnective()); switch (exp.getConnective()) { case EQUAL_ATOM: intExp.setPredicate(IntExp.EQUAL_PREDICATE); int[] args = new int[exp.getAtom().size()]; for (int i = 0; i < exp.getAtom().size(); i++) { final Symbol argument = exp.getAtom().get(i); if (argument.getKind().equals(Symbol.Kind.VARIABLE)) { args[i] = -variables.indexOf(argument.getImage()) - 1; } else { args[i] = Encoder.tableOfConstants.indexOf(argument.getImage()); } } intExp.setArguments(args); break; case FN_HEAD: final String functor = exp.getAtom().get(0).getImage(); intExp.setPredicate(Encoder.tableOfFunctions.indexOf(functor)); args = new int[exp.getAtom().size() - 1]; for (int i = 1; i < exp.getAtom().size(); i++) { final Symbol argument = exp.getAtom().get(i); if (argument.getKind().equals(Symbol.Kind.VARIABLE)) { args[i - 1] = -variables.indexOf(argument.getImage()) - 1; } else { args[i - 1] = Encoder.tableOfConstants.indexOf(argument.getImage()); } } intExp.setArguments(args); break; case ATOM: final String predicate = exp.getAtom().get(0).getImage(); intExp.setPredicate(Encoder.tableOfPredicates.indexOf(predicate)); args = new int[exp.getAtom().size() - 1]; for (int i = 1; i < exp.getAtom().size(); i++) { final Symbol argument = exp.getAtom().get(i); if (argument.getKind().equals(Symbol.Kind.VARIABLE)) { args[i - 1] = -variables.indexOf(argument.getImage()) - 1; } else { args[i - 1] = Encoder.tableOfConstants.indexOf(argument.getImage()); } } intExp.setArguments(args); break; case AND: case OR: for (int i = 0; i < exp.getChildren().size(); i++) { intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(i), variables)); } break; case FORALL: case EXISTS: final List newVariables = new ArrayList<>(variables); final List qvar = exp.getVariables(); final String type = IntEncoding.toStringType(qvar.get(0).getTypes()); int typeIndex = Encoder.tableOfTypes.indexOf(type); intExp.setType(typeIndex); intExp.setVariable(-variables.size() - 1); newVariables.add(qvar.get(0).getImage()); if (qvar.size() == 1) { intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(0), newVariables)); } else { qvar.remove(0); intExp.getChildren().add(IntEncoding.encodeExp(exp, newVariables)); } break; case F_EXP_T: if (!exp.getChildren().isEmpty()) { intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(0), variables)); } break; case FN_ATOM: case WHEN: case DURATION_ATOM: case LESS: case LESS_OR_EQUAL: case EQUAL: case GREATER: case GREATER_OR_EQUAL: case ASSIGN: case INCREASE: case DECREASE: case SCALE_UP: case SCALE_DOWN: case MUL: case DIV: case MINUS: case PLUS: case SOMETIME_AFTER: case SOMETIME_BEFORE: case WITHIN: case HOLD_AFTER: intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(0), variables)); intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(1), variables)); break; case AT_START: case AT_END: case MINIMIZE: case MAXIMIZE: case UMINUS: case NOT: case ALWAYS: case OVER_ALL: case SOMETIME: case AT_MOST_ONCE: case F_EXP: intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(0), variables)); break; case NUMBER: intExp.setValue(exp.getValue()); break; case ALWAYS_WITHIN: case HOLD_DURING: intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(0), variables)); intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(1), variables)); intExp.getChildren().add(IntEncoding.encodeExp(exp.getChildren().get(2), variables)); break; case TIME_VAR: case IS_VIOLATED: // Do nothing break; default: // do nothing } return intExp; } /** * Returns the string representation of a list of types. * * @param types the list of types. * @return the string representation of this type. */ private static String toStringType(final List types) { final StringBuilder str = new StringBuilder(); if (types.size() > 1) { str.append("either"); for (Symbol type : types) { str.append("~"); str.append(type.getImage()); } } else { str.append(types.get(0).getImage()); } return str.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy