class WIGG
{
  public static void main(String args[])
  {
      if(args.length!=2)
      {  
	  System.out.println("You have not supplied the two pieces of data necessary to run this program.");
	  System.out.println("The first entry must be B, Q, K, or N, representing a bishop, queen, king, or nighrider");
	  System.out.println("The second entry must be an integer, representing the number of rows of the board.");
	  System.out.println("Example: java WIGG Q 3");
	  return;
      }

      char[] Board = args[0].toCharArray();
      if(Board.length > 1)
      {  
	  System.out.println("The first piece of data you have supplied is not a single character.");
	  System.out.println("The first entry must be B, Q, K, or N, representing a bishop, queen, king, or nighrider");
	  System.out.println("The second entry must be an integer, representing the number of rows of the board.");
	  return;
      }

      char boardType = Board[0];

      switch (boardType) {
            case 'B':  boardType = 'B'; break;
            case 'b':  boardType = 'B'; break;
            case 'Q':  boardType = 'Q'; break;
            case 'q':  boardType = 'Q'; break;
            case 'K':  boardType = 'K'; break;
            case 'k':  boardType = 'K'; break;
            case 'N':  boardType = 'N'; break;
            case 'n':  boardType = 'N'; break;
            default: 
		System.out.println("Invalid board type."); 	  
		System.out.println("The first entry must be B, Q, K, or N, representing a bishop, queen, king, or nighrider");
		System.out.println("The second entry must be an integer, representing the number of rows of the board.");
		return; 
        }
      int NumNodes = 0;

      try {
	  NumNodes = Integer.parseInt(args[1]);
      }
      catch (NumberFormatException e) {
		System.out.println("Invalid board size."); 	  
		System.out.println("The first entry must be B, Q, K, or N, representing a bishop, queen, king, or nighrider");
		System.out.println("The second entry must be an integer, representing the number of rows of the board.");
      return;
      }
      ///////////////Graph Creation////////////////////

      int count, count2, NumEdges, EdgeNum;
      Graph myGraph = new Graph();
      Node[] Node_List = null;

      switch(boardType) {

      /***************For a bishop graph: *************/
      case 'B':
	  // int NumNodes = 3;
	  Node[] NodeArrayB = new Node[NumNodes];
	  Edge[][] EdgeArrayB = new Edge[NumNodes][NumNodes];
	  int[][][] GainArrayB = new int[NumNodes][NumNodes][2];
	  Edge[] Edge_ListB = new Edge[NumNodes*(NumNodes-1)/2];
	  for(count=0;count<NumNodes;count++)
	      NodeArrayB[count] = new Node(count,0);
	  EdgeNum = 0;
	  for(count=0;count<NumNodes;count++)
	      for(count2=count+1;count2<NumNodes;count2++)
	      {
		  GainArrayB[count][count2][0] = count-count2;
		  GainArrayB[count][count2][1] = count2-count;
		  EdgeArrayB[count][count2] = new Edge(NodeArrayB[count],NodeArrayB[count2],GainArrayB[count][count2]);
		  Edge_ListB[EdgeNum] = EdgeArrayB[count][count2];
		  EdgeNum++;
	      }
	  Node_List = NodeArrayB;
	  myGraph = new Graph(Node_List, Edge_ListB);
	  System.out.println("#We are placing " + NumNodes + " bishops on a board with " + NumNodes + " rows.");
	  System.out.println("#The weighted integral gain graph that represents this situation is as follows.");
	  System.out.println(myGraph);
      break;
      /********************/

      /***************For a queen graph:***************/
      case 'Q':
	  // int NumNodes = 3;
	  Node[] NodeArrayQ = new Node[NumNodes];
	  Edge[][] EdgeArrayQ = new Edge[NumNodes][NumNodes];
	  int[][][] GainArrayQ = new int[NumNodes][NumNodes][3];
	  Edge[] Edge_ListQ = new Edge[NumNodes*(NumNodes-1)/2];
	  for(count=0;count<NumNodes;count++)
	      NodeArrayQ[count] = new Node(count,0);
	  EdgeNum = 0;
	  for(count=0;count<NumNodes;count++)
	      for(count2=count+1;count2<NumNodes;count2++)
	      {
		  GainArrayQ[count][count2][0] = 0;
		  GainArrayQ[count][count2][1] = count-count2;
		  GainArrayQ[count][count2][2] = count2-count;
		  EdgeArrayQ[count][count2] = new Edge(NodeArrayQ[count],NodeArrayQ[count2],GainArrayQ[count][count2]);
		  Edge_ListQ[EdgeNum] = EdgeArrayQ[count][count2];
		  EdgeNum++;
	      }
	  Node_List = NodeArrayQ;
	  myGraph = new Graph(Node_List, Edge_ListQ);
	  System.out.println("#We are placing " + NumNodes + " queens on a board with " + NumNodes + " rows.");
	  System.out.println("#The weighted integral gain graph that represents this situation is as follows.");
	  System.out.println(myGraph);
      break;
      /********************/

      /***************For a knight graph: *************/
      case 'K':
	  //int NumNodes = 2;
	  NumEdges = NumNodes*2-3;
	  Node_List = new Node[NumNodes];
	  Edge[] Edge_ListK = new Edge[NumEdges];
	  int[][] GainArrayK = new int[NumEdges][2];
	  for(count=0;count<NumNodes;count++)
	      Node_List[count] = new Node(count,0);
	  EdgeNum = 0;
	  for(count=0;count<NumNodes-1;count++)
	  {
	      GainArrayK[count][0] = -2;
	      GainArrayK[count][1] = 2;
	      Edge_ListK[count] = new Edge(Node_List[count],Node_List[count+1],GainArrayK[count]);
	      if(count!=NumNodes-2)
	      {
		  GainArrayK[NumNodes-1+count][0] = -1;	      
		  GainArrayK[NumNodes-1+count][1] = 1;
		  Edge_ListK[NumNodes-1+count] = new Edge(Node_List[count],Node_List[count+2],GainArrayK[NumNodes-1+count]);
	      }
	  }
	  myGraph = new Graph(Node_List, Edge_ListK);
	  System.out.println("#We are placing " + NumNodes + " knights on a board with " + NumNodes + " rows.");
	  System.out.println("#The weighted integral gain graph that represents this situation is as follows.");
	  System.out.println(myGraph);
      break;
      /********************/

      /***************For a nightrider graph: *********/
      case 'N': 
	  //int NumNodes = 4;
	  NumEdges = NumNodes*(NumNodes-1)/2; //Counts number of edges of height 1.
	  Node[] NodeArrayN = new Node[NumNodes];
	  Edge[][] EdgeArrayN = new Edge[NumNodes][NumNodes];
	  int[][][] GainArrayN = new int[NumNodes][NumNodes][2];
	  Edge[][] EdgeArray2N = new Edge[NumNodes][NumNodes];
	  int[][][] GainArray2N = new int[NumNodes][NumNodes][2];
	  Edge[] Edge_ListN = new Edge[NumEdges+(int) Math.floor((NumNodes-1)*(NumNodes-1)/4)]; //Now includes edges of height 2.
	  for(count=0;count<NumNodes;count++)
	      NodeArrayN[count] = new Node(count,0);
	  EdgeNum = 0;
	  for(count=0;count<NumNodes;count++)
	      for(count2=count+1;count2<NumNodes;count2++)
	      {
		  GainArrayN[count][count2][0] = -2;
		  GainArrayN[count][count2][1] = 2;
		  EdgeArrayN[count][count2] = new Edge(NodeArrayN[count],NodeArrayN[count2],GainArrayN[count][count2]);
		  Edge_ListN[EdgeNum] = EdgeArrayN[count][count2];
		  EdgeNum++;
	      }
	  for(count=0;count<NumNodes;count++)
	      for(count2=count+2;count2<NumNodes;count2+=2)
	      {
		  GainArray2N[count][count2][0] = -1;
		  GainArray2N[count][count2][1] = 1;
		  EdgeArray2N[count][count2] = new Edge(NodeArrayN[count],NodeArrayN[count2],GainArray2N[count][count2]);
		  Edge_ListN[EdgeNum] = EdgeArray2N[count][count2];
		  EdgeNum++;
	      }
	  
	  Node_List = NodeArrayN;
	  myGraph = new Graph(Node_List, Edge_ListN);
	  System.out.println("#We are placing " + NumNodes + " nightriders on a board with " + NumNodes + " rows.");
	  System.out.println("#The weighted integral gain graph that represents this situation is as follows.");
	  System.out.println(myGraph);
      break;
      /********************/
      }

      /**  Here is an example of inputting a graph by hand:
      Node Node1 = new Node(1,0);
      Node Node2 = new Node(2,0);
      Node Node3 = new Node(3,0);
      Node Node4 = new Node(4,0);
      int[] Gains12 = {0,-1,1};
      int[] Gains23 = {0,-1,1};
      int[] Gains13 = {0,-2,2};
      int[] Gains34 = {0,-1,1};
      int[] Gains24 = {0,-2,2};
      int[] Gains14 = {0,-3,3};
      Edge Edge12 = new Edge(Node1, Node2, Gains12);
      Edge Edge23 = new Edge(Node2, Node3, Gains23);
      Edge Edge13 = new Edge(Node1, Node3, Gains13);
      Edge Edge34 = new Edge(Node3, Node4, Gains34);
      Edge Edge24 = new Edge(Node2, Node4, Gains24);
      Edge Edge14 = new Edge(Node1, Node4, Gains14);
      Node[] Node_List = {Node1, Node2, Node3, Node4};
      Edge[] Edge_List = {Edge12, Edge23, Edge13, Edge34, Edge24, Edge14};
      Graph myGraph = new Graph(Node_List,Edge_List);
      **/
      //////////////End Graph Creation/////////////////


      //Expansion will start with our initial graph, and then run deletion and contraction until we're done.
      Graph[] Expansion = {myGraph};
      int ex_count = 0;  //(Expansion counter) 
      //Tells us that we are investigating graph #0.  Will increment when graph counter contains only isolated vertices
     
      int NL;             //Represents the current non-loop edge in the current graph.
      Graph c_graph;      Edge c_edge, c_edge2;  //Define the current graph and current edge.
      int i,j,k,l,c,ii,jj,kk;          //Counters
      boolean ZeroGain;   //Checks if the edge to be contracted has zero gain.
      int[][] NodeWeights = new int[0][Node_List.length];  

      //For each graph, find the first non-loop edge.  If there are none, collect the weights of the vertices.
      while(ex_count<Expansion.length)
      {
	  c_graph = Expansion[ex_count]; //current graph.
//System.out.println("///////////////////// I am working on graph " + ex_count + " which was spawned by graph " + Expansion[ex_count].PrevGraph() + " //////////////");
//System.out.println(c_graph);
	  NL = 0; //Represents the index of the first edge that is not a loop.	  
	  while(NL<c_graph.EdgeSet().length)
	      {
//System.out.println("\\\\\\\\\\\\\\\\\\\\ I am working on edge " + NL + " \\\\\\\\\\\\");
		  c_graph = Expansion[ex_count]; //current graph.
//The following is a real mess.  The reason for it is because of how crazy java gets with pointers.
//In order to redefine a graph, we need to create a whole new graph structure, which means creating
//a whole NEW set of Nodes, a whole NEW set of Edges on those NEW nodes, and then a whole NEW graph with them.

//c_edge is a NEW edge, used in the deletion part of the deletion-contraction
		  int[] new_gain3 = new int[c_graph.EdgeSet()[NL].gain().length];
		  for(l=0;l<c_graph.EdgeSet()[NL].gain().length;l++)
		      new_gain3[l] = c_graph.EdgeSet()[NL].gain()[l];
		  c_edge = new Edge(c_graph.EdgeSet()[NL].initial(),c_graph.EdgeSet()[NL].terminal(),new_gain3);

//c_edge2 is a NEW edge, used in the contraction part of the deletion-contraction
		  int[] new_gain4 = new int[c_graph.EdgeSet()[NL].gain().length];
		  for(l=0;l<c_graph.EdgeSet()[NL].gain().length;l++)
		      new_gain4[l] = c_graph.EdgeSet()[NL].gain()[l];
		  c_edge2 = new Edge(c_graph.EdgeSet()[NL].initial(),c_graph.EdgeSet()[NL].terminal(),new_gain4);

//If the edge is not a loop, delete and contract.
		  if(!c_edge.isloop())             
		      {
//First, augment the size of the Expansion list by one.
			  Graph[] new_Expansion = new Graph[Expansion.length+1];  
			  for(i=0;i<Expansion.length;i++)
			      new_Expansion[i] = Expansion[i];

//Create a new list of Nodes and Edges for the deletion graph.
			  Node[] new_NodeSet2 = new Node[Expansion[ex_count].NodeSet().length];
			  for(i=0;i<Expansion[ex_count].NodeSet().length;i++)
			      new_NodeSet2[i] = new Node(Expansion[ex_count].NodeSet()[i].name(),Expansion[ex_count].NodeSet()[i].weight());
			  Edge[] new_EdgeSet2 = new Edge[Expansion[ex_count].EdgeSet().length];
			  for(i=0;i<Expansion[ex_count].EdgeSet().length;i++)
			      {
				  Node Inode2 = new Node(Expansion[ex_count].EdgeSet()[i].initial().name(),Expansion[ex_count].EdgeSet()[i].initial().weight());
				  Node Tnode2 = new Node(Expansion[ex_count].EdgeSet()[i].terminal().name(),Expansion[ex_count].EdgeSet()[i].terminal().weight());
				  int[] new_gain2 = new int[Expansion[ex_count].EdgeSet()[i].gain().length];
				  for(l=0;l<Expansion[ex_count].EdgeSet()[i].gain().length;l++)
				      new_gain2[l] = Expansion[ex_count].EdgeSet()[i].gain()[l];
				  new_EdgeSet2[i] = new Edge(Inode2,Tnode2,new_gain2);
			      }
			  int new_sign2 = Expansion[ex_count].sign();
//With these new Nodes and Edges, create the graph on which we'll do deletion.
			  Graph Deletion = new Graph(new_NodeSet2,new_EdgeSet2,new_sign2);

//Now do the same for contraction.
			  Node[] new_NodeSet = new Node[Expansion[ex_count].NodeSet().length];
			  for(i=0;i<Expansion[ex_count].NodeSet().length;i++)
			      new_NodeSet[i] = new Node(Expansion[ex_count].NodeSet()[i].name(),Expansion[ex_count].NodeSet()[i].weight());
			  Edge[] new_EdgeSet = new Edge[Expansion[ex_count].EdgeSet().length];
			  for(i=0;i<Expansion[ex_count].EdgeSet().length;i++)
			      {
				  Node Inode = new Node(Expansion[ex_count].EdgeSet()[i].initial().name(),Expansion[ex_count].EdgeSet()[i].initial().weight());
				  Node Tnode = new Node(Expansion[ex_count].EdgeSet()[i].terminal().name(),Expansion[ex_count].EdgeSet()[i].terminal().weight());
				  int[] new_gain = new int[Expansion[ex_count].EdgeSet()[i].gain().length];
				  for(l=0;l<Expansion[ex_count].EdgeSet()[i].gain().length;l++)
				      new_gain[l] = Expansion[ex_count].EdgeSet()[i].gain()[l];
				  new_EdgeSet[i] = new Edge(Inode,Tnode,new_gain);
			      }
			  int new_sign = Expansion[ex_count].sign();
			  Graph Contraction = new Graph(new_NodeSet,new_EdgeSet,new_sign);
		  //After all this setup, we can now go about the contracting and deleting.
//System.out.println("Now working on contracting.");
		  //First step:  negate the graph (deletion minus contraction)
		  Contraction.negate();          
		  //Keep track of which graph spawned this graph.
		  Contraction.set_PrevGraph(ex_count);

		  //Check if the edge being deleted has a zero gain.
		  ZeroGain=false;
		  for(i=0;i<c_edge.gain().length;i++)
		  {
		      ZeroGain = ZeroGain || c_edge.gain()[i]==0;
		  }
		  if(!ZeroGain)  //If there is no zero gain, then we'll just switch so that the first one is zero.
		  {              //There are two cases depending on whether the gain is positive or negative.
		      if(c_edge.gain()[0]>0)
			  Contraction.switching(c_edge.initial(),c_edge.gain()[0]);
		      else
			  Contraction.switching(c_edge.terminal(),(-1)*c_edge.gain()[0]);
		  }

		  //Fix c_edge to make sure node weights are correct.
		  int[] new_gain5 = new int[Contraction.EdgeSet()[NL].gain().length];
		  for(l=0;l<Contraction.EdgeSet()[NL].gain().length;l++)
		      new_gain5[l] = Contraction.EdgeSet()[NL].gain()[l];
		  c_edge = new Edge(Contraction.EdgeSet()[NL].initial(),Contraction.EdgeSet()[NL].terminal(),new_gain5);

//System.out.println("Contracting this edge:  " + c_edge);

		  Contraction.contract(c_edge);   //Now we're assured of a zero gain, so we can contract.
		  new_Expansion[Expansion.length] = Contraction;

//System.out.println("Now working on deleting.");
		  if(ZeroGain)   //If there is a zero gain, we contracted the zero multiedge.  
		  {              //Otherwise we contracted the first multiedge.
		      int[] Zero = {0};
		      c_edge2.new_gain(Zero);
		      Deletion.delete(c_edge2);
		  }
		  else
		      Deletion.delete(c_edge2);    
//Deletion:  Remove the first of the multiedges or (if not multi) the edge.

		  new_Expansion[ex_count]= Deletion;
		  Expansion = new_Expansion;
		  c_graph = Expansion[ex_count]; //current graph.
		      }
		  else
		      NL++;  //Now check the next edge.
	      }
	  //Once we've deleted every edge, we have some set of Node weights, which will tell us 
	  //The contribution of this term to our piecewise-defined polynomial. 
	  //So we should collect them in the NodeWeights array.  
	  int[][] new_NodeWeights = new int[NodeWeights.length+1][Node_List.length];
	  for(j=0;j<NodeWeights.length;j++)
	  {for(k=0;k<Node_List.length;k++)
	   {
	       new_NodeWeights[j][k] = NodeWeights[j][k];
	   }
	  }
	  for(k=0;k<Expansion[ex_count].Vertex_Weights().length;k++)
	      new_NodeWeights[NodeWeights.length][k] = Expansion[ex_count].Vertex_Weights()[k]; 
	  //For other graphs than the first graph, there will be fewer factors than Node_List.length
	  //So we'll designate -1 as the placeholder.
	  for(k=Expansion[ex_count].Vertex_Weights().length;k<Node_List.length;k++)
	      new_NodeWeights[NodeWeights.length][k] =-1;
	  NodeWeights = new_NodeWeights;
	  //ON TO THE NEXT GRAPH!!!
	  ex_count++;      	  
      }

      //The user might like to know how many graphs there were in all.
      System.out.println("#There were graphs labeled 0 through " + (ex_count-1) + " in the Expansion.");      

      //We sort the node weights, and then consolidate, adding together all contributions of graphs.
      sort_weights(NodeWeights);
      int[] contributions = new int[Expansion.length];
      for(i=0;i<Expansion.length;i++)
	  contributions[i]=Expansion[i].sign();
      consolidate_weights(NodeWeights,contributions);
      sort_weight_list(NodeWeights,contributions);

      //User-friendly output:
      System.out.println("#-----------------------\n#-----Node Weights------\n#-----------------------"      );
      for(jj=0;jj<NodeWeights.length;jj++)
      {
	  if(contributions[jj]!=0)
	  {System.out.print("#");
	      for(kk=0;kk<Node_List.length;kk++)
	   {
	       System.out.print("[" + NodeWeights[jj][kk] + "]");
	   }
	  System.out.println( " (contribution " + contributions[jj] + ")");
	  }
      }
      System.out.print("#-----------------------\n#A '-1' means fewer nodes\n#than the initial number");
      System.out.println("\n#exist due to contraction.\n#-----------------------");

      System.out.println("#-------Maple Code------\n#---to determine the----\n#polynomial for large n:");
      System.out.println("#-----------------------");
      System.out.print("\"Polynomial for large n = \" ,sort(expand(simplify(");
      for(jj=0;jj<NodeWeights.length;jj++)
      {
	  if(contributions[jj]!=0)
	      {System.out.print("("+ contributions[jj] + ")");
               for(kk=0;kk<Node_List.length;kk++)
	       {
		   if(NodeWeights[jj][kk]!=-1)
		       System.out.print("*(n-" + NodeWeights[jj][kk] + ")");
	       }
	       System.out.print( " + ");
	  }
      }
      System.out.println("0)));");

      System.out.println("#-----------------------");
      System.out.println("#-------Maple Code------\n#---of the piecewise----\n#--function for all n:--");
      System.out.println("#-----------------------");
      System.out.print("\"Piecewise Function = \" ,sort(simplify(convert(");
      for(jj=0;jj<NodeWeights.length;jj++)
      {
	  if(contributions[jj]!=0)
	      {System.out.print("("+ contributions[jj] + ")");
               for(kk=0;kk<Node_List.length;kk++)
	       {
		   if(NodeWeights[jj][kk]!=-1)
		       System.out.print("*piecewise(n>=" + NodeWeights[jj][kk] + ", n-" + NodeWeights[jj][kk] + ", 0)");
	       }
	       System.out.print( " + ");
	  }
      }
      System.out.println("0,piecewise)));");



      System.out.print("#-----------------------\n#-------Maple Code------\n#---to determine the----");
      System.out.println("\n#-generating function:--\n#-----------------------");

      System.out.println("with(SF): with(combinat):");
      System.out.println("Eulerian := (N,K) -> sum((-1)^J*binomial(N+1,J)*(K-J)^N,J=0..K):");
      System.out.println("EulerianPoly := (N) -> sum(sum((-1)^J*binomial(N+1,J)*(K-J)^N,J=0..K)*t^K,K=0..N):");
      System.out.println("ElemSF:= J -> if J=0 then 1 else e || J end if:");
      System.out.println("LPointCount := proc(N) local r;");
      System.out.println("unassign('n');");
      System.out.println("r:=nops(N);");
      System.out.println("[seq((-1)^(r-j)*evalsf(ElemSF(r-j),sum(n[r]-n[i],i=1..r-1))*EulerianPoly(j)/(1-t)^(j+1),j=1..r)];");
      System.out.println("simplify(t^(n[r])*add(%[i],i=1..nops(%)));");
      System.out.println("end proc:");
      System.out.println("LatticePointCount := N -> subs({seq(n[i]=(sort(N,`>`))[i],i=1..nops(N))},LPointCount(N)):");
      System.out.print("\"Generating Function = \" , sort(expand(simplify(");
      
      for(jj=0;jj<NodeWeights.length;jj++)
      {
	  if(contributions[jj]!=0)
	  {
	      System.out.print("("+ contributions[jj] + ")*LatticePointCount([");
              for(kk=0;kk<Node_List.length;kk++)
	      {
		  if(NodeWeights[jj][kk]!=-1)
		      System.out.print(NodeWeights[jj][kk]);
		  if(kk+1<Node_List.length && NodeWeights[jj][kk+1] != -1)
		      System.out.print(",");
	      }
	      System.out.print( "]) + ");
	  }
      }
      System.out.println("0)));");
  }

    public static void sort_weights(int[][] a)
    {
	int i,j;
	for(i=0;i<a.length;i++)
	{
	    for(j=1;j<a[i].length;j++)
	    {
		if(a[i][j]!=-1)
		    if(a[i][j]<a[i][j-1])
		    {
			int placeholder = a[i][j-1];
			a[i][j-1] = a[i][j];
			a[i][j] = placeholder;
			if(j>1)
			    j=0;  //I just changed this from j-- to j=0.
		    }
	    }
	}
    }




    public static void consolidate_weights(int[][] a, int[] contributions)
    {
	int i,j,k;	
	int NumNonZero = 1; //Counts how many non-duplicate rows there are.
	int[] nonduplicates = new int[a.length];
	int[][] consolidated = new int[a.length][a[0].length];
	int[] cons_cont = new int[contributions.length];
	for(j=0;j<a[0].length;j++)
	    consolidated[0][j]=a[0][j];
	int length_cons = 0;  //Tells us where to check in a.
	for(i=1;i<a.length;i++)
	    for(j=0;j<a[i].length;j++)
		consolidated[i][j]=-2;
	cons_cont[0] = contributions[0];
	for(j=1;j<a[0].length;j++)
	    cons_cont[j] = 0;

	boolean line_equals = true;
	boolean line_ever_equals = true;

	for(i=1;i<a.length;i++)
	{
	    //	for(j=0;j<cons_cont.length;j++)
	    //	    System.out.print("[" + cons_cont[j] + "]");
	    //	System.out.println();
	    //	    System.out.println("Length = " + length_cons);

	    line_ever_equals = false;
	    for(k=0;k<=length_cons;k++)
	    {
		line_equals = true;
		for(j=0;j<a[i].length;j++)
		{
		    line_equals = line_equals && (a[i][j]==consolidated[k][j]);
		}
		if(line_equals)
		{
		    for(j=0;j<a[i].length;j++)
			a[i][j] = 0;
		    cons_cont[k] = cons_cont[k] + contributions[i];
		    line_ever_equals = true;
		}
	    }
	    if(!line_ever_equals)
	    {
		length_cons = i;
		for(j=0;j<a[i].length;j++)
		    consolidated[i][j] = a[i][j];
		cons_cont[i] = contributions[i];
	    }
	}

	a = consolidated;
	for(i=0;i<contributions.length;i++)
	    contributions[i] = cons_cont[i];
    }

    //This method sorts the list of node weights for our human eyes.
    public static void sort_weight_list(int[][] a, int[] b)
    {
	int listlength = a[0].length;
	int i,j,k,l,m;
	boolean skiprest=false;
	int[] a_placeholder = new int[a[0].length];
	int b_placeholder = 0;

	for(i=0;i<a.length;i++)
	 for(j=i+1;j<a.length;j++)
	 {
	     k=0;
	     do 
	     {
		 if((b[j]!=0 && a[i][k]!=a[j][k]))
 	         {
		     if(a[j][k]<a[i][k] && a[j][k]!=-1)   //If the kth entry is inverted, switch the rows. 
		     {                                    //But make sure we're not moving -1's up.
//System.out.println("Moving " + j + " in front of " + i + " because of entry " + (k+1));
			 for(l=0;l<listlength;l++)
			     a_placeholder[l] = a[j][l];
			 b_placeholder = b[j];
			 for(l=j-1;l>=i;l--)
			     { for(m=0;m<listlength;m++) a[l+1][m]=a[l][m];  b[l+1]=b[l];}
			 for(l=0;l<listlength;l++)
			     a[i][l]=a_placeholder[l];
			 b[i]=b_placeholder;
			 i=0;
			 j=i+1;
		     }
		     else if(a[i][k]==-1) //If the kth entries are not equal and a[i][k]=-1, 
		     {		          //we want to move a[i][k] down. 
 			 for(l=0;l<listlength;l++)
			     a_placeholder[l] = a[i][l];
			 b_placeholder = b[i];
			 for(l=i+1;l<=j;l++)
			     { for(m=0;m<listlength;m++) a[l-1][m]=a[l][m];  b[l-1]=b[l];}
			 for(l=0;l<listlength;l++)
			     a[j][l]=a_placeholder[l];
			 b[j]=b_placeholder;
			 i=0;
			 j=i+1;
		     }
		     skiprest=true;
		 }
		 else k++;
	     } while(!skiprest && k<listlength);
	     skiprest=false;
	 }

    }


}
