// file: $isip/class/dstr/BiGraph/BiGraphDiagnose.h
// version: $Id: BiGraphDiagnose.h 10636 2007-01-26 22:18:09Z tm334 $
//

// make sure definitions are only made once
//
#ifndef ISIP_BI_GRAPH_DIAGNOSE
#define ISIP_BI_GRAPH_DIAGNOSE

// isip include files
//
#ifndef ISIP_BI_GRAPH
#include "BiGraph.h"
#endif

#ifndef ISIP_DI_GRAPH
#include "DiGraph.h"
#endif

#ifndef ISIP_FILENAME
#include <Filename.h>
#endif

// BiGraphDiagnose: a class that contains the diagnose method of BiGraph class.
//
template<class TObject>
class BiGraphDiagnose : public BiGraph<TObject> {

  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:
  
  // define the class name
  //

  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------

  // default values
  //
    
  // default arguments to methods
  //
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // define the object used to hold graph topology in read and write
  //
  typedef Triple< Pair<Long, Long>, Float, Boolean> TopoTriple;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:

  // methods: name
  //
  static const String& name() {
    return BiGraph<TObject>::name();
  }

  // other static methods
  //
  static boolean diagnose(Integral::DEBUG debug_level);

  // debug methods
  //  these methods are omitted since this class does not have data
  //  members and operations  
  //
  
  // destructor/constructor(s):
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // assign methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // operator= methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //  

  // i/o methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // equality methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //

  // memory-management methods:
  //  these methods are omitted since this class does not have data
  //  members and operations
  //
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods
  //
  //---------------------------------------------------------------------------

  //  these methods are omitted since this class does not have data
  //  members and operations
  //
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------
private:

}; 

// below are all the methods for the PairDiagnose template class
//

//-----------------------------------------------------------------------------
//
// required static methods
//
//-----------------------------------------------------------------------------

// method: diagnose
//
// arguments:
//  Integral::DEBUG level: (input) debug level for diagnostics
//
// return: a boolean value indicating status
//
template<class TObject>
boolean BiGraphDiagnose<TObject>::diagnose(Integral::DEBUG level_a) {

  //----------------------------------------------------------------------
  //
  // 0. preliminaries
  //
  //----------------------------------------------------------------------

  // output the class name
  //
  if (level_a > Integral::NONE) {
    SysString output(L"diagnosing class ");
    output.concat(BiGraph<TObject>::CLASS_NAME);
    output.concat(L": ");
    Console::put(output);
    Console::increaseIndention();
  }

  //---------------------------------------------------------------------
  //
  // 1. required public methods
  //
  //---------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing required public methods...\n");
    Console::increaseIndention();
  }

  // test the debug methods
  //
  BiGraph<TObject>::setDebug(BiGraph<TObject>::debug_level_d);
  
  // test constructors and memory management methods
  //
  BiGraph<Char> def_graph;

  // create an arc from the first to the last node
  //
  def_graph.insertArc(def_graph.getStart(), def_graph.getTerm(), false, 0.75);

  // copy constructor
  //
  BiGraph<Char> copy_graph(def_graph);

  // the copy graph should now have an arc from its start node to its terminal
  // node with a weight of 0.75
  //
  BiGraphArc<Char>* cstr_arc = (BiGraphArc<Char>*)NULL;
  if ((cstr_arc = copy_graph.getStart()->getFirstChild()) == 
      (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }
  if ((cstr_arc->getVertex() != copy_graph.getTerm()) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }

  // the copy graph should also have an arc from its term node to its start
  // node with a weight of 0.75
  //
  cstr_arc = (BiGraphArc<Char>*)NULL;
  if ((cstr_arc = copy_graph.getTerm()->getFirstParent()) == 
      (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }
  if ((cstr_arc->getVertex() != copy_graph.getStart()) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }  

  // check the constructors and destructors for allocating on the dynamic
  // memory heap
  //
  BiGraph<Char>* def_dyn_graph = new BiGraph<Char>;

  // create an arc from the first to the last node
  //
  def_dyn_graph->insertArc(def_dyn_graph->getStart(), def_dyn_graph->getTerm(),
			false, 0.75);

  // copy constructor
  //
  BiGraph<Char>* copy_dyn_graph = new BiGraph<Char>(*def_dyn_graph);

  // the copy graph should now have an arc from its start node to its terminal
  // node with a weight of 0.75
  //
  cstr_arc = (BiGraphArc<Char>*)NULL;
  if ((cstr_arc = copy_dyn_graph->getStart()->getFirstChild())
      == (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }
  if ((cstr_arc->getVertex() != copy_dyn_graph->getTerm()) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }

  // the copy graph should also have an arc from its term node to its start
  // node with a weight of 0.75
  //
  cstr_arc = (BiGraphArc<Char>*)NULL;
  if ((cstr_arc = copy_dyn_graph->getTerm()->getFirstParent())
      == (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }
  if ((cstr_arc->getVertex() != copy_dyn_graph->getStart()) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
    return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			 __LINE__);
  }  

  // clear the respective graphs
  //
  ((BiGraph<TObject>)copy_graph).clear(Integral::FREE);
  ((BiGraph<TObject>*)def_dyn_graph)->clear(Integral::FREE);
  def_graph.clear(Integral::FREE);
  copy_dyn_graph->clear(Integral::FREE);
  
  // see if we can dynamically delete
  //
  delete def_dyn_graph;
  delete copy_dyn_graph;

  {
    // test constructors and memory management methods in USER-allocation
    //
    BiGraph<Char> def_graph(DstrBase::USER);
    
    // create an arc from the first to the last node
    //
    def_graph.insertArc(def_graph.getStart(), def_graph.getTerm(),
			false, 0.75);
    
    // copy constructor
    //
    BiGraph<Char> copy_graph(def_graph);
    
    // the copy graph should now have an arc from its start node to its
    // terminal node with a weight of 0.75
    //
    BiGraphArc<Char>* cstr_arc = (BiGraphArc<Char>*)NULL;
    if ((cstr_arc = copy_graph.getStart()->getFirstChild()) == 
	(BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }
    if ((cstr_arc->getVertex() != copy_graph.getTerm()) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }

    // the copy graph should also have an arc from its term node to its
    // start node with a weight of 0.75
    //
    cstr_arc = (BiGraphArc<Char>*)NULL;
    if ((cstr_arc = copy_graph.getTerm()->getFirstParent()) == 
	(BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }
    if ((cstr_arc->getVertex() != copy_graph.getStart()) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }    
    
    // check the constructors and destructors for allocating on the dynamic
    // memory heap in USER-allocation mode
    //
    BiGraph<Char>* def_dyn_graph = new BiGraph<Char>(DstrBase::USER);
    
    // create an arc from the first to the last node
    //
    def_dyn_graph->insertArc(def_dyn_graph->getStart(),
			     def_dyn_graph->getTerm(), false, 0.75);
    
    // copy constructor
    //
    BiGraph<Char>* copy_dyn_graph = new BiGraph<Char>(*def_dyn_graph);
    
    // the copy graph should now have an arc from its start node to its
    // terminal node with a weight of 0.75
    //
    cstr_arc = (BiGraphArc<Char>*)NULL;
    if ((cstr_arc = copy_dyn_graph->getStart()->getFirstChild())
	== (BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }
    if ((cstr_arc->getVertex() != copy_dyn_graph->getTerm()) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }

    // the copy graph should also have an arc from its term node to its
    // start node with a weight of 0.75
    //
    cstr_arc = (BiGraphArc<Char>*)NULL;
    if ((cstr_arc = copy_dyn_graph->getTerm()->getFirstParent())
	== (BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }
    if ((cstr_arc->getVertex() != copy_dyn_graph->getStart()) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
      return Error::handle(name(), L"constructors", Error::TEST, __FILE__,
			   __LINE__);
    }    

    // clear the respective graphs
    //
    copy_graph.clear(Integral::FREE);
    def_dyn_graph->clear(Integral::FREE);
    def_graph.clear(Integral::FREE);
    copy_dyn_graph->clear(Integral::FREE);
    
    // see if we can dynamically delete
    //
    delete def_dyn_graph;
    delete copy_dyn_graph;    
  }

  // test large allocation construction and deletion in both modes
  //
  if (level_a >= Integral::ALL) {

    // output an informative message
    //
    Console::put(L"\ntesting large chunk memory allocation and deletion:\n");
    
    // set the memory to a strange block size so we can hopefully catch any
    // frame overrun errors
    //
    BiGraph<TObject>::setGrowSize((long)731);
    
    // loop for a large number of times creating and deleting a large number
    // of vertices at each loop
    //
    for (long j = 1; j <= 100; j++) {
      BiGraph<TObject>** self_graphs = new BiGraph<TObject>*[j * 50];
      BiGraph<TObject>** graphs = new BiGraph<TObject>*[j * 50];
      
      // create the vertices
      //
      for (long i = 0; i < j * 50; i++) {
	self_graphs[i] = new BiGraph<TObject>();
	graphs[i] = new BiGraph<TObject>(DstrBase::USER);
      }
      
      // delete nodes
      //
      for (long i = (j * 50) - 1; i >= 0; i--) {
	delete self_graphs[i];
	delete graphs[i];
      }
      
      delete [] self_graphs;
      delete [] graphs;
    }

    // perform the same test using the new[] and delete [] operators
    //
    for (long j = 1; j <= 100; j++) {
      
      // allocate a large number of nodes
      //
      BiGraph<TObject>* self_graphs = new BiGraph<TObject>[j * 50];
      //BiGraph<TObject>* graphs = new BiGraph<TObject>[j * 50](DstrBase::USER);

      // clean up memory
      //
      delete [] self_graphs;
      //delete [] graphs;
    }
  }

  // test assign method in SYSTEM-allocation mode
  //
  BiGraph<Char> assn_graph_0;

  // create an arc from the first to a common node
  //
  Char* char1 = new Char('k');
  assn_graph_0.insertArc(assn_graph_0.getStart(),
			 assn_graph_0.insertVertex(char1),
			 false, 0.75);

  BiGraphVertex<Char>* tmp_vertex;
  if ((tmp_vertex = (BiGraphVertex<Char>*)assn_graph_0.getFirst()) ==
      (BiGraphVertex<Char>*)NULL) {
    return Error::handle(name(), L"insertArc", Error::TEST, __FILE__,
			 __LINE__);
  }
  assn_graph_0.insertArc(tmp_vertex, assn_graph_0.getTerm(),
			 false, -0.75);

  BiGraph<Char> assn_graph_1;
  assn_graph_1.assign(assn_graph_0);

  // the assigned graph should now have an arc from its start node to the
  // char1 with a weight of 0.75 and an arc from the char1 to the terminal
  // node with a weight of -0.75
  //
  cstr_arc = (BiGraphArc<Char>*)NULL;

  if ((cstr_arc = assn_graph_1.getStart()->getFirstChild())
      == (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }

  if ((cstr_arc->getVertex()->getItem()->ne(*char1)) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }

  if ((cstr_arc = cstr_arc->getVertex()->getFirstChild())
      == (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }

  if ((cstr_arc->getVertex() != assn_graph_1.getTerm()) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), -0.75)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }

  // the assigned graph should also have an arc from the char1 node to the
  // start with a weight of 0.75 and an arc from the term to the char1
  // node with a weight of -0.75
  //
  cstr_arc = (BiGraphArc<Char>*)NULL;

  if ((cstr_arc = assn_graph_1.getTerm()->getFirstParent())
      == (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }

  if ((cstr_arc->getVertex()->getItem()->ne(*char1)) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), -0.75)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }

  if ((cstr_arc = cstr_arc->getVertex()->getFirstParent())
      == (BiGraphArc<Char>*)NULL) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }

  if ((cstr_arc->getVertex() != assn_graph_1.getStart()) ||
      cstr_arc->getEpsilon() ||
      !Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
  }  

  // test the assign from a DiGraph
  //
  DiGraph<Char> digraph_0;
  
  // create an arc from the first to a common node
  //
  Char* char_a = new Char('a');
  Char* char_b = new Char('b');
  
  GraphVertex<Char>* vertex_a = digraph_0.insertVertex(char_a);
  GraphVertex<Char>* vertex_b = digraph_0.insertVertex(char_b);  
  
  digraph_0.insertArc(digraph_0.getStart(), vertex_a, false, 1.0);
  digraph_0.insertArc(vertex_a, vertex_a, false, 0.5);
  digraph_0.insertArc(vertex_a, vertex_b, false, 0.5);
  digraph_0.insertArc(vertex_b, digraph_0.getTerm(), false, 1.0);    

  // assign it to the BiGraph
  //
  BiGraph<Char> bigraph_0;
  bigraph_0.assign(digraph_0);

  // get the term vertex
  //
  BiGraphVertex<Char>* temp_vertex = bigraph_0.getTerm();

  // check for TREM -> 'b'
  //
  temp_vertex->gotoFirstParent();
  BiGraphArc<Char>* temp_arc = temp_vertex->getCurrParent();
  if (temp_arc->getVertex()->getItem()->ne(*char_b)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  // check for 'b' -> 'a'
  //
  temp_vertex = temp_arc->getVertex();
  temp_vertex->gotoFirstParent();
  temp_arc = temp_vertex->getCurrParent();
  if (temp_arc->getVertex()->getItem()->ne(*char_a)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  // check for 'a' -> start and 'a' -> 'a'
  //
  temp_vertex = temp_arc->getVertex();
  temp_vertex->gotoFirstParent();
  temp_arc = temp_vertex->getCurrParent();
  if (temp_arc->getVertex() != bigraph_0.getStart()) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  temp_vertex->gotoNextParent();
  temp_arc = temp_vertex->getCurrParent();
  if (temp_arc->getVertex()->getItem()->ne(*char_a)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }  
  
  // clean up memory
  //
  delete char1;
  delete char_a;
  delete char_b;  

  {
    // test assign method in USER-allocation mode
    //
    BiGraph<Char> assn_graph_0(DstrBase::USER);
    
    // create an arc from the first to a common node
    //
    Char* char1 = new Char('k');
    assn_graph_0.insertArc(assn_graph_0.getStart(),
			   assn_graph_0.insertVertex(char1),
			   false, 0.75);
    
    BiGraphVertex<Char>* tmp_vertex;
    if ((tmp_vertex = (BiGraphVertex<Char>*)assn_graph_0.getFirst()) ==
	(BiGraphVertex<Char>*)NULL) {
      return Error::handle(name(), L"insertArc", Error::TEST, __FILE__,
			   __LINE__);
    }
    assn_graph_0.insertArc(tmp_vertex, assn_graph_0.getTerm(),
			   false, -0.75);
    
    BiGraph<Char> assn_graph_1(DstrBase::USER);
    assn_graph_1.assign(assn_graph_0);
    
    // the assigned graph should now have an arc from its start node to the
    // char1 with a weight of 0.75 and an arc from the char1 to the terminal
    // node with a weight of -0.75
    //
    cstr_arc = (BiGraphArc<Char>*)NULL;
    
    if ((cstr_arc = assn_graph_1.getStart()->getFirstChild())
	== (BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			   __LINE__);
    }
    
    if ((cstr_arc->getVertex()->getItem()->ne(*char1)) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			   __LINE__);
    }
    
    if ((cstr_arc = cstr_arc->getVertex()->getFirstChild())
	== (BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			 __LINE__);
    }

    if ((cstr_arc->getVertex() != assn_graph_1.getTerm()) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), -0.75)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			   __LINE__);
    }

    // the assigned graph should also have an arc from the char1 node to the
    // start with a weight of 0.75 and an arc from the term to the char1
    // node with a weight of -0.75
    //
    cstr_arc = (BiGraphArc<Char>*)NULL;
    
    if ((cstr_arc = assn_graph_1.getTerm()->getFirstParent())
	== (BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			   __LINE__);
    }
    
    if ((cstr_arc->getVertex()->getItem()->ne(*char1)) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), -0.75)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			   __LINE__);
    }
    
    if ((cstr_arc = cstr_arc->getVertex()->getFirstParent())
	== (BiGraphArc<Char>*)NULL) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			   __LINE__);
    }
    
    if ((cstr_arc->getVertex() != assn_graph_1.getStart()) ||
	cstr_arc->getEpsilon() ||
	!Integral::almostEqual((double)cstr_arc->getWeight(), 0.75)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__,
			   __LINE__);
    }


    // test the assign from a DiGraph
    //
    DiGraph<Char> digraph_0(DstrBase::USER);
    
    // create an arc from the first to a common node
    //
    Char* char_a = new Char('a');
    Char* char_b = new Char('b');
    
    GraphVertex<Char>* vertex_a = digraph_0.insertVertex(char_a);
    GraphVertex<Char>* vertex_b = digraph_0.insertVertex(char_b);  
    
    digraph_0.insertArc(digraph_0.getStart(), vertex_a, false, 1.0);
    digraph_0.insertArc(vertex_a, vertex_a, false, 0.5);
    digraph_0.insertArc(vertex_a, vertex_b, false, 0.5);
    digraph_0.insertArc(vertex_b, digraph_0.getTerm(), false, 1.0);    
    
    // assign it to the BiGraph
    //
    BiGraph<Char> bigraph_0(DstrBase::USER);
    bigraph_0.assign(digraph_0);
    
    // get the term vertex
    //
    BiGraphVertex<Char>* temp_vertex = bigraph_0.getTerm();
    
    // check for TREM -> 'b'
    //
    temp_vertex->gotoFirstParent();
    BiGraphArc<Char>* temp_arc = temp_vertex->getCurrParent();
    if (temp_arc->getVertex()->getItem()->ne(*char_b)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    
    // check for 'b' -> 'a'
    //
    temp_vertex = temp_arc->getVertex();
    temp_vertex->gotoFirstParent();
    temp_arc = temp_vertex->getCurrParent();
    if (temp_arc->getVertex()->getItem()->ne(*char_a)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    
    // check for 'a' -> start and 'a' -> 'a'
    //
    temp_vertex = temp_arc->getVertex();
    temp_vertex->gotoFirstParent();
    temp_arc = temp_vertex->getCurrParent();
    if (temp_arc->getVertex() != bigraph_0.getStart()) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    
    temp_vertex->gotoNextParent();
    temp_arc = temp_vertex->getCurrParent();
    if (temp_arc->getVertex()->getItem()->ne(*char_a)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }  
    
    // clean up memory
    //
    delete char1;
    delete char_a;
    delete char_b;  
  }
  
  // test the assign method in SYSTEM mode
  //
  
  // -------------------------------------------------
  // START -(epi) -> a
  // a     -(0.1) -> a
  // a     -(0.5) -> b
  // b     -(0.7) -> b
  // b     -(epi) -> TERM 
  //
  // START <-(epi) - a
  // a     <-(0.1) - a
  // a     <-(0.5) - b
  // b     <-(0.7) - b
  // b     <-(epi) - TERM   
  // -------------------------------------------------

  // create the graph items
  //
  Char* a = new Char('a');
  Char* b = new Char('b');
  TopoTriple* triple;
  
  // create the list of arcs
  //
  DoubleLinkedList<TopoTriple> arcs;
	
  Float float_00(0.0);
  Boolean bool_00(true);
  Pair<Long, Long> pair_00(BiGraph<Char>::START_INDEX, 0);
  triple = new TopoTriple(pair_00, float_00, bool_00);
  arcs.insert(triple);
  delete triple;

  Float float_01(0.1);
  Boolean bool_01(false);
  Pair<Long, Long> pair_01(0, 0);
  triple = new TopoTriple(pair_01, float_01, bool_01);
  arcs.insert(triple);
  delete triple;

  Float float_02(0.5);
  Boolean bool_02(false);
  Pair<Long, Long> pair_02(0, 1);
  triple = new TopoTriple(pair_02, float_02, bool_02);
  arcs.insert(triple);
  delete triple;

  Float float_03(0.7);
  Boolean bool_03(false);
  Pair<Long, Long> pair_03(1, 1);
  triple = new TopoTriple(pair_03, float_03, bool_03);
  arcs.insert(triple);
  delete triple;

  Float float_04(0.0);
  Boolean bool_04(true);
  Pair<Long, Long> pair_04(1, BiGraph<Char>::TERM_INDEX);
  triple = new TopoTriple(pair_04, float_04, bool_04);
  arcs.insert(triple);
  delete triple;  

  // create the list of data elements
  //
  DoubleLinkedList<Char> dlist;
  dlist.insert(a);
  dlist.insert(b);  
  
  // create the graph using the lists
  //
  BiGraph<Char> assgn_graph;
  assgn_graph.assign(dlist, arcs);

  // the graph should contain 'a' and 'b'
  //
  if (!assgn_graph.contains(a)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }
  if (!assgn_graph.contains(b)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }  

  // the start vertex should have an epsilon transition to 'a'
  //
  assgn_graph.gotoFirst();
  if (!assgn_graph.getStart()->getFirstChild()->getVertex()->getItem()->eq(*a)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  // the 'a' vertex should have an epsilon transition to start
  //
  BiGraphVertex<Char>* ver_test =
    assgn_graph.getStart()->getFirstChild()->getVertex();
  if (ver_test->getFirstParent()->getVertex() != assgn_graph.getStart()) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }  

  // 'a' should have a transition to 'b' and itself
  //
  assgn_graph.gotoFirst();
  BiGraphVertex<Char>* ver_00 = (BiGraphVertex<Char>*)assgn_graph.getCurr();
  ver_00->gotoFirstChild();
  BiGraphArc<Char>* arc_00 = ver_00->getCurrChild();
  if (!arc_00->getVertex()->getItem()->eq(*a)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }
  BiGraphArc<Char>* arc_01 = ver_00->getNextChild();
  if (!arc_01->getVertex()->getItem()->eq(*b)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  // 'a' should have transition to start and itself
  //
  ver_00->gotoFirstParent();
  arc_00 = ver_00->getCurrParent();
  if (arc_00->getVertex() != assgn_graph.getStart()) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }
  arc_01 = ver_00->getNextParent();
  if (!arc_01->getVertex()->getItem()->eq(*a)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  // 'b' should have an epsilon transition to the term vertex and itself
  //
  assgn_graph.gotoNext();
  BiGraphVertex<Char>* ver_01 = (BiGraphVertex<Char>*)assgn_graph.getCurr();
  ver_01->gotoFirstChild();
  BiGraphArc<Char>* arc_02 = ver_01->getCurrChild();
  if (!arc_02->getVertex()->getItem()->eq(*b)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }
  BiGraphArc<Char>* arc_03 = ver_01->getNextChild();
  if (arc_03->getVertex() != assgn_graph.getTerm()) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  // 'b' should have an a transition to 'a' and itself
  //
  ver_01 = (BiGraphVertex<Char>*)assgn_graph.getCurr();
  ver_01->gotoFirstParent();
  arc_02 = ver_01->getCurrParent();
  if (!arc_02->getVertex()->getItem()->eq(*a)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }

  arc_03 = ver_01->getNextParent();
  if (!arc_03->getVertex()->getItem()->eq(*b)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }  

  // the term vertex should have a transition to 'b'
  //
  ver_01 = assgn_graph.getTerm();
  ver_01->gotoFirstParent();
  arc_02 = ver_01->getCurrParent();
  if (!arc_02->getVertex()->getItem()->eq(*b)) {
    return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
  }
    
  // clean up
  //
  delete a;
  delete b;
  arcs.clear(Integral::FREE);
  dlist.clear(Integral::FREE);
  assgn_graph.clear(Integral::FREE);

  {
    // -------------------------------------------------
    // START -(epi) -> a
    // a     -(0.1) -> a
    // a     -(0.5) -> b
    // b     -(0.7) -> b
    // b     -(epi) -> TERM 
    //
    // START <-(epi) - a
    // a     <-(0.1) - a
    // a     <-(0.5) - b
    // b     <-(0.7) - b
    // b     <-(epi) - TERM   
    // -------------------------------------------------
    
    // create the graph items
    //
    Char* a = new Char('a');
    Char* b = new Char('b');
    TopoTriple* triple;
  
    // create the list of arcs
    //
    DoubleLinkedList<TopoTriple> arcs;
    
    Float float_00(0.0);
    Boolean bool_00(true);
    Pair<Long, Long> pair_00(BiGraph<Char>::START_INDEX, 0);
    triple = new TopoTriple(pair_00, float_00, bool_00);
    arcs.insert(triple);
    delete triple;
    
    Float float_01(0.1);
    Boolean bool_01(false);
    Pair<Long, Long> pair_01(0, 0);
    triple = new TopoTriple(pair_01, float_01, bool_01);
    arcs.insert(triple);
    delete triple;
    
    Float float_02(0.5);
    Boolean bool_02(false);
    Pair<Long, Long> pair_02(0, 1);
    triple = new TopoTriple(pair_02, float_02, bool_02);
    arcs.insert(triple);
    delete triple;
    
    Float float_03(0.7);
    Boolean bool_03(false);
    Pair<Long, Long> pair_03(1, 1);
    triple = new TopoTriple(pair_03, float_03, bool_03);
    arcs.insert(triple);
    delete triple;
    
    Float float_04(0.0);
    Boolean bool_04(true);
    Pair<Long, Long> pair_04(1, BiGraph<Char>::TERM_INDEX);
    triple = new TopoTriple(pair_04, float_04, bool_04);
    arcs.insert(triple);
    delete triple;
    
    // create the list of data elements
    //
    DoubleLinkedList<Char> dlist;
    dlist.insert(a);
    dlist.insert(b);  
    
    // create the graph using the lists
    //
    BiGraph<Char> assgn_graph(DstrBase::USER);
    assgn_graph.assign(dlist, arcs);
    
    // the graph should contain 'a' and 'b'
    //
    if (!assgn_graph.contains(a)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    if (!assgn_graph.contains(b)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }  
    
    // the start vertex should have an epsilon transition to 'a'
    //
    assgn_graph.gotoFirst();
    if (!assgn_graph.getStart()->getFirstChild()->getVertex()->getItem()->eq(*a)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }

    // the 'a' vertex should have an epsilon transition to start
    //
    BiGraphVertex<Char>* ver_test =
      assgn_graph.getStart()->getFirstChild()->getVertex();
    if (ver_test->getFirstParent()->getVertex() != assgn_graph.getStart()) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    
    // 'a' should have a transition to 'b' and itself
    //
    assgn_graph.gotoFirst();
    BiGraphVertex<Char>* ver_00 = (BiGraphVertex<Char>*)assgn_graph.getCurr();
    ver_00->gotoFirstChild();
    BiGraphArc<Char>* arc_00 = ver_00->getCurrChild();
    if (!Integral::almostEqual((double)arc_00->getWeight(), 0.1)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    if (!arc_00->getVertex()->getItem()->eq(*a)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    BiGraphArc<Char>* arc_01 = ver_00->getNextChild();
    if (!Integral::almostEqual((double)arc_01->getWeight(), 0.5)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    if (!arc_01->getVertex()->getItem()->eq(*b)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }  

    // 'a' should have transition to start and itself
    //
    ver_00->gotoFirstParent();
    arc_00 = ver_00->getCurrParent();
    if (arc_00->getVertex() != assgn_graph.getStart()) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    arc_01 = ver_00->getNextParent();
    if (!Integral::almostEqual((double)arc_01->getWeight(), 0.1)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }    
    if (!arc_01->getVertex()->getItem()->eq(*a)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
  
    // 'b' should have an epsilon transition to the term vertex and itself
    //
    assgn_graph.gotoNext();
    BiGraphVertex<Char>* ver_01 = (BiGraphVertex<Char>*)assgn_graph.getCurr();
    ver_01->gotoFirstChild();
    BiGraphArc<Char>* arc_02 = ver_01->getCurrChild();
    if (!Integral::almostEqual((double)arc_02->getWeight(), 0.7)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    if (!arc_02->getVertex()->getItem()->eq(*b)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    BiGraphArc<Char>* arc_03 = ver_01->getNextChild();
    if (arc_03->getVertex() != assgn_graph.getTerm()) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }

    // 'b' should have an a transition to 'a' and itself
    //
    ver_01 = (BiGraphVertex<Char>*)assgn_graph.getCurr();
    ver_01->gotoFirstParent();
    arc_02 = ver_01->getCurrParent();
    if (!Integral::almostEqual((double)arc_02->getWeight(), 0.5)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    if (!arc_02->getVertex()->getItem()->eq(*a)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    
    arc_03 = ver_01->getNextParent();
    if (!Integral::almostEqual((double)arc_03->getWeight(), 0.7)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }    
    if (!arc_03->getVertex()->getItem()->eq(*b)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }  
    
    // the term vertex should have a transition to 'b'
    //
    ver_01 = assgn_graph.getTerm();
    ver_01->gotoFirstParent();
    arc_02 = ver_01->getCurrParent();
    if (!arc_02->getVertex()->getItem()->eq(*b)) {
      return Error::handle(name(), L"assign", Error::TEST, __FILE__, __LINE__);
    }
    
    // clean up
    //
    delete a;
    delete b;    
    arcs.clear(Integral::FREE);
  }

  // testing i/o methods in SYSTEM mode
  //

  // -------------------------------------------------
  // START    -> a 
  //          -> b
  //          -> c
  // a        -> d
  // a        -> f  
  // b        -> d
  // c        -> g  
  // c        -> d
  // d        -> e
  // e        -> f
  // e        -> g        
  // f        -> TERM
  // g        -> TERM   
  // -------------------------------------------------
  
  BiGraph<Char> write_graph;

  write_graph.insertArc(write_graph.getStart(), write_graph.getTerm(), true);
  
  Char* chr = new Char(L'a');
  BiGraphVertex<Char>* ptr_a = write_graph.insertVertex(chr);
  write_graph.insertArc(write_graph.getStart(), ptr_a, true);
  delete chr;
  
  chr = new Char(L'b');
  BiGraphVertex<Char>* ptr_b = write_graph.insertVertex(chr);
  write_graph.insertArc(write_graph.getStart(), ptr_b, true);
  delete chr;
  
  chr = new Char(L'c');
  BiGraphVertex<Char>* ptr_c = write_graph.insertVertex(chr);
  write_graph.insertArc(write_graph.getStart(), ptr_c, true);
  delete chr;
  
  chr = new Char(L'd');
  BiGraphVertex<Char>* ptr_d = write_graph.insertVertex(chr);
  delete chr;
  
  write_graph.insertArc(ptr_a, ptr_d, false, (float)0.7);
  write_graph.insertArc(ptr_b, ptr_d, false, (float)0.9);
  write_graph.insertArc(ptr_c, ptr_d, false, (float)3.7);

  chr = new Char(L'e');
  BiGraphVertex<Char>* ptr_e = write_graph.insertVertex(chr);
  write_graph.insertArc(ptr_d, ptr_e, false, (float)1.2);
  delete chr;
  
  chr = new Char(L'f');
  BiGraphVertex<Char>* ptr_f = write_graph.insertVertex(chr);
  write_graph.insertArc(ptr_a, ptr_f, false, (float)0.8);
  write_graph.insertArc(ptr_e, ptr_f, false, (float)6.1);
  delete chr;
  
  chr = new Char(L'g');
  BiGraphVertex<Char>* ptr_g = write_graph.insertVertex(chr); 
  delete chr;
  
  write_graph.insertArc(ptr_c, ptr_g, false, (float)3.1);
  write_graph.insertArc(ptr_e, ptr_g, false, (float)1.7);
  write_graph.insertArc(ptr_f, write_graph.getTerm(), true);
  write_graph.insertArc(ptr_g, write_graph.getTerm(), true);
  
  Filename file_text_00;
  Filename file_bin_00;
  Integral::makeTemp(file_text_00);
  Integral::makeTemp(file_bin_00);
  File::registerTemp(file_text_00);
  File::registerTemp(file_bin_00);
  
  Sof out_text_00;
  Sof out_bin_00;
  
  out_text_00.open(file_text_00, File::WRITE_ONLY, File::TEXT);
  out_bin_00.open(file_bin_00, File::WRITE_ONLY, File::BINARY);

  write_graph.write(out_text_00, 0);
  write_graph.write(out_bin_00, 0);

  out_text_00.close();
  out_bin_00.close();
  
  Sof in_text_00;
  Sof in_bin_00;

  BiGraph<Char> read_graph_text_00;
  BiGraph<Char> read_graph_bin_00;
  
  in_text_00.open(file_text_00, File::READ_PLUS);
  in_bin_00.open(file_bin_00, File::READ_PLUS);
  
  read_graph_text_00.read(in_text_00, 0);
  read_graph_bin_00.read(in_bin_00, 0);

  in_text_00.close();
  in_bin_00.close();
  
  Filename file_text_01;
  Filename file_bin_01;
  Integral::makeTemp(file_text_01);
  Integral::makeTemp(file_bin_01);
  File::registerTemp(file_text_01);
  File::registerTemp(file_bin_01);
  
  Sof out_text_01;
  Sof out_bin_01;

  out_text_01.open(file_text_01, File::WRITE_ONLY, File::TEXT);
  out_bin_01.open(file_bin_01, File::WRITE_ONLY, File::BINARY);  
  
  read_graph_text_00.write(out_text_01, 0);
  read_graph_bin_00.write(out_bin_01, 0);

  out_text_01.close();
  out_bin_01.close();
  
  // test to see if the graphs are equal
  //
  if (!write_graph.eq(read_graph_text_00)) {
    return Error::handle(name(), L"i/o", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!write_graph.eq(read_graph_bin_00)) {
    return Error::handle(name(), L"i/o", Error::TEST,
			 __FILE__, __LINE__);
  }

  Sof in_text_01;
  Sof in_bin_01;

  BiGraph<Char> read_graph_text_01;
  BiGraph<Char> read_graph_bin_01;
  
  in_text_01.open(file_text_01, File::READ_PLUS);
  in_bin_01.open(file_bin_01, File::READ_PLUS);
  
  read_graph_text_01.read(in_text_01, 0);
  read_graph_bin_01.read(in_bin_01, 0);
  
  // close file descriptors
  //
  in_text_01.close();
  in_bin_01.close();

  // test to see if the graphs are equal
  //
  if (!write_graph.eq(read_graph_text_01)) {
    return Error::handle(name(), L"i/o", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!write_graph.eq(read_graph_bin_01)) {
    return Error::handle(name(), L"i/o", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  // clean up allocated memory
  //
  write_graph.clear(Integral::FREE);
  read_graph_text_00.clear(Integral::FREE);
  read_graph_bin_00.clear(Integral::FREE);
  read_graph_text_01.clear(Integral::FREE);
  read_graph_bin_01.clear(Integral::FREE);  

  // read in two graph text files with different indeces for the vertices
  // but the same structure and compare them for equality in SYSTEM-allocation
  //
  BiGraph<Char> read_graph_utext_00;
  BiGraph<Char> read_graph_utext_01;
  BiGraph<Char> read_graph_utext_02;
  BiGraph<Char> read_graph_utext_03;
  
  Sof in_utext_00;  
  String file_utext_00(L"graph.sof");
  in_utext_00.open(file_utext_00);

  read_graph_utext_00.read(in_utext_00, 0);
  read_graph_utext_01.read(in_utext_00, 1);

  // the graph that were read in must be equal
  //
  if (!read_graph_utext_00.eq(read_graph_utext_01)) {
    return Error::handle(name(), L"read/eq", Error::TEST,
			 __FILE__, __LINE__);
  }

  // close file descriptors
  //
  in_utext_00.close();
  
  Sof out_utext_00;

  Filename file_utext_01;
  Integral::makeTemp(file_utext_01);
  File::registerTemp(file_utext_01);
 
  out_utext_00.open(file_utext_01, File::WRITE_ONLY, File::TEXT);

  read_graph_utext_00.write(out_utext_00, 0);
  read_graph_utext_01.write(out_utext_00, 1);

  // close file descriptors
  //
  out_utext_00.close();
  
  // read them back
  //
  Sof in_utext_01;    

  in_utext_01.open(file_utext_01);
  
  read_graph_utext_02.read(in_utext_01, 0);
  read_graph_utext_03.read(in_utext_01, 0);  

  // the graph that were read in must be equal
  //
  if (!read_graph_utext_02.eq(read_graph_utext_00)) {
    return Error::handle(name(), L"read/eq", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!read_graph_utext_03.eq(read_graph_utext_01)) {
    return Error::handle(name(), L"read/eq", Error::TEST,
			 __FILE__, __LINE__);
  }  
  
  // close file descriptors
  //
  in_utext_01.close();  

  {
    // read in two graph text files with different indeces for the
    // vertices but the same structure and compare them for equality
    // in USER-allocation
    //
    BiGraph<Char> read_graph_utext_00(DstrBase::USER);
    BiGraph<Char> read_graph_utext_01(DstrBase::USER);
    BiGraph<Char> read_graph_utext_02(DstrBase::USER);
    BiGraph<Char> read_graph_utext_03(DstrBase::USER);
  
    Sof in_utext_00;  
    String file_utext_00(L"graph.sof");
    in_utext_00.open(file_utext_00);
    
    read_graph_utext_00.read(in_utext_00, 0);
    read_graph_utext_01.read(in_utext_00, 1);
    
    // the graph that were read in must be equal
    //
    if (!read_graph_utext_00.eq(read_graph_utext_01)) {
      return Error::handle(name(), L"read/eq", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // close file descriptors
    //
    in_utext_00.close();
    
    Sof out_utext_00;
    Filename file_utext_01;
    Integral::makeTemp(file_utext_01);
    File::registerTemp(file_utext_01);
 
    out_utext_00.open(file_utext_01, File::WRITE_ONLY, File::TEXT);
    
    read_graph_utext_00.write(out_utext_00, 0);
    read_graph_utext_01.write(out_utext_00, 1);
    
    // close file descriptors
    //
    out_utext_00.close();
    
    // read them back
    //
    Sof in_utext_01;    

    in_utext_01.open(file_utext_01);
    
    read_graph_utext_02.read(in_utext_01, 0);
    read_graph_utext_03.read(in_utext_01, 0);  
    
    // the graph that were read in must be equal
    //
    if (!read_graph_utext_02.eq(read_graph_utext_00)) {
      return Error::handle(name(), L"read/eq", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (!read_graph_utext_03.eq(read_graph_utext_01)) {
    return Error::handle(name(), L"read/eq", Error::TEST,
			 __FILE__, __LINE__);
    }  
    
    // close file descriptors
    //
    in_utext_01.close();

    // free allocated memory
    //
    read_graph_utext_00.clear(Integral::FREE);
    read_graph_utext_01.clear(Integral::FREE);
    read_graph_utext_02.clear(Integral::FREE);
    read_graph_utext_03.clear(Integral::FREE);    
  }
  
  {
    // testing i/o methods in USER mode
    //
    // -------------------------------------------------
    // START    -> a 
    //          -> b
    //          -> c
    // a        -> d
    // b        -> d
    // c        -> d
    // d        -> e
    // a        -> f
    // e        -> f
    // c        -> g
    // e        -> g        
    // f        -> TERM
    // g        -> TERM   
    // -------------------------------------------------
    
    BiGraph<Char> write_graph(DstrBase::USER);

    write_graph.insertArc(write_graph.getStart(), write_graph.getTerm(), true);
    
    Char* chr = new Char(L'a');
    BiGraphVertex<Char>* ptr_a = write_graph.insertVertex(chr);
    write_graph.insertArc(write_graph.getStart(), ptr_a, true);
    
    chr = new Char(L'b');
    BiGraphVertex<Char>* ptr_b = write_graph.insertVertex(chr);
    write_graph.insertArc(write_graph.getStart(), ptr_b, true);
    
    chr = new Char(L'c');
    BiGraphVertex<Char>* ptr_c = write_graph.insertVertex(chr);
    write_graph.insertArc(write_graph.getStart(), ptr_c, true);
    
    chr = new Char(L'd');
    BiGraphVertex<Char>* ptr_d = write_graph.insertVertex(chr);
    
    write_graph.insertArc(ptr_a, ptr_d, false, (float)0.7);
    write_graph.insertArc(ptr_b, ptr_d, false, (float)0.9);
    write_graph.insertArc(ptr_c, ptr_d, false, (float)3.7);
    
    chr = new Char(L'e');
    BiGraphVertex<Char>* ptr_e = write_graph.insertVertex(chr);
    write_graph.insertArc(ptr_d, ptr_e, false, (float)1.2);
    
    chr = new Char(L'f');
    BiGraphVertex<Char>* ptr_f = write_graph.insertVertex(chr);
    write_graph.insertArc(ptr_a, ptr_f, false, (float)0.8);
    write_graph.insertArc(ptr_e, ptr_f, false, (float)6.1);
    
    chr = new Char(L'g');
    BiGraphVertex<Char>* ptr_g = write_graph.insertVertex(chr);
    
    write_graph.insertArc(ptr_c, ptr_g, false, (float)3.1);
    write_graph.insertArc(ptr_e, ptr_g, false, (float)1.7);
    write_graph.insertArc(ptr_f, write_graph.getTerm(), true);
    write_graph.insertArc(ptr_g, write_graph.getTerm(), true);
    
    Filename file_text_00;
    Filename file_bin_00;
    
    Filename file_text_01;
    Filename file_bin_01;

    Integral::makeTemp(file_text_00);
    Integral::makeTemp(file_bin_00);
    Integral::makeTemp(file_text_01);
    Integral::makeTemp(file_bin_01);

    File::registerTemp(file_text_00);
    File::registerTemp(file_bin_00);
    File::registerTemp(file_text_01);
    File::registerTemp(file_bin_01);
    
    Sof out_text_00;
    Sof out_bin_00;
    
    out_text_00.open(file_text_00, File::WRITE_ONLY, File::TEXT);
    out_bin_00.open(file_bin_00, File::WRITE_ONLY, File::BINARY);
    
    write_graph.write(out_text_00, 0);
    write_graph.write(out_bin_00, 0);
    
    out_text_00.close();
    out_bin_00.close();
    
    Sof in_text_00;
    Sof in_bin_00;
    
    BiGraph<Char> read_graph_text_00;
    BiGraph<Char> read_graph_bin_00;
    
    in_text_00.open(file_text_00, File::READ_PLUS);
    in_bin_00.open(file_bin_00, File::READ_PLUS);
    
    read_graph_text_00.read(in_text_00, 0);
    read_graph_bin_00.read(in_bin_00, 0);

    in_text_00.close();
    in_bin_00.close();
    
    Sof out_text_01;
    Sof out_bin_01;
    
    out_text_01.open(file_text_01, File::WRITE_ONLY, File::TEXT);
    out_bin_01.open(file_bin_01, File::WRITE_ONLY, File::BINARY);  
    
    read_graph_text_00.write(out_text_01, 0);
    read_graph_bin_00.write(out_bin_01, 0);
    
    out_text_01.close();
    out_bin_01.close();
    
    // test to see if the graphs are equal
    //
    if (!write_graph.eq(read_graph_text_00)) {
      return Error::handle(name(), L"i/o", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (!write_graph.eq(read_graph_bin_00)) {
      return Error::handle(name(), L"i/o", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    Sof in_text_01;
    Sof in_bin_01;
    
    BiGraph<Char> read_graph_text_01;
    BiGraph<Char> read_graph_bin_01;
    
    in_text_01.open(file_text_01, File::READ_PLUS);
    in_bin_01.open(file_bin_01, File::READ_PLUS);
    
    read_graph_text_01.read(in_text_01, 0);
    read_graph_bin_01.read(in_bin_01, 0);
    
    // close file descriptors
    //
    in_text_01.close();
    in_bin_01.close();
    
    // test to see if the graphs are equal
    //
    if (!write_graph.eq(read_graph_text_01)) {
      return Error::handle(name(), L"i/o", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (!write_graph.eq(read_graph_bin_01)) {
      return Error::handle(name(), L"i/o", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // clean up allocated memory
    //
    write_graph.clear(Integral::FREE);
    read_graph_text_00.clear(Integral::FREE);
    read_graph_bin_00.clear(Integral::FREE);
    read_graph_text_01.clear(Integral::FREE);
    read_graph_bin_01.clear(Integral::FREE);  
  }

  // test the equality method in SYSTEM-allocated mode
  //

  // -------------------------------------------------
  // START    -> A 
  // A -(0.3) -> A
  //   -(0.3) -> R
  //   -(epi) -> B
  //   -(epi) -> C
  // B -(0.2) -> L
  // C -(3.6) -> K
  // M -(0.6) -> K
  // M -(1.2) -> A
  // L -(-0.7)-> R
  // L -(0.4) -> C
  // S -(-0.2)-> K
  // S -(-0.6)-> S
  // R        -> TERM
  //
  // START    <- A 
  // A <-(0.3) - A
  //   <-(0.3) - R
  //   <-(epi) - B
  //   <-(epi) - C
  // B <-(0.2) - L
  // C <-(3.6) - K
  // M <-(0.6) - K
  // M <-(1.2) - A
  // L <-(-0.7)- R
  // L <-(0.4) - C
  // S <-(-0.2)- K
  // S <-(-0.6)- S
  // R        <- TERM 
  // -------------------------------------------------  

  // create the graph items
  //
  Char* A = new Char('A');
  Char* B = new Char('B');
  Char* C = new Char('C');
  Char* K = new Char('K');
  Char* L = new Char('L');
  Char* M = new Char('M');
  Char* S = new Char('S');  
  Char* R = new Char('R');

  // create the graph
  //
  BiGraph<Char>* graph_00 = new BiGraph<Char>();
  
  // create the verteices
  //
  BiGraphVertex<Char>* VA = graph_00->insertVertex(A);
  BiGraphVertex<Char>* VB = graph_00->insertVertex(B);
  BiGraphVertex<Char>* VC = graph_00->insertVertex(C);    
  BiGraphVertex<Char>* VK = graph_00->insertVertex(K);
  BiGraphVertex<Char>* VL = graph_00->insertVertex(L);
  BiGraphVertex<Char>* VM = graph_00->insertVertex(M);    
  BiGraphVertex<Char>* VS = graph_00->insertVertex(S);
  BiGraphVertex<Char>* VR = graph_00->insertVertex(R);

  // connect the graph
  //
  graph_00->insertArc(graph_00->getStart(), VA, true);
  graph_00->insertArc(VA, VA, false, 0.3);
  graph_00->insertArc(VA, VR, false, 0.3);
  graph_00->insertArc(VA, VB, true);
  graph_00->insertArc(VA, VC, true);  
  graph_00->insertArc(VB, VL, false, 0.2);
  graph_00->insertArc(VC, VK, false, 3.6);
  graph_00->insertArc(VM, VK, false, 0.6);
  graph_00->insertArc(VM, VA, false, 1.2);
  graph_00->insertArc(VL, VR, false, -0.7);
  graph_00->insertArc(VL, VC, false, 0.4);
  graph_00->insertArc(VS, VK, false, -0.2);
  graph_00->insertArc(VS, VS, false, -0.6);
  graph_00->insertArc(VR, graph_00->getTerm(), true);  

  // create the graph
  //
  BiGraph<Char>* graph_01 = new BiGraph<Char>(*graph_00);
  
  // create the graph
  //
  BiGraph<Char>* graph_02 = new BiGraph<Char>();
  
  VA = graph_02->insertVertex(A);
  VB = graph_02->insertVertex(B);
  VC = graph_02->insertVertex(C);    
  VK = graph_02->insertVertex(K);
  VL = graph_02->insertVertex(L);
  VM = graph_02->insertVertex(M);    
  VS = graph_02->insertVertex(S);
  VR = graph_02->insertVertex(R);

  // connect the graph
  //
  graph_02->insertArc(graph_02->getStart(), VA, true);  
  graph_02->insertArc(VA, VA, false, 0.3);
  graph_02->insertArc(VA, VR, false, 0.3);
  graph_02->insertArc(VA, VB, true);
  graph_02->insertArc(VA, VC, true);  
  graph_02->insertArc(VB, VL, false, 0.2);
  graph_02->insertArc(VC, VK, false, 3.6);
  graph_02->insertArc(VM, VK, false, 0.6);
  graph_02->insertArc(VM, VA, false, -1.2);
  graph_02->insertArc(VL, VR, false, -0.7);
  graph_02->insertArc(VL, VC, false, 0.4);
  graph_02->insertArc(VS, VK, false, -0.2);
  graph_02->insertArc(VS, VS, false, -0.6);    
  graph_02->insertArc(VR, graph_02->getTerm(), true);
  
  // graph_00 and graph_01 should be equal
  //
  if (!graph_00->eq(*graph_01)) {
    return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__);
  }

  // graph_00 and graph_01 should not be equal
  //
  if (graph_00->eq(*graph_02)) {
    return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__);
  }  

  // delete the character objects
  //
  delete A;
  delete B;
  delete C;
  delete K;
  delete L;
  delete M;
  delete S;
  delete R;
  
  // clean up memory
  //
  graph_00->clear(Integral::FREE);
  graph_01->clear(Integral::FREE);
  graph_02->clear(Integral::FREE);

  delete graph_00;
  delete graph_01;
  delete graph_02;  

  {
    // test the equality method in USER-allocated mode
    //
    
    // -------------------------------------------------
    // START    -> A 
    // A -(0.3) -> A
    //   -(0.3) -> R
    //   -(epi) -> B
    //   -(epi) -> C
    // B -(0.2) -> L
    // C -(3.6) -> K
    // M -(0.6) -> K
    // M -(1.2) -> A
    // L -(-0.7)-> R
    // L -(0.4) -> C
    // S -(-0.2)-> K
    // S -(-0.6)-> S
    // R        -> TERM 
    // -------------------------------------------------  
    
    // create the graph items
    //
    Char* A = new Char('A');
    Char* B = new Char('B');
    Char* C = new Char('C');
    Char* K = new Char('K');
    Char* L = new Char('L');
    Char* M = new Char('M');
    Char* S = new Char('S');  
    Char* R = new Char('R');
    
    // create the graph
    //
    BiGraph<Char>* graph_00 = new BiGraph<Char>(DstrBase::USER);
    
    // create the verteices
    //
    BiGraphVertex<Char>* VA = graph_00->insertVertex(A);
    BiGraphVertex<Char>* VB = graph_00->insertVertex(B);
    BiGraphVertex<Char>* VC = graph_00->insertVertex(C);    
    BiGraphVertex<Char>* VK = graph_00->insertVertex(K);
    BiGraphVertex<Char>* VL = graph_00->insertVertex(L);
    BiGraphVertex<Char>* VM = graph_00->insertVertex(M);    
    BiGraphVertex<Char>* VS = graph_00->insertVertex(S);
    BiGraphVertex<Char>* VR = graph_00->insertVertex(R);
    
    // connect the graph
    //
    graph_00->insertArc(graph_00->getStart(), VA, true);    
    graph_00->insertArc(VA, VA, false, 0.3);
    graph_00->insertArc(VA, VR, false, 0.3);
    graph_00->insertArc(VA, VB, true);
    graph_00->insertArc(VA, VC, true);  
    graph_00->insertArc(VB, VL, false, 0.2);
    graph_00->insertArc(VC, VK, false, 3.6);
    graph_00->insertArc(VM, VK, false, 0.6);
    graph_00->insertArc(VM, VA, false, 1.2);
    graph_00->insertArc(VL, VR, false, -0.7);
    graph_00->insertArc(VL, VC, false, 0.4);
    graph_00->insertArc(VS, VK, false, -0.2);
    graph_00->insertArc(VS, VS, false, -0.6);
    graph_00->insertArc(VR, graph_00->getTerm(), true);  
    
    // create the graph
    //
    BiGraph<Char>* graph_01 = new BiGraph<Char>(*graph_00);
    
    // create the graph
    //
    BiGraph<Char>* graph_02 = new BiGraph<Char>(DstrBase::USER);
    
    VA = graph_02->insertVertex(A);
    VB = graph_02->insertVertex(B);
    VC = graph_02->insertVertex(C);    
    VK = graph_02->insertVertex(K);
    VL = graph_02->insertVertex(L);
    VM = graph_02->insertVertex(M);    
    VS = graph_02->insertVertex(S);
    VR = graph_02->insertVertex(R);
    
    // connect the graph
    //
    graph_02->insertArc(graph_02->getStart(), VA, true);  
    graph_02->insertArc(VA, VA, false, 0.3);
    graph_02->insertArc(VA, VR, false, 0.3);
    graph_02->insertArc(VA, VB, true);
    graph_02->insertArc(VA, VC, true);  
    graph_02->insertArc(VB, VL, false, 0.2);
    graph_02->insertArc(VC, VK, false, 3.6);
    graph_02->insertArc(VM, VK, false, 0.6);
    graph_02->insertArc(VM, VA, false, -1.2);
    graph_02->insertArc(VL, VR, false, -0.7);
    graph_02->insertArc(VL, VC, false, 0.4);
    graph_02->insertArc(VS, VK, false, -0.2);
    graph_02->insertArc(VS, VS, false, -0.6);
    graph_02->insertArc(VR, graph_02->getTerm(), true);    
    
    // graph_00 and graph_01 should be equal
    //
    if (!graph_00->eq(*graph_01)) {
      return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__);
    }
    
    // graph_00 and graph_01 should not be equal
    //
    if (graph_00->eq(*graph_02)) {
      return Error::handle(name(), L"eq", Error::TEST, __FILE__, __LINE__);
    }  
    
    // clean up memory
    //
    graph_00->clear(Integral::FREE);
    graph_01->clear();
    graph_02->clear();

    delete graph_00;
    delete graph_01;
    delete graph_02;    
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  // --------------------------------------------------------------------
  //
  // 2. class-specific public methods:
  //     graph manipulation methods
  //
  // --------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific public methods: graph manipulation methods...\n");
    Console::increaseIndention(); 
  }

  // test insert vetrex methods in SYSTEM-allocation mode
  //
  BiGraph<Char>* graph_03 = new BiGraph<Char>();

  // create some vertices
  //
  A = new Char('A');
  B = new Char('B');
  C = new Char('C');
  K = new Char('K');  

  VA = graph_03->insertVertex(A);
  VB = graph_03->insertVertex(B);
  VC = graph_03->insertVertex(C);
  VK = graph_03->insertVertex(K);    

  L = new Char('L');    
  VL = new BiGraphVertex<TObject>();
    
  // the graph should contain VA, VB, VC and VK
  //
  if ((!graph_03->contains(VA)) || (!graph_03->contains(VB)) ||
      (!graph_03->contains(VC)) || (!graph_03->contains(VK))) {
    return Error::handle(name(), L"insertVertex", Error::TEST,
			 __FILE__, __LINE__);
  }

  // the graph should not contain VL
  //
  if (graph_03->contains(VL)) {
    return Error::handle(name(), L"insertVertex", Error::TEST,
			 __FILE__, __LINE__);
  }  

  // test the find and contains methods in SYSTEM-allocation mode
  //
  graph_03->setMark();
  if (!graph_03->contains(VC)) {
    return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__);
  }
  if (graph_03->contains(VL)) {
    return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__);
  }
  if (!graph_03->contains(K)) {
    return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__);
  }  
  if (graph_03->contains(L)) {
    return Error::handle(name(), L"contains", Error::TEST, __FILE__, __LINE__);
  }  

  if (!graph_03->find(VA)) {
    return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
  }
  if (graph_03->getCurr() != VA) {
    return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
  }
  if (!graph_03->find(K)) {
    return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
  }
  if (graph_03->getCurr() != VK) {
    return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
  }  
  graph_03->gotoMark();
  
  // test remove vetrex methods in SYSTEM-allocation mode
  //
  graph_03->find(VC);
  graph_03->removeVertex();
  if (graph_03->contains(VC)) {
    return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__);
  }

  TObject* item = new TObject();
  graph_03->find(VK);
  graph_03->removeVertex(item);
  if ((graph_03->contains(VK)) || (!item->eq(*K))) {
    return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__);
  }  
       
  // test insert arc methods in SYSTEM-allocation mode
  //
  graph_03->insertArc(graph_03->getStart(), VB, true);  
  graph_03->insertArc(VB, graph_03->getTerm(), false, 0.3);

  // the start vertex should have an epsilon transition to VB
  //
  BiGraphArc<TObject>* my_arc = graph_03->getStart()->getFirstChild();    
  if ((my_arc->getVertex()) != VB && (!my_arc->getEpsilon())) {
    return Error::handle(name(), L"insertArc", Error::TEST,
			 __FILE__, __LINE__);
  }

  // the VB should have an epsilon transition to the start
  //
  ver_test = my_arc->getVertex();
  my_arc = ver_test->getFirstParent();    
  if ((my_arc->getVertex()) != graph_03->getStart()  &&
      (!my_arc->getEpsilon())) {
    return Error::handle(name(), L"insertArc", Error::TEST,
			 __FILE__, __LINE__);
  }  
  
  boolean more_nodes = graph_03->gotoFirst();

  while (more_nodes) {
    
    // VB should a weighted arc to the term vertex
    //
    BiGraphVertex<TObject>* my_vertex =
      (BiGraphVertex<TObject>*)graph_03->getCurr();
    BiGraphArc<TObject>* my_arc = my_vertex->getFirstChild();

    if (my_vertex == VB) {
      if ((my_arc->getVertex() != graph_03->getTerm()) &&
	  (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
	return Error::handle(name(), L"insertArc", Error::TEST,
			     __FILE__, __LINE__);
      }
    }

    // the start should a weighted arc to VB
    //
    my_vertex = graph_03->getTerm();
    my_arc = my_vertex->getFirstParent();

    if (my_vertex == graph_03->getTerm()) {
      if ((my_arc->getVertex() != VB) &&
	  (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
	return Error::handle(name(), L"insertArc", Error::TEST,
			     __FILE__, __LINE__);
      }
    }
    
    more_nodes = graph_03->gotoNext();
  }

  // test remove arc methods in SYSTEM-allocation mode
  //
  graph_03->removeArc(VB, graph_03->getTerm());

  more_nodes = graph_03->gotoFirst();

  while (more_nodes) {
    
    // VB should not have a weighted arc to the term vertex
    //
    BiGraphVertex<TObject>* my_vertex =
      (BiGraphVertex<TObject>*)graph_03->getCurr();
    BiGraphArc<TObject>* my_arc = my_vertex->getFirstChild();

    if (my_vertex == VB) {
      if (my_arc != (BiGraphArc<TObject>*)NULL) {
	return Error::handle(name(), L"removeArc", Error::TEST,
			     __FILE__, __LINE__);
      }
    }

    // term vertex should not have a weighted arc to VB
    //
    my_vertex = graph_03->getTerm();
    my_arc = my_vertex->getFirstParent();

    if (my_vertex == graph_03->getTerm()) {
      if (my_arc != (BiGraphArc<TObject>*)NULL) {
	return Error::handle(name(), L"removeArc", Error::TEST,
			     __FILE__, __LINE__);
      }
    }    
    
    more_nodes = graph_03->gotoNext();
  }
  
  // clean up memory
  //
  delete item;
  delete L;
  delete VL;
  graph_03->clear(Integral::FREE);

  delete A;
  delete B;
  delete C;
  delete K;
  delete graph_03;

  {
    // test insert vetrex methods in USER-allocation mode
    //
    BiGraph<Char>* graph_03 = new BiGraph<Char>(DstrBase::USER);
    
    // create some vertices
    //
    A = new Char('A');
    B = new Char('B');
    C = new Char('C');
    K = new Char('K');  
    
    VA = graph_03->insertVertex(A);
    VB = graph_03->insertVertex(B);
    VC = graph_03->insertVertex(C);
    VK = graph_03->insertVertex(K);    
    
    L = new Char('L');    
    VL = new BiGraphVertex<TObject>();
    
    // the graph should contain VA, VB, VC and VK
    //
    if ((!graph_03->contains(VA)) || (!graph_03->contains(VB)) ||
	(!graph_03->contains(VC)) || (!graph_03->contains(VK))) {
      return Error::handle(name(), L"insertVertex", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // the graph should not contain VL
    //
    if (graph_03->contains(VL)) {
      return Error::handle(name(), L"insertVertex", Error::TEST,
			   __FILE__, __LINE__);
    }  
    
    // test the find and contains methods in USER-allocation mode
    //
    graph_03->setMark();
    if (!graph_03->contains(VC)) {
      return Error::handle(name(), L"contains", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (graph_03->contains(VL)) {
      return Error::handle(name(), L"contains", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (!graph_03->contains(K)) {
      return Error::handle(name(), L"contains", Error::TEST,
			   __FILE__, __LINE__);
    }  
    if (graph_03->contains(L)) {
      return Error::handle(name(), L"contains", Error::TEST,
			   __FILE__, __LINE__);
    }  
    
    if (!graph_03->find(VA)) {
      return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
    }
    if (graph_03->getCurr() != VA) {
      return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
    }
    if (!graph_03->find(K)) {
      return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
    }
    if (graph_03->getCurr() != VK) {
      return Error::handle(name(), L"find", Error::TEST, __FILE__, __LINE__);
    }  
    graph_03->gotoMark();
    
    // test remove vetrex methods in USER-allocation mode
    //
    TObject* item = (TObject*)NULL;

    graph_03->find(VC);
    graph_03->removeVertex(item);
    if ((graph_03->contains(VC)) || (!item->eq(*C))) {
      return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__);
    }
    
    item = (TObject*)NULL;

    delete C;

    graph_03->find(VK);
    graph_03->removeVertex(item);
    if ((graph_03->contains(VK)) || (!item->eq(*K))) {
      return Error::handle(name(), L"remove", Error::TEST, __FILE__, __LINE__);
    }  

    delete K;
    
    // test insert arc methods in USER-allocation mode
    //
    graph_03->insertArc(graph_03->getStart(), VB, true);  
    graph_03->insertArc(VB, graph_03->getTerm(), false, 0.3);
    
    // the start vertex should have an epsilon transition to VB
    //
    BiGraphArc<TObject>* my_arc = graph_03->getStart()->getFirstChild();    
    if ((my_arc->getVertex() != VB) && (!my_arc->getEpsilon())) {
      return Error::handle(name(), L"insertArc", Error::TEST,
			   __FILE__, __LINE__);
    }

    // the VB should have an epsilon transition to the start
    //
    ver_test = my_arc->getVertex();
    my_arc = ver_test->getFirstParent();    
    if ((my_arc->getVertex()) != graph_03->getStart()  &&
	(!my_arc->getEpsilon())) {
      return Error::handle(name(), L"insertArc", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    boolean more_nodes = graph_03->gotoFirst();
    
    while (more_nodes) {
      
      // VB should not have weighted arc to the term vertex
      //
      BiGraphVertex<TObject>* my_vertex =
	(BiGraphVertex<TObject>*)graph_03->getCurr();
      
      BiGraphArc<TObject>* my_arc = my_vertex->getFirstChild();
      
      if (my_vertex == VB) {
	if ((my_arc->getVertex() != graph_03->getTerm()) &&
	    (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
	  return Error::handle(name(), L"insertArc", Error::TEST,
			       __FILE__, __LINE__);
	}
      }

      // the start should a weighted arc to VB
      //
      my_vertex = graph_03->getTerm();
      my_arc = my_vertex->getFirstParent();
      
      if (my_vertex == graph_03->getTerm()) {
	if ((my_arc->getVertex() != VB) &&
	    (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
	  return Error::handle(name(), L"insertArc", Error::TEST,
			       __FILE__, __LINE__);
	}
      }
    
      more_nodes = graph_03->gotoNext();
    }
    
    // test remove arc methods in USER-allocation mode
    //
    graph_03->removeArc(VB, graph_03->getTerm());
    
    more_nodes = graph_03->gotoFirst();
    
    while (more_nodes) {
      
      // VB should a weighted arc to the term vertex
      //
      BiGraphVertex<TObject>* my_vertex =
	(BiGraphVertex<Char>*)graph_03->getCurr();
      
      BiGraphArc<TObject>* my_arc = my_vertex->getFirstChild();
      
      if (my_vertex == VB) {
	if (my_arc != (BiGraphArc<TObject>*)NULL) {
	  return Error::handle(name(), L"removeArc", Error::TEST,
			       __FILE__, __LINE__);
	}
      }

      // term vertex should not have a weighted arc to VB
      //
      my_vertex = graph_03->getTerm();
      my_arc = my_vertex->getFirstParent();
      
      if (my_vertex == graph_03->getTerm()) {
	if (my_arc != (BiGraphArc<TObject>*)NULL) {
	return Error::handle(name(), L"removeArc", Error::TEST,
			     __FILE__, __LINE__);
	}
      }
      
      more_nodes = graph_03->gotoNext();
    }
    
    // clean up memory (note K and C have already been deleted from the graph)
    //
    graph_03->clear(Integral::FREE);

    delete L;  
    delete VL;    
    delete graph_03;
  }

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  // --------------------------------------------------------------------
  //
  // 3. class-specific public methods:
  //     graph property methods
  //
  // --------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific public methods: graph property methods...\n");
    Console::increaseIndention(); 
  }

  // test the graph get method in SYSTEM-allocation mode
  //
  
  {
    // -------------------------------------------------
    // START -(epi) -> a
    // a     -(0.1) -> a
    // a     -(0.5) -> b
    // b     -(0.7) -> b
    // b     -(epi) -> TERM 
    // -------------------------------------------------
    
    // create the graph items
    //    
    Char* a = new Char('a');
    Char* b = new Char('b');
    TopoTriple* triple;
  
    // create the list of arcs
    //
    DoubleLinkedList<TopoTriple> arcs;
    
    Float float_00(0.0);
    Boolean bool_00(true);
    Pair<Long, Long> pair_00(BiGraph<Char>::START_INDEX, 0);
    triple = new TopoTriple(pair_00, float_00, bool_00);
    arcs.insert(triple);
    delete triple;
    
    Float float_01(0.1);
    Boolean bool_01(false);
    Pair<Long, Long> pair_01(0, 0);
    triple = new TopoTriple(pair_01, float_01, bool_01);
    arcs.insert(triple);
    delete triple;
    
    Float float_02(0.5);
    Boolean bool_02(false);
    Pair<Long, Long> pair_02(0, 1);
    triple = new TopoTriple(pair_02, float_02, bool_02);
    arcs.insert(triple);
    delete triple;
    
    Float float_03(0.7);
    Boolean bool_03(false);
    Pair<Long, Long> pair_03(1, 1);
    triple = new TopoTriple(pair_03, float_03, bool_03);
    arcs.insert(triple);
    delete triple;
    
    Float float_04(0.0);
    Boolean bool_04(true);
    Pair<Long, Long> pair_04(1, BiGraph<Char>::TERM_INDEX);
    triple = new TopoTriple(pair_04, float_04, bool_04);
    arcs.insert(triple);
    delete triple;  
    
    // create the list of data elements
    //
    DoubleLinkedList<Char> dlist;
    dlist.insert(a);
    dlist.insert(b);  
    
    // create the graph using the lists
    //
    BiGraph<Char> assgn_graph;
    assgn_graph.assign(dlist, arcs);

    // retrieve the lists from the graph
    //
    DoubleLinkedList<Char> test_dlist;
    DoubleLinkedList<TopoTriple> test_arcs;
    assgn_graph.get(test_dlist, test_arcs);

    // test for quuality of the lists
    //
    if (!test_dlist.eq(dlist)) {
      return Error::handle(name(), L"get", Error::TEST,
			   __FILE__, __LINE__);
    }

    if (!test_arcs.eq(arcs)) {
      return Error::handle(name(), L"get", Error::TEST,
			   __FILE__, __LINE__);
    }

    // clean up
    //
    delete a;
    delete b;

    // test the graph get method in USER-allocation mode
    //
    
    {
      // -------------------------------------------------
      // START -(epi) -> a
      // a     -(0.1) -> a
      // a     -(0.5) -> b
      // b     -(0.7) -> b
      // b     -(epi) -> TERM 
      // -------------------------------------------------
    
      // create the graph items
      //          
      Char* a = new Char('a');
      Char* b = new Char('b');
      TopoTriple* triple;
      
      // create the list of arcs
      //
      DoubleLinkedList<TopoTriple> arcs;
      
      Float float_00(0.0);
      Boolean bool_00(true);
      Pair<Long, Long> pair_00(BiGraph<Char>::START_INDEX, 0);
      triple = new TopoTriple(pair_00, float_00, bool_00);
      arcs.insert(triple);
      delete triple;
    
      Float float_01(0.1);
      Boolean bool_01(false);
      Pair<Long, Long> pair_01(0, 0);
      triple = new TopoTriple(pair_01, float_01, bool_01);
      arcs.insert(triple);
      delete triple;
      
      Float float_02(0.5);
      Boolean bool_02(false);
      Pair<Long, Long> pair_02(0, 1);
      triple = new TopoTriple(pair_02, float_02, bool_02);
      arcs.insert(triple);
      delete triple;
      
      Float float_03(0.7);
      Boolean bool_03(false);
      Pair<Long, Long> pair_03(1, 1);
      triple = new TopoTriple(pair_03, float_03, bool_03);
      arcs.insert(triple);
      delete triple;
      
      Float float_04(0.0);
      Boolean bool_04(true);
      Pair<Long, Long> pair_04(1, BiGraph<Char>::TERM_INDEX);
      triple = new TopoTriple(pair_04, float_04, bool_04);
      arcs.insert(triple);
      delete triple;  
      
      // create the list of data elements
      //
      DoubleLinkedList<Char> dlist;
      dlist.insert(a);
      dlist.insert(b);  
      
      // create the graph using the lists
      //
      BiGraph<Char> assgn_graph(DstrBase::USER);
      assgn_graph.assign(dlist, arcs);
      
      // retrieve the lists from the graph
      //
      DoubleLinkedList<Char> test_dlist;
      DoubleLinkedList<TopoTriple> test_arcs;
      assgn_graph.get(test_dlist, test_arcs);
      
      // test for quuality of the lists
      //
      if (!test_dlist.eq(dlist)) {
	return Error::handle(name(), L"get", Error::TEST,
			     __FILE__, __LINE__);
      }
      
      if (!test_arcs.eq(arcs)) {
	return Error::handle(name(), L"get", Error::TEST,
			     __FILE__, __LINE__);
      }
      
      // clean up
      //
      delete a;
      delete b;  
    }
  }
  
  // declare a new graph
  //
  BiGraph<TObject>* graph_04 = new  BiGraph<TObject>();
  
  // weight methods in SYSTEM-allocation mode
  //
  if (!graph_04->isWeighted()) {
    return Error::handle(name(), L"isWeighted", Error::TEST,
			 __FILE__, __LINE__);
  }
  graph_04->setWeighted(false);
  if (graph_04->isWeighted()) {
    return Error::handle(name(), L"setWeighted", Error::TEST,
			 __FILE__, __LINE__);
  }
  graph_04->setWeighted(true);
  
  A = new Char('A');
  VA = graph_04->insertVertex(A);
  graph_04->insertArc(graph_04->getStart(), VA, false, 0.1);
  graph_04->insertArc(VA, graph_04->getStart(), false, 0.1);
  
  graph_04->insertArc(VA, graph_04->getTerm(), false, 0.3);
  graph_04->insertArc(graph_04->getTerm(), VA, false, 0.3);

  // the start vertex should a weighted arc to VA
  //
  my_arc = graph_04->getStart()->getFirstChild();    
  if ((my_arc->getVertex() != VA) &&
     (!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
    return Error::handle(name(), L"insertArc", Error::TEST,
			 __FILE__, __LINE__);
  }

  // VA should a weighted arc to the start vertex
  //
  ver_test = my_arc->getVertex();
  my_arc = ver_test->getFirstParent();    
  if ((my_arc->getVertex() != graph_04->getStart()) &&
     (!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
    return Error::handle(name(), L"insertArc", Error::TEST,
			 __FILE__, __LINE__);
  }  
    
  more_nodes = graph_04->gotoFirst();
  
  while (more_nodes) {
    
    // VA should a weighted arc to the term vertex
    //
    BiGraphVertex<TObject>* my_vertex =
      (BiGraphVertex<TObject>*)graph_04->getCurr();

    my_vertex->setMarkChild();    
    my_vertex->gotoFirstChild();
    BiGraphArc<TObject>* my_arc = my_vertex->getCurrChild();
    
    if (my_vertex == VA) {
      if ((my_arc->getVertex() == graph_04->getStart()) &&
	  (!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
	return Error::handle(name(), L"insertArc", Error::TEST,
			     __FILE__, __LINE__);
      }      
    }
       
    my_vertex->gotoNextChild();
    my_arc = my_vertex->getCurrChild();
    
    if (my_vertex == VA) {    
      if ((my_arc->getVertex() == graph_04->getTerm()) &&
	  (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
	return Error::handle(name(), L"insertArc", Error::TEST,
			     __FILE__, __LINE__);
      }
    }

    // term vertex should have a weighted arc to VA
    //
    if (my_vertex == graph_04->getTerm()) {
      my_vertex->gotoFirstParent();
      my_arc = my_vertex->getCurrParent();
      if ((my_arc->getVertex() != VA) &&
	  (!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
	return Error::handle(name(), L"insertArc", Error::TEST,
			     __FILE__, __LINE__);
      }    
    }
    
    my_vertex->gotoMarkChild();    
    more_nodes = graph_04->gotoNext();
  }

  // the end vertex should a weighted arc to VA
  //
  my_arc = graph_04->getTerm()->getFirstChild();    
  if ((my_arc->getVertex() != VA) &&
     (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
    return Error::handle(name(), L"insertArc", Error::TEST,
			 __FILE__, __LINE__);
  }

  // the VA should a weighted arc to the term vertex
  //
  ver_test = my_arc->getVertex();
  ver_test->gotoLastParent();
  my_arc = ver_test->getCurrParent();

  if ((my_arc->getVertex() != graph_04->getTerm()) &&
      (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
    return Error::handle(name(), L"insertArc", Error::TEST,
			 __FILE__, __LINE__);
  }
  
  // clean up memory
  //
  graph_04->clear(Integral::FREE);

  delete A;
  delete graph_04;
  
  {
    // declare a new graph
    //
    BiGraph<TObject>* graph_04 = new  BiGraph<TObject>(DstrBase::USER);
    
    // weight methods in USER-allocation mode
    //
    if (!graph_04->isWeighted()) {
      return Error::handle(name(), L"isWeighted", Error::TEST,
			   __FILE__, __LINE__);
    }
    graph_04->setWeighted(false);
    if (graph_04->isWeighted()) {
      return Error::handle(name(), L"setWeighted", Error::TEST,
			   __FILE__, __LINE__);
    }
    graph_04->setWeighted(true);
    
    // check the directed methods in USER-allocation mode
    //
    // weight methods in USER-allocation mode
    //
    A = new Char('A');
    VA = graph_04->insertVertex(A);
    graph_04->insertArc(graph_04->getStart(), VA, false, 0.1);  
    graph_04->insertArc(VA, graph_04->getStart(), false, 0.1);  
    graph_04->insertArc(VA, graph_04->getTerm(), false, 0.3);
    graph_04->insertArc(graph_04->getTerm(), VA, false, 0.3);
    
    // the start vertex should a weighted arc to VA
    //
    my_arc = graph_04->getStart()->getFirstChild();    
    if ((my_arc->getVertex() != VA) &&
	(!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
      return Error::handle(name(), L"insertArc", Error::TEST,
			   __FILE__, __LINE__);
    }

    // VA should a weighted arc to the start vertex
    //
    ver_test = my_arc->getVertex();
    my_arc = ver_test->getFirstParent();    
    if ((my_arc->getVertex() != graph_04->getStart()) &&
	(!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
      return Error::handle(name(), L"insertArc", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    more_nodes = graph_04->gotoFirst();
    
    while (more_nodes) {
      
      // VA should a weighted arc to the term vertex
      //
      BiGraphVertex<TObject>* my_vertex =
	(BiGraphVertex<TObject>*)graph_04->getCurr();
      
      my_vertex->setMarkChild();    
      my_vertex->gotoFirstChild();
      BiGraphArc<TObject>* my_arc = my_vertex->getCurrChild();
      
      if (my_vertex == VA) {
	if ((my_arc->getVertex() == graph_04->getStart()) &&
	    (!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
	  return Error::handle(name(), L"insertArc", Error::TEST,
			       __FILE__, __LINE__);
	}      
      }
      
      my_vertex->gotoNextChild();
      my_arc = my_vertex->getCurrChild();
      
      if (my_vertex == VA) {    
	if ((my_arc->getVertex() == graph_04->getTerm()) &&
	    (!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
	  return Error::handle(name(), L"insertArc", Error::TEST,
			       __FILE__, __LINE__);
	}
      }

      // term vertex should have a weighted arc to VA
      //
      if (my_vertex == graph_04->getTerm()) {
	my_vertex->gotoFirstParent();
	my_arc = my_vertex->getCurrParent();
	if ((my_arc->getVertex() != VA) &&
	    (!Integral::almostEqual((double)my_arc->getWeight(), 0.1))) {
	  return Error::handle(name(), L"insertArc", Error::TEST,
			       __FILE__, __LINE__);
	}    
      }
      
      my_vertex->gotoMarkChild();    
      more_nodes = graph_04->gotoNext();
    }
    
    // the end vertex should a weighted arc to VA
    //
    my_arc = graph_04->getTerm()->getFirstChild();    
    if ((my_arc->getVertex() != VA) &&
	(!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
      return Error::handle(name(), L"insertArc", Error::TEST,
			   __FILE__, __LINE__);
    }

    // the VA should a weighted arc to the term vertex
    //
    ver_test = my_arc->getVertex();
    ver_test->gotoLastParent();
    my_arc = ver_test->getCurrParent();
    
    if ((my_arc->getVertex() != graph_04->getTerm()) &&
	(!Integral::almostEqual((double)my_arc->getWeight(), 0.3))) {
      return Error::handle(name(), L"insertArc", Error::TEST,
			   __FILE__, __LINE__);
    }
    
    // clean up memory
    //
    graph_04->clear(Integral::FREE);

    delete graph_04;
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  // --------------------------------------------------------------------
  //
  // 4. class-specific public methods:
  //     graph ordering methods
  //
  // --------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific public methods: graph ordering methods...\n");
    Console::increaseIndention(); 
  }

  // test topological sort in SYSTEM-allocation mode
  //
  //  T. Cormen, C. Leiserson, R. Rivest, "Exercise 23.4-1", Introduction to
  //  Algorithms, MIT Press, Boston, Massachusetts, USA, pp. 487, 1998.
  //
  BiGraph<Char> dag_00;

  // create the graph to be topologically sorted
  //
  Char* my_chr;
  my_chr = new Char(L'm');
  BiGraphVertex<Char>* ptr_m = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'n');
  BiGraphVertex<Char>* ptr_n = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'o');
  BiGraphVertex<Char>* ptr_o = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'p');
  BiGraphVertex<Char>* ptr_p = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'q');
  BiGraphVertex<Char>* ptr_q = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'r');
  BiGraphVertex<Char>* ptr_r = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L's');
  BiGraphVertex<Char>* ptr_s = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L't');
  BiGraphVertex<Char>* ptr_t = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'u');
  BiGraphVertex<Char>* ptr_u = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'v');
  BiGraphVertex<Char>* ptr_v = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'w');
  BiGraphVertex<Char>* ptr_w = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'x');
  BiGraphVertex<Char>* ptr_x = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'y');
  BiGraphVertex<Char>* ptr_y = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  my_chr = new Char(L'z');
  BiGraphVertex<Char>* ptr_z = dag_00.insertVertex(my_chr);
  delete my_chr;
  
  // insert all the arcs
  //
  dag_00.insertArc(ptr_m, ptr_q);
  dag_00.insertArc(ptr_m, ptr_r);
  dag_00.insertArc(ptr_m, ptr_x);
  dag_00.insertArc(ptr_n, ptr_o);
  dag_00.insertArc(ptr_n, ptr_q);
  dag_00.insertArc(ptr_n, ptr_u);
  dag_00.insertArc(ptr_o, ptr_r);
  dag_00.insertArc(ptr_o, ptr_s);
  dag_00.insertArc(ptr_o, ptr_v);
  dag_00.insertArc(ptr_p, ptr_o);
  dag_00.insertArc(ptr_p, ptr_s);
  dag_00.insertArc(ptr_p, ptr_z);
  dag_00.insertArc(ptr_q, ptr_t);
  dag_00.insertArc(ptr_r, ptr_u);
  dag_00.insertArc(ptr_r, ptr_y);
  dag_00.insertArc(ptr_s, ptr_r);
  dag_00.insertArc(ptr_u, ptr_t);
  dag_00.insertArc(ptr_v, ptr_w);
  dag_00.insertArc(ptr_v, ptr_x);
  dag_00.insertArc(ptr_w, ptr_z);
  dag_00.insertArc(ptr_y, ptr_v);

  // create a color hash table
  //
  dag_00.makeColorHash();
  
  // create the solution vector - in SYSTEM mode
  //
  DoubleLinkedList<Char> topo_sorted_result;
  topo_sorted_result.insert(ptr_p->getItem());
  topo_sorted_result.insert(ptr_n->getItem());
  topo_sorted_result.insert(ptr_o->getItem());
  topo_sorted_result.insert(ptr_s->getItem());
  topo_sorted_result.insert(ptr_m->getItem());
  topo_sorted_result.insert(ptr_r->getItem());
  topo_sorted_result.insert(ptr_y->getItem());
  topo_sorted_result.insert(ptr_v->getItem());
  topo_sorted_result.insert(ptr_x->getItem());
  topo_sorted_result.insert(ptr_w->getItem());
  topo_sorted_result.insert(ptr_z->getItem());
  topo_sorted_result.insert(ptr_u->getItem());
  topo_sorted_result.insert(ptr_q->getItem());
  topo_sorted_result.insert(ptr_t->getItem());
  
  // run a topological sort
  //
  DoubleLinkedList<Char> sorted_list(DstrBase::USER);
  dag_00.topologicalSort(sorted_list);

  if (!sorted_list.eq(topo_sorted_result)) {
    topo_sorted_result.debug(L"expected sort");
    sorted_list.debug(L"actual topo sort");
    return Error::handle(name(), L"topologicalSort", Error::TEST,
			 __FILE__, __LINE__);
  }

  if (level_a >= Integral::ALL) {
    sorted_list.debug(L"actual topo sort");
  }
  
  // test color setting
  //
  dag_00.setColor(Integral::WHITE);
  
  if (!dag_00.isColor(Integral::WHITE)) {
    return Error::handle(name(), L"setColor", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (dag_00.isColor(Integral::BLACK)) {
    return Error::handle(name(), L"setColor", Error::TEST,
			 __FILE__, __LINE__);
  }
  dag_00.invertColor();
  if (!dag_00.isColor(Integral::BLACK)) {
    return Error::handle(name(), L"invertColor", Error::TEST,
			 __FILE__, __LINE__);
  }
  dag_00.replaceColor(Integral::BLACK, Integral::GREY);
  if (!dag_00.isColor(Integral::GREY)) {
    return Error::handle(name(), L"replaceColor", Error::TEST,
			 __FILE__, __LINE__);
  }

  if (dag_00.isColor(Integral::BLACK)) {
    return Error::handle(name(), L"setColor", Error::TEST,
			 __FILE__, __LINE__);
  }

  if (!dag_00.isColor(Integral::GREY)) {
    return Error::handle(name(), L"setColor", Error::TEST,
			 __FILE__, __LINE__);
  }

  
  // clean up memory
  //
  dag_00.clear(Integral::FREE);

  // declare a graph
  //
  BiGraph<Char> dag_01;
  
  // create the nodes
  //
  my_chr = new Char(L'm');
  dag_01.insertVertex(my_chr);
  ptr_m = (BiGraphVertex<Char>*)dag_01.getCurr();
  delete my_chr;
  
  my_chr = new Char(L'n');
  dag_01.insertVertex(my_chr);
  ptr_n = (BiGraphVertex<Char>*)dag_01.getCurr();
  delete my_chr;
  
  my_chr = new Char(L'o');
  dag_01.insertVertex(my_chr);
  ptr_o = (BiGraphVertex<Char>*)dag_01.getCurr();
  delete my_chr;
  
  my_chr = new Char(L'p');
  dag_01.insertVertex(my_chr);    
  ptr_p = (BiGraphVertex<Char>*)dag_01.getCurr();
  delete my_chr;
  
  my_chr = new Char(L'q');
  dag_01.insertVertex(my_chr);    
  ptr_q = (BiGraphVertex<Char>*)dag_01.getCurr();
  delete my_chr;
  
  // create a color hash table
  //
  dag_01.makeColorHash(Integral::GREEN);

  // test the makeColorHash method
  //
  if (dag_01.isColor(Integral::WHITE)) {
    return Error::handle(name(), L" makeColorHash", Error::TEST,
			 __FILE__, __LINE__);
  }
  if (!dag_01.isColor(Integral::GREEN)) {
    return Error::handle(name(), L" makeColorHash", Error::TEST,
			 __FILE__, __LINE__);
  }  
  
  // test the getColor method
  //
  for (boolean nodes_remain = dag_01.gotoFirst();
       nodes_remain;
       nodes_remain = dag_01.gotoNext()) {
    
    if (dag_01.getColor(dag_01.getCurr()) != Integral::GREEN) {
      return Error::handle(name(), L"getColor", Error::TEST,
			   __FILE__, __LINE__);
    }
  }
      
  // clean up memory
  //
  dag_01.clear(Integral::FREE);

  // declare some graphs
  //
  BiGraph<Char> dag_02;

  // insert some vertices
  //
  my_chr = new Char(L'm');
  dag_02.insertVertex(my_chr);
  ptr_m = (BiGraphVertex<Char>*)dag_01.getCurr();
  delete my_chr;
  
  my_chr = new Char(L'n');
  dag_02.insertVertex(my_chr);
  ptr_n = (BiGraphVertex<Char>*)dag_01.getCurr();
  delete my_chr;
  
  // create a color hash table
  //
  dag_02.makeColorHash(Integral::GREEN);

  // test the releaseColorHash method
  //
  dag_02.releaseColorHash();

  // clean up memory
  //
  dag_02.clear(Integral::FREE);

  {
    // test topological sort in USER-allocation mode
    //
    BiGraph<Char> dag_00(DstrBase::USER);
    
    // create the nodes
    //
    Char* my_chr;
    my_chr = new Char(L'm');
    BiGraphVertex<Char>* ptr_m = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'n');
    BiGraphVertex<Char>* ptr_n = dag_00.insertVertex(my_chr);

    my_chr = new Char(L'o');
    BiGraphVertex<Char>* ptr_o = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'p');
    BiGraphVertex<Char>* ptr_p = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'q');
    BiGraphVertex<Char>* ptr_q = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'r');
    BiGraphVertex<Char>* ptr_r = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L's');
    BiGraphVertex<Char>* ptr_s = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L't');
    BiGraphVertex<Char>* ptr_t = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'u');
    BiGraphVertex<Char>* ptr_u = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'v');
    BiGraphVertex<Char>* ptr_v = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'w');
    BiGraphVertex<Char>* ptr_w = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'x');
    BiGraphVertex<Char>* ptr_x = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'y');
    BiGraphVertex<Char>* ptr_y = dag_00.insertVertex(my_chr);
    
    my_chr = new Char(L'z');
    BiGraphVertex<Char>* ptr_z = dag_00.insertVertex(my_chr);
    
    // insert all the arcs
    //
    dag_00.insertArc(ptr_m, ptr_q);
    dag_00.insertArc(ptr_m, ptr_r);
    dag_00.insertArc(ptr_m, ptr_x);
    dag_00.insertArc(ptr_n, ptr_o);
    dag_00.insertArc(ptr_n, ptr_q);
    dag_00.insertArc(ptr_n, ptr_u);
    dag_00.insertArc(ptr_o, ptr_r);
    dag_00.insertArc(ptr_o, ptr_s);
    dag_00.insertArc(ptr_o, ptr_v);
    dag_00.insertArc(ptr_p, ptr_o);
    dag_00.insertArc(ptr_p, ptr_s);
    dag_00.insertArc(ptr_p, ptr_z);
    dag_00.insertArc(ptr_q, ptr_t);
    dag_00.insertArc(ptr_r, ptr_u);
    dag_00.insertArc(ptr_r, ptr_y);
    dag_00.insertArc(ptr_s, ptr_r);
    dag_00.insertArc(ptr_u, ptr_t);
    dag_00.insertArc(ptr_v, ptr_w);
    dag_00.insertArc(ptr_v, ptr_x);
    dag_00.insertArc(ptr_w, ptr_z);
    dag_00.insertArc(ptr_y, ptr_v);

    // create a color hash table
    //
    dag_00.makeColorHash();
  
    // run a topological sort
    //
    DoubleLinkedList<Char> sorted_list(DstrBase::USER);
    dag_00.topologicalSort(sorted_list);
    if (!sorted_list.eq(topo_sorted_result)) {
      topo_sorted_result.debug(L"expected sort");
      sorted_list.debug(L"actual topo sort");
      return Error::handle(name(), L"topologicalSort", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (level_a >= Integral::ALL) {
      sorted_list.debug(L"actual topo sort");
    }
    
    // test color setting
    //
    dag_00.setColor(Integral::WHITE);
    
    if (!dag_00.isColor(Integral::WHITE)) {
      return Error::handle(name(), L"setColor", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (dag_00.isColor(Integral::BLACK)) {
      return Error::handle(name(), L"setColor", Error::TEST,
			   __FILE__, __LINE__);
    }
    dag_00.invertColor();
    if (!dag_00.isColor(Integral::BLACK)) {
      return Error::handle(name(), L"invertColor", Error::TEST,
			   __FILE__, __LINE__);
    }
    dag_00.replaceColor(Integral::BLACK, Integral::GREY);
    if (!dag_00.isColor(Integral::GREY)) {
      return Error::handle(name(), L"replaceColor", Error::TEST,
			   __FILE__, __LINE__);
    }

    // clean up memory
    //
    dag_00.clear(Integral::FREE);

    // declare a graph
    //
    BiGraph<Char> dag_01(DstrBase::USER);
    
    // create the nodes
    //
    my_chr = new Char(L'm');
    ptr_m = dag_01.insertVertex(my_chr);
    
    my_chr = new Char(L'n');
    ptr_n = dag_01.insertVertex(my_chr);
    
    my_chr = new Char(L'o');
    ptr_o = dag_01.insertVertex(my_chr);
    
    my_chr = new Char(L'p');
    ptr_p = dag_01.insertVertex(my_chr);    
    
    my_chr = new Char(L'q');
    ptr_q = dag_01.insertVertex(my_chr);    
    
    // create a color hash table
    //
    dag_01.makeColorHash(Integral::GREEN);
    
    // test the makeColorHash method
    //
    if (dag_01.isColor(Integral::WHITE)) {
      return Error::handle(name(), L" makeColorHash", Error::TEST,
			   __FILE__, __LINE__);
    }
    if (!dag_01.isColor(Integral::GREEN)) {
      return Error::handle(name(), L" makeColorHash", Error::TEST,
			   __FILE__, __LINE__);
    }  
    
    // test the getColor method
    //
    for (boolean nodes_remain = dag_01.gotoFirst();
	 nodes_remain;
	 nodes_remain = dag_01.gotoNext()) {
      
      if (dag_01.getColor(dag_01.getCurr()) != Integral::GREEN) {
	return Error::handle(name(), L"getColor", Error::TEST,
			     __FILE__, __LINE__);
      }
    }
    
    // clean up memory
    //
    dag_01.clear(Integral::FREE);

    // declare some graphs
    //
    BiGraph<Char> dag_02(DstrBase::USER);

    // insert some vertices
    //
    my_chr = new Char(L'm');
    dag_02.insertVertex(my_chr);
    ptr_m = (BiGraphVertex<Char>*)dag_01.getCurr();
    
    my_chr = new Char(L'n');
    dag_02.insertVertex(my_chr);
    ptr_n = (BiGraphVertex<Char>*)dag_01.getCurr();
    
    // create a color hash table
    //
    dag_02.makeColorHash(Integral::GREEN);
    
    // test the releaseColorHash method
    //
    dag_02.releaseColorHash();
    
    // clean up memory
    //
    dag_02.clear(Integral::FREE);
  }
  
  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }

  //---------------------------------------------------------------------
  //
  // 5. graph allocation mode methods
  //
  //---------------------------------------------------------------------

  // set indentation
  //
  if (level_a > Integral::NONE) {
    Console::put(L"testing class-specific public methods: graph allocation mode methods...\n");
    Console::increaseIndention(); 
  }
  
  // declare a graph
  //
  BiGraph<TObject> graph_05;

  // test the allocation mode
  //
  if (graph_05.getAllocationMode() != DstrBase::SYSTEM) {
    return Error::handle(name(), L"getAllocationMode", Error::TEST,
			 __FILE__, __LINE__);
  }

  graph_05.setAllocationMode(DstrBase::USER);
  if (graph_05.getAllocationMode() != DstrBase::USER) {
    return Error::handle(name(), L"setAllocationMode", Error::TEST,
    __FILE__, __LINE__);
			 }

  // reset indentation
  //
  if (level_a > Integral::NONE) {
  Console::decreaseIndention();
  }

  //---------------------------------------------------------------------
  //
  // 6. print completion message
  //
  //---------------------------------------------------------------------  

  // reset indentation
  //
  if (level_a > Integral::NONE) {
    Console::decreaseIndention();
  }
  
  if (level_a > Integral::NONE) {
    SysString output(L"diagnostics passed for class ");
    output.concat(name());
    output.concat(L"\n");
    Console::put(output);
  }  
  
  // exit gracefully
  //
  return true;  
 }

// end of include file
//
#endif
