es.usc.citius.hipster.algorithm.MultiobjectiveLS.java Source code

Java tutorial

Introduction

Here is the source code for es.usc.citius.hipster.algorithm.MultiobjectiveLS.java

Source

/*
 * Copyright 2014 CITIUS <http://citius.usc.es>, University of Santiago de Compostela.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package es.usc.citius.hipster.algorithm;

import com.google.common.base.Predicate;
import com.google.common.base.Stopwatch;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import es.usc.citius.hipster.model.HeuristicNode;
import es.usc.citius.hipster.model.function.NodeExpander;

import java.util.*;

/**
 * <p>Implementation of the multi-objective label setting algorithm described
 * by Martins and Santos.</p>
 *
 * Original paper:
 * Martins, E. D. Q. V., & Santos, J. L. E. (1999). <b>"The labeling algorithm for the multiobjective shortest path problem"</b>. <i>Departamento de Matematica, Universidade de Coimbra, Portugal, Tech. Rep. TR-99/005</i>.
 *
 * @param <A> action type.
 * @param <S> state type.
 * @param <C> comparable cost used to compare states.
 * @param <N> type of the heuristic search node used.
 *           
 * @author Pablo Rodrguez Mier <<a href="mailto:pablo.rodriguez.mier@usc.es">pablo.rodriguez.mier@usc.es</a>>
 */
public class MultiobjectiveLS<A, S, C extends Comparable<C>, N extends HeuristicNode<A, S, C, N>>
        extends Algorithm<A, S, N> {
    private N initialNode;
    private NodeExpander<A, S, N> nodeExpander;

    public MultiobjectiveLS(N initialNode, NodeExpander<A, S, N> nodeExpander) {
        this.initialNode = initialNode;
        this.nodeExpander = nodeExpander;
    }

    /**
     * MultiobjectiveLS iterator. It expands one state at a time and updates
     * an internal table (nonDominated) which stores all non-dominated paths.
     * In order to find all non-dominated shortest path, the algorithm must be
     * executed until {@code iterator.hasNext() == false}. Paths can be recovered
     * with {@code iterator.getNonDominated.get(goalState)}
     */
    public class Iterator implements java.util.Iterator<N> {
        private Queue<N> queue = new LinkedList<N>();
        public Multimap<S, N> nonDominated;

        public Iterator() {
            queue = new PriorityQueue<N>();
            this.nonDominated = HashMultimap.create();
            this.queue.add(initialNode);
        }

        public boolean hasNext() {
            return !this.queue.isEmpty();
        }

        @Override
        public N next() {
            // 1- Take smallest lexicographical element from queue
            // 2- For all successors:
            //       - Build the new node, which represents a path from s to t.
            //      - Check all non dominated paths tracked from s to t. If
            //        this new node is dominated, discard it.
            //      - Add the new node, sorted by a lexicographical comparator
            //      - Check and remove dominated paths
            // Repeat 1.
            // Finally, the node that contains the goal state t, contains
            // the set of all non-dominated paths from s to t.
            N current = queue.poll();
            // Take successors
            for (N candidate : nodeExpander.expand(current)) {
                // Take non-dominated (nd) nodes associated to the current state
                // (i.e., all non-dominated paths from start to currentState
                Collection<N> ndNodes = this.nonDominated.get(candidate.state());
                // Check if the node is non-dominated
                if (!isDominated(candidate, ndNodes)) {
                    // Assign the candidate to the queue
                    this.queue.add(candidate);
                    // Add new non dominated path
                    ndNodes.add(candidate);
                    // Re-analyze dominance and remove new dominated paths
                    // Find all paths that can be dominated by the new non-dominated path
                    for (N dominated : dominatedBy(candidate, ndNodes)) {
                        ndNodes.remove(dominated);
                    }
                }
            }
            return current;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }

        private Collection<N> dominatedBy(N node, Iterable<N> nonDominated) {
            Collection<N> dominated = new HashSet<N>();
            for (N n : nonDominated) {
                if (node.getScore().compareTo(n.getScore()) < 0) {
                    dominated.add(n);
                }
            }
            return dominated;
        }

        private boolean isDominated(N node, Iterable<N> nonDominated) {
            // Compare all non-dominated nodes with node
            for (N nd : nonDominated) {
                if (nd.getScore().compareTo(node.getScore()) < 0) {
                    return true;
                }
            }
            return false;
        }

        public Queue<N> getQueue() {
            return queue;
        }

        public Multimap<S, N> getNonDominated() {
            return nonDominated;
        }
    }

    @Override
    public SearchResult search(Predicate<N> condition) {
        int iteration = 0;
        Iterator it = new Iterator();
        Stopwatch w = Stopwatch.createStarted();
        N currentNode;
        N goalNode = null;
        while (it.hasNext()) {
            iteration++;
            currentNode = it.next();
            if (condition.apply(currentNode)) {
                goalNode = currentNode;
            }
        }
        w.stop();
        if (goalNode != null) {
            Collection<N> solutions = it.nonDominated.get(goalNode.state());
            return new SearchResult(solutions, iteration, w);
        }
        return new SearchResult(Collections.<N>emptyList(), iteration, w);
    }

    @Override
    public java.util.Iterator<N> iterator() {
        return new Iterator();
    }
}