//------------------------------------------------------------------------------------------------------------------------------
void ImplTreetorDistance::calculateTree(
		HTree & tree,
		const HMultipleAlignment & mali ) const
{

	debug_func_cerr( 5 );
	startUp( tree, mali );

	DistanceMatrixSize swap_temp;	// for swapping indices

#define SWAP(x,y) { swap_temp = x; x = y; y = swap_temp; }

	//------------------------------------------------------------------------------------------
	// start up
	DistanceMatrixSize width = mWorkMatrix->getWidth();
	DistanceMatrixSize i;

	/* in this algorithm I assume that the matrix I use is only a half-matrix using the lower diagonal */
	tree->setNumLeaves( width );					// allocate memory for tree

	mIndices = new Node[width];			        /* allocate array to keep track of indices */

	for (i = 0; i < width; i++) mIndices[i] = i;

	//----------------------------------------------------------------------------------------------------
	// Perform hierarchical clustering

	DistanceMatrixSize last_row = width - 1;

	/* shrink distance matrix, until it contains only a single cluster */
	while (last_row > 0)
	{

	  debug_cerr( 6, "Last row " << last_row );
	  debug_cerr( 6, "Work matrix " << endl << *mWorkMatrix );

    // find minimum distance in matrix
    /*
	-
	--
	---
	----
	-x---
	------
	-------
	--------
      */
    calculateMinimumDistance();
    DistanceMatrixSize min_row = mMinimumCoord.row;
    DistanceMatrixSize min_col = mMinimumCoord.col;

    debug_cerr( 5, "Joining nodes -> "
			    << "minimum distance :" << mMinimumValue << " "
			    << "node 1: " << mIndices[min_row] << " (" << min_row << ") "
			    << "node 2: " << mIndices[min_col] << " (" << min_col << ") " );

    //------------------------------------------------------------------------------------------------------
    // move rows around, so that the last two joined cluster are in the two last rows

    /*
	-			-
	y-			--
	-y-			---
	-y--		->	----
	xOxx-			-----
	-y--x-			------
	-y--x--			xxxxxxx
	-y--x---		yyyyyyyy
    */

    DistanceMatrixSize second_row = last_row - 1;		// second to last row

    // exchange row with last row
    mWorkMatrix->swap( min_row, last_row);
    SWAP( mIndices[min_row], mIndices[last_row]);
    swapHelpers( min_row, last_row);

    // exchange col with second to last row
    mWorkMatrix->swap( min_col, second_row);
    SWAP( mIndices[min_col], mIndices[second_row]);
    swapHelpers( min_col, second_row);

    //------------------------------------------------------------------------------------------------------
    // join the two nodes in the tree giving the correct edge weights
    Node new_node = joinNodes( tree, second_row, last_row );

    debug_cerr( 6, "-> new node " << new_node );

    //------------------------------------------------------------------------------------------------------
    // calculate distance to new cluster and put them in second to last row
    updateDistanceMatrix( tree, second_row, last_row);

    /* delete last row, update mIndices, so that the last row now
       contains the number of the new cluster id */
    /*
	-	       	-
	--	       	--
	---	       	---
	----	     ->	----
	-----		-----
	------		------
	xxxxxxx		xxxxxxx
	yyyyyyyy
    */

    mWorkMatrix->shrink();

    mIndices[last_row - 1] = new_node;

    last_row = mWorkMatrix->getWidth() - 1;

  }

  delete [] mIndices;
  cleanUp();	// cleans up mWorkMatrix

}
void pn::Init() {

	PNFactory* instance = PNFactory::GetInstance();

    instance->Init();

	//Input Node Queue

    Node* p1 = instance->createNode("p1", PlaceObjectType, SingleToken);
    Node* p2 = instance->createNode("p2", PlaceObjectType, SingleToken);
	Node* p3 = instance->createNode("p3", PlaceObjectType, SingleToken);

	//Input Node

    Node* t1 = instance->createNode("t1", TransitionObjectType, SingleToken);
	Node* t2 = instance->createNode("t2", TransitionObjectType, SingleToken);
	Node* t3 = instance->createNode("t3", TransitionObjectType, SingleToken);

	//Routing Queue

	Node* p4 = instance->createNode("p4 (routing queue)", PlaceObjectType, SingleToken);
	
	//Routing

	Node* t4 = instance->createNode("t4 (routing)", TransitionObjectType, SingleToken);

	//Output Node Queue

	Node* p5 = instance->createNode("p5", PlaceObjectType, SingleToken);
    Node* p6 = instance->createNode("p6", PlaceObjectType, SingleToken);
	Node* p7 = instance->createNode("p7", PlaceObjectType, SingleToken);

	//Output Node

	Node* t5 = instance->createNode("t5", TransitionObjectType, SingleToken);
	Node* t6 = instance->createNode("t6", TransitionObjectType, SingleToken);
	Node* t7 = instance->createNode("t7", TransitionObjectType, SingleToken);

	//Output

	Node* p8 = instance->createNode("p8", PlaceObjectType, SingleToken);
    Node* p9 = instance->createNode("p9", PlaceObjectType, SingleToken);
	Node* p10 = instance->createNode("p10", PlaceObjectType, SingleToken);

	//Input Node Queue & Input Node
	
    joinNodes(p1, t1);
    joinNodes(p2, t2);
	joinNodes(p3, t3);

	//Input Node & Routing Queue

    joinNodes(t1, p4);
    joinNodes(t2, p4);
	joinNodes(t3, p4);
	
	//Routing Queue & Routing

    joinNodes(p4, t4);

	//Routing & Output Node Queue

    joinNodes(t4, p5);
    joinNodes(t4, p6);
	joinNodes(t4, p7);

	//Output Node Queue & Output

	joinNodes(p5, t5);
    joinNodes(p6, t6);
	joinNodes(p7, t7);

	//Output & Final Place

    joinNodes(t5, p8);
    joinNodes(t6, p9);
	joinNodes(t7, p10);
	
	//Connect Generator

	gm::addNewGenerator(p1, 1, 250);
	gm::addNewGenerator(p2, 2, 250);
	gm::addNewGenerator(p3, 3, 250);

}