/* * Copyright 2010 Network Engine for Objects in Lund AB [neotechnology.com] * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.neo4j.graphalgo.competition.tobias; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import org.neo4j.graphalgo.competition.Path; import org.neo4j.graphalgo.competition.ShortestPath; import org.neo4j.graphdb.Node; class ShortestPathAlgorithm implements ShortestPath { private final int maxlength; private final RelationshipExpander expander; ShortestPathAlgorithm( int maxlength, RelationshipExpander expander ) { this.maxlength = maxlength; this.expander = expander; } public Path onePath( Node start, Node end ) { Collection<Path> paths = paths( true, start, end ); if ( paths.size() == 0 ) { return null; } assert paths.size() == 1 : "Returned more than one shortest path"; return paths.iterator().next(); } public Collection<Path> allPaths( Node start, Node end ) { return paths( false, start, end ); } private Collection<Path> paths( final boolean single, Node start, Node end ) { if ( start.equals( end ) ) { return Arrays.asList( PathType.singular( start ) ); } else { final EvaluationState sharedState = new EvaluationState( single ); EvaluationStage source, target; source = new InitialStage( sharedState, true, start ); target = new InitialStage( sharedState, false, end ); Collection<Path> result = new LinkedList<Path>(); for ( int depth = 0; depth < maxlength && result.isEmpty(); depth++ ) { source = source.evaluate( result, target ); if ( source == null || !result.isEmpty() ) break; if ( source.size > target.size ) // swap { EvaluationStage stage = source; source = target; target = stage; } } return Collections.unmodifiableCollection( result ); } } final class EvaluationState { private final boolean single; EvaluationState( boolean single ) { this.single = single; } } static abstract class EvaluationStage { final EvaluationState state; private final boolean isStart; final int size; EvaluationStage( EvaluationState state, boolean isStart, int size ) { this.state = state; this.isStart = isStart; this.size = size; } /* * Returns the new stage to replace this or null if no further * expansions can be made. */ EvaluationStage evaluate( Collection<Path> result, EvaluationStage target ) { throw new UnsupportedOperationException( "Not implemented yet." ); } } static class InitialStage extends EvaluationStage { final Node node; InitialStage( EvaluationState state, boolean isStart, Node node ) { super( state, isStart, 1 ); this.node = node; } } static class IncompleteStage extends EvaluationStage { IncompleteStage( EvaluationState state, boolean isStart ) { super( state, isStart, 0 ); // TODO: implement this } } static class FullStage extends EvaluationStage { FullStage( EvaluationState state, boolean isStart ) { super( state, isStart, 0 ); // TODO: implement this } } }