es.usc.citius.hipster.graph.GraphSearchProblem Maven / Gradle / Ivy
/*
* 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();
}
}
}
}
}
}