ShortestPathTest
Applies to: yFiles 2.6 print article email article

Type: Demo Source Code

Categories this article belongs to:
yFiles for Java > yFiles Basic > Demo Applications Source Code

Tutorial demo application from the demo/algo/ directory.

Compares the performance and results of some shortest path algorithms available in yFiles.

/****************************************************************************
 **
 ** This file is part of yFiles-2.6. 
 ** 
 ** yWorks proprietary/confidential. Use is subject to license terms.
 **
 ** Redistribution of this file or of an unauthorized byte-code version
 ** of this file is strictly forbidden.
 **
 ** Copyright (c) 2000-2008 by yWorks GmbH, Vor dem Kreuzberg 28, 
 ** 72070 Tuebingen, Germany. All rights reserved.
 **
 ***************************************************************************/
package demo.algo;


import demo;
import y.algo.GraphChecker;
import y.algo.ShortestPaths;
import y.base.Edge;
import y.base.EdgeCursor;
import y.base.Graph;
import y.base.Node;
import y.base.NodeCursor;
import y.util.D;
import y.util.Timer;
import y.util.YRandom;


/**
 * This class compares the performance and results of some shortest path
 * algorithms available in yFiles.
 */
public class ShortestPathTest {
  static long seed = 0;

  private Timer timerA = new Timer( false );
  private Timer timerB = new Timer( false );
  private Timer timerC = new Timer( false );
  private Timer timerD = new Timer( false );

  /**
   * programm launcher. Accepts a random seed on the command line.
   */
  public static void main( String[] args ) {
    try {
      seed = Long.parseLong( args[0] );
    }
    catch ( Exception ex ) {
    }

    (new ShortestPathTest()).doIt();

  }

  private void doIt() {
    testSP( true );
    testAllPairs( true );
    testSingleSourceSingleSink( true );
    testSP( false );
    testAllPairs( false );
    testSingleSourceSingleSink( false );
  }


  /**
   * Tests single source single sink shortest path algorithms
   */
  private void testSingleSourceSingleSink( boolean directed ) {
    D.bug( ">>> testSingleSourceSingleSink(" + directed + ")" );

    timerA.reset();
    timerB.reset();

    YRandom random = new YRandom( seed );

    RandomGraphGenerator rg = new RandomGraphGenerator( seed );

    rg.allowCycles( true );
    rg.setNodeCount( random.nextInt( 200 ) );
    rg.setEdgeCount( random.nextInt( 1600 ) );

    Graph G = rg.generate();

    double[] cost = new double[G.E()];
    double[] distA = new double[G.N()];
    double[] distB = new double[G.N()];

    for ( EdgeCursor ec = G.edges(); ec.ok(); ec.next() ) {
      Edge e = ec.edge();
      int eid = e.index();
      cost[eid] = random.nextInt( 10000 );
    }

    for ( NodeCursor nc = G.nodes(); nc.ok(); nc.next() ) {
      Node v = nc.node();
      if ( v.index() % 60 == 59 ) D.bug( "." );
      else D.bu( "." );
      for ( NodeCursor ncc = G.nodes(); ncc.ok(); ncc.next() ) {
        Node w = ncc.node();
        timerA.start();
        ShortestPaths.dijkstra( G, v, directed, cost, distA );
        timerA.stop();
        timerB.start();
        double dist = ShortestPaths.singleSourceSingleSink( G, v, w, directed, cost, new Edge[G.N()] );
        timerB.stop();
        if ( distA[w.index()] != dist ) {
          D.bug( "\ndist mismatch: v = " + v + "  w = " + w );
          D.bug( "distA = " + distA[w.index()] + "  dist = " + dist );
        }
      }
    }

    D.bug( "\ndijkstra= " + timerA + "\nsource-target-dijkstra " + timerB );

    D.bug( "<<< testSingleSourceSingleSink(" + directed + ")\n\n" );
  }


  /**
   * Compares the builtin all pairs shortest path algorithm with
   * multiple calls to single source shortest path algorithms
   */
  private void testAllPairs( boolean directed ) {
    D.bug( ">>> testAllPairs(" + directed + ")" );

    timerA.reset();
    timerB.reset();

    YRandom random = new YRandom( seed );

    RandomGraphGenerator rg = new RandomGraphGenerator( seed );

    rg.allowCycles( true );
    rg.setNodeCount( random.nextInt( 1000 ) );
    rg.setEdgeCount( random.nextInt( 100000 ) );

    Graph G = rg.generate();

    double[] cost = new double[G.E()];
    double[][] distA = new double[G.N()][G.N()];
    double[] distB = new double[G.N()];


    for ( EdgeCursor ec = G.edges(); ec.ok(); ec.next() ) {
      Edge e = ec.edge();
      int eid = e.index();
      cost[eid] = random.nextInt( 100000 );
    }


    timerA.start();
    ShortestPaths.allPairs( G, directed, cost, distA );
    timerA.stop();


    for ( NodeCursor nc = G.nodes(); nc.ok(); nc.next() ) {
      Node v = nc.node();

      timerB.start();
      ShortestPaths.singleSource( G, v, directed, cost, distB );
      timerB.stop();
      if ( v.index() % 60 == 59 ) D.bug( "." );
      else D.bu( "." );

      for ( NodeCursor ncc = G.nodes(); ncc.ok(); ncc.next() ) {
        Node w = ncc.node();
        if ( distA[v.index()][w.index()] != distB[w.index()] ) {
          D.bug( "dist mismatch! v = " + v + "  w = " + w );
          D.bug( "distA = " + distA[v.index()][w.index()] + "   distB = " + distB[w.index()] );
          System.exit( 1 );
        }

      }
    }
    D.bug( "\nallPairs = " + timerA + "\nsingleSource " + timerB );

    D.bug( "<<< testAllPairs(" + directed + ")\n\n" );
  }

  /**
   * calls testSP with different random seeds.
   */
  private void testSP( boolean directed ) {
    D.bug( ">>> testSP(" + directed + ")" );

    timerA.reset();
    timerB.reset();
    timerC.reset();
    timerD.reset();

    timerD.start();
    for ( int i = 0; i < 100; i++ ) {
      if ( i % 60 == 59 ) D.bug( "." );
      else D.bu( "." );

      testSP( i, directed );
    }
    D.bug( "" );
    timerD.stop();
    D.bug( "overall = " + timerD + "\ndijkstra = " + timerA + "\nbellmanFord = " + timerB + "\nacyclic = " + timerC );

    D.bug( "<<< testSP(" + directed + ")\n\n" );

  }

  /**
   * Compares dijkstra with bellman-ford shortest path algorithms and with
   * special routine for acyclic graphs.
   */
  private void testSP( int loop, boolean directed ) {
    YRandom random = new YRandom( seed + loop );

    RandomGraphGenerator rg = new RandomGraphGenerator( seed + loop );

    rg.allowCycles( false );
    rg.setNodeCount( random.nextInt( 100 ) );
    rg.setEdgeCount( random.nextInt( 5555 ) );

    Graph G = rg.generate();

    //D.bug("\nn="  + G.N() + " m=" + G.E());

    double[] cost = new double[G.edgeCount()];
    double[] distA = new double[G.nodeCount()];
    double[] distB = new double[G.nodeCount()];
    double[] distC = new double[G.nodeCount()];

    for ( EdgeCursor ec = G.edges(); ec.ok(); ec.next() ) {
      Edge e = ec.edge();
      int eid = e.index();
      cost[eid] = random.nextInt( 100000 );
    }

    for ( NodeCursor nc = G.nodes(); nc.ok(); nc.next() ) {
      Node s = nc.node();
      int sid = s.index();
      timerA.start();
      ShortestPaths.dijkstra( G, s, directed, cost, distA );
      timerA.stop();

      timerB.start();
      boolean resultB = ShortestPaths.bellmanFord( G, s, directed, cost, distB );
      timerB.stop();


      boolean resultC = GraphChecker.isAcyclic( G ) && directed;
      timerC.start();
      if ( resultC ) ShortestPaths.acyclic( G, s, cost, distC );
      timerC.stop();
      if ( resultB ) {
        for ( NodeCursor ncc = G.nodes(); ncc.ok(); ncc.next() ) {
          Node w = ncc.node();
          int wid = w.index();

          if ( distA[wid] != distB[wid] ) {
            D.bug( "dist mismatch" );
            D.bug( "" + w + " dijkstra: " + distA[wid] + " bellmanford: " + distB[wid] );
            System.exit( 1 );
          }
        }
      }

      if ( resultC ) {
        for ( NodeCursor ncc = G.nodes(); ncc.ok(); ncc.next() ) {
          Node w = ncc.node();
          int wid = w.index();

          if ( distA[wid] != distC[wid] ) {
            D.bug( "dist mismatch" );
            D.bug( "" + w + " dijkstra: " + distA[wid] + " acyclic: " + distC[wid] );
            System.exit( 1 );
          }
        }
      }

    }
  }

}

Keywords: ShortestPaths - algorithm - shortest - path - performance - Dijkstra - Bellman - Ford - ShortestPathTest

Provide feedback:
How useful was this article?    less 1 2 3 4 5 more
Email address (optional):
COPYRIGHT © 2008 yWorks · ALL RIGHTS RESERVED imprint | top | home