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

es.usc.citius.hipster.graph.GraphSearchProblem Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014 CITIUS , 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.graph;


import es.usc.citius.hipster.model.Transition;
import es.usc.citius.hipster.model.function.CostFunction;
import es.usc.citius.hipster.model.function.HeuristicFunction;
import es.usc.citius.hipster.model.function.TransitionFunction;
import es.usc.citius.hipster.model.function.impl.BinaryOperation;
import es.usc.citius.hipster.model.function.impl.ScalarOperation;
import es.usc.citius.hipster.model.impl.UnweightedNode;
import es.usc.citius.hipster.model.impl.WeightedNode;
import es.usc.citius.hipster.model.problem.ProblemBuilder;
import es.usc.citius.hipster.model.problem.SearchComponents;
import es.usc.citius.hipster.model.problem.SearchProblem;
import es.usc.citius.hipster.util.Function;

import java.util.ArrayList;

/**
 * Builder to generate a {@link es.usc.citius.hipster.model.problem.SearchProblem} but using
 * a HipsterGraph.
 * 
 * @author Pablo Rodríguez Mier
 */
public final class GraphSearchProblem {

    public static  FromVertex startingFrom(V vertex) {
        return new FromVertex(vertex);
    }

    public static class FromVertex {
        private V fromVertex;
        private V toVertex;

        public FromVertex goalAt(V vertex) {
            this.toVertex = vertex;
            return this;
        }

        private FromVertex(V fromVertex) {
            this.fromVertex = fromVertex;
        }

        public  CostType in(final HipsterGraph graph) {
            TransitionFunction tf;
            if (graph instanceof HipsterDirectedGraph) {
                final HipsterDirectedGraph dg = (HipsterDirectedGraph) graph;
                tf = new TransitionFunction() {
                    @Override
                    public Iterable> transitionsFrom(final V state) {
                        ArrayList> transitions = new ArrayList>();
                        for(GraphEdge edge : dg.outgoingEdgesOf(state)){
                            transitions.add(Transition.create(state, edge.getEdgeValue(), edge.getVertex2()));
                        }
                        return transitions;
                    }
                };
            } else {
                tf = new TransitionFunction() {
                    @Override
                    public Iterable> transitionsFrom(final V state) {
                        ArrayList> transitions = new ArrayList>();
                        for(GraphEdge edge : graph.edgesOf(state)){
                            V oppositeVertex = edge.getVertex1().equals(state) ? edge.getVertex2() : edge.getVertex1();
                            transitions.add(Transition.create(state, edge.getEdgeValue(), oppositeVertex));
                        }
                        return transitions;
                    }
                };
            }
            return new CostType(tf);
        }

        public class CostType {
            private TransitionFunction tf;

            private CostType(TransitionFunction tf) {
                this.tf = tf;
            }

            public HeuristicType takeCostsFromEdges() {
                // Try to automatically obtain weights from edges
                CostFunction cf = new CostFunction() {
                    @Override
                    public Double evaluate(Transition transition) {
                        E action = transition.getAction();

                        if (action instanceof Number) {
                            // Try to cast to number automatically
                            return ((Number) action).doubleValue();
                        } else if (action instanceof String){
                            // Try to parse to a number
                            try {
                                return Double.parseDouble((String) action);
                            } catch (NumberFormatException e){
                                throw new IllegalArgumentException("Exception ocurred when trying" +
                                        "to cast " + action + " to a number. Use the method " +
                                        "extractCostsFromEdges to define a custom evaluation strategy.", e);
                            }
                        } else {
                            // TODO: Throw exception instead?
                            // Assume uniform costs.
                            return 1d;
                            /*
                            throw new ClassCastException("The defined graph uses edges of type " +
                                    action.getClass() + " instead of Number. For custom edge costs" +
                                    " please use withGenericCosts method.");*/
                        }

                    }
                };
                return new HeuristicType(cf, BinaryOperation.doubleAdditionOp()).useScaleAlgebra(ScalarOperation.doubleMultiplicationOp());
            }

            public HeuristicType extractCostFromEdges(final Function extractor) {
                CostFunction cf = new CostFunction() {
                    @Override
                    public Double evaluate(Transition transition) {
                        return extractor.apply(transition.getAction());
                    }
                };
                return new HeuristicType(cf, BinaryOperation.doubleAdditionOp()).useScaleAlgebra(ScalarOperation.doubleMultiplicationOp());
            }

            public > HeuristicType useGenericCosts(BinaryOperation costAlgebra) {
                CostFunction cf = new CostFunction() {
                    @Override
                    public C evaluate(Transition transition) {
                        return (C) transition.getAction();
                    }
                };
                return new HeuristicType(cf, costAlgebra);
            }

            public SearchProblem> build() {
                return ProblemBuilder.create()
                        .initialState(fromVertex, toVertex)
                        .defineProblemWithExplicitActions()
                        .useTransitionFunction(tf)
                        .build();
            }

            public class HeuristicType> {
                private CostFunction cf;
                private BinaryOperation costAlgebra;
                private ScalarOperation scaleAlgebra;

                private HeuristicType(CostFunction cf, BinaryOperation costAlgebra) {
                    this.cf = cf;
                    this.costAlgebra = costAlgebra;
                }

                public HeuristicType useScaleAlgebra(ScalarOperation scaleAlgebra){
                    this.scaleAlgebra = scaleAlgebra;
                    return this;
                }

                public Final useHeuristicFunction(HeuristicFunction hf) {
                    return new Final(hf);
                }

                public SearchProblem> build() {
                    return ProblemBuilder.create()
                            .initialState(fromVertex)
                            .defineProblemWithExplicitActions()
                            .useTransitionFunction(tf)
                            .useGenericCostFunction(cf, costAlgebra)
                            .build();
                }

                public class Final {
                    private HeuristicFunction hf;

                    private Final(HeuristicFunction hf) {
                        this.hf = hf;
                    }

                    public SearchComponents components(){
                        return new SearchComponents(fromVertex, toVertex, cf, hf, tf, tf, costAlgebra, scaleAlgebra);
                    }

                    public SearchProblem> build() {
                        return ProblemBuilder.create()
                                .initialState(fromVertex)
                                .defineProblemWithExplicitActions()
                                .useTransitionFunction(tf)
                                .useGenericCostFunction(cf, costAlgebra)
                                .useHeuristicFunction(hf)
                                .build();
                    }
                }
            }
        }

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy