package com.interview.basics.search; import com.interview.basics.model.collection.heap.BinaryArrayHeap; import java.util.*; /** * Created with IntelliJ IDEA. * User: stefanie * Date: 9/12/14 * Time: 1:50 PM */ public abstract class ASearcher<T, S extends ASearcher.State<T>, Input> { public interface State<T> { public T key(); } protected class Candidate implements Comparable<Candidate>{ public S state; public double cost; @Override public int compareTo(Candidate candidate) { if(this.cost > candidate.cost) return 1; else if(this.cost == candidate.cost) return 0; else return -1; } Candidate(S state, double cost) { this.state = state; this.cost = cost; } } public class Path<T>{ public Stack<T> path; public double weight; public Path(Stack<T> path, double weight) { this.path = path; this.weight = weight; } } protected boolean isDebug = false; protected Input input; protected Map<T, Double> gScore; protected Map<T, Double> hScore; protected Map<T, S> previous; public ASearcher(Input input){ this.input = input; } private void prepare(){ this.gScore = new HashMap<T, Double>(); this.hScore = new HashMap<T, Double>(); this.previous = new HashMap<T, S>(); } private double fScore(State c){ return gScore.get(c.key()) + hScore.get(c.key()); } protected abstract double heuristicEstimateDistance(S c, S t); protected abstract boolean isSame(S s, S t); protected abstract S[] nextState(S s); protected abstract double gScore(Candidate c, S t); public Path<T> pathTo(S s, S t){ Stack<T> path = new Stack<T>(); if(s.key().equals(t.key())) return new Path(path, 0.0); double weight = search(s, t); if(weight != -1){ for(S state = t; state != null && !state.equals(s); state = previous.get(state.key())){ path.push(state.key()); } } return new Path(path, weight); } public double search(S s, S t){ prepare(); Set<State> close = new HashSet<State>(); BinaryArrayHeap<Candidate> open = new BinaryArrayHeap<Candidate>(BinaryArrayHeap.MIN_HEAD); gScore.put(s.key(), 0.0); hScore.put(s.key(), heuristicEstimateDistance(s, t)); open.add(new Candidate(s, fScore(s))); while(open.size() != 0){ Candidate c = open.pollHead(); if(isDebug) System.out.printf("state: %s with score %2f\n", c.state.key(), c.cost); if(isSame(c.state, t)) return c.cost; if(!close.contains(c.state)){ close.add(c.state); S[] nextStates = nextState(c.state); if(nextStates == null) continue; for(int i = 0; i < nextStates.length; i++){ S e = nextStates[i]; if(e == null) continue; double ten = gScore(c, e); if(! gScore.containsKey(e.key()) || gScore.get(e.key()) > ten){ gScore.put(e.key(), ten); previous.put(e.key(), c.state); hScore.put(e.key(), heuristicEstimateDistance(e, t)); Candidate nc = new Candidate(e, fScore(e)); open.add(nc); } } } } return -1; } }