Skip to content
Snippets Groups Projects
IntMatrix.java 27.02 KiB
/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille
 * 
 * ludovic.apvrille AT enst.fr
 * 
 * This software is a computer program whose purpose is to allow the
 * edition of TURTLE analysis, design and deployment diagrams, to
 * allow the generation of RT-LOTOS or Java code from this diagram,
 * and at last to allow the analysis of formal validation traces
 * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP
 * from INRIA Rhone-Alpes.
 * 
 * This software is governed by the CeCILL  license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 * 
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 * 
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 * 
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
 */




package myutil;

import java.util.BitSet;
import java.util.LinkedList;

/**
 * Class IntMatrix
 * Creation: 06/02/2012
 * Version 2.0 06/02/2012
 * @author Ludovic APVRILLE
 */
public class IntMatrix implements Runnable {
   public int [][] matrice;
   public int sizeRow;
   public int sizeColumn;
   private String []nameOfRows;
   
   private long percentageCompletion;
   private boolean mustGo;
   private boolean noMultiplier;
   private boolean interrupted;
   private boolean finished;
   
    private boolean withHeuristics;
   
   public BitSet [] bitSetOfMatrix;
   
   public IntMatrix(int _sizeRow, int _sizeColumn) {
	   matrice = new int[_sizeRow][_sizeColumn];
	   sizeRow= _sizeRow;
	   sizeColumn = _sizeColumn;
	   nameOfRows = new String[sizeRow];
	   for(int i=0; i<sizeRow; i++) {
	   	   nameOfRows[i] = "" + i;
	   }
	  
   }
   
   public long getPercentageCompetion() {
   	   return percentageCompletion;
   }
   
   public void setValue(int i, int j, int value) {
	   matrice[i][j] = value;
   }
   
   public void setLineValues(int line, int[] values) {
   	   for(int j=0; j<sizeColumn; j++) {
   	   	   matrice[line][j] = values[j];
	   }
   }
   
   public int getValue(int i, int j) {
   	   try {
   	   	   return matrice[i][j];
   	   } catch (Exception e) {}
   	   return -1;
   }
   
   public int getNbOfLines() {
   	   return sizeRow;
   }
   
   public String getNameOfLine(int i) {
   	   return nameOfRows[i];
   }
   
   public void putShortNames() {
   	   for(int i=0; i<sizeRow; i++) {
   	   	   nameOfRows[i] = "" + i;
   	   }
   }
   
   public int getValueOfLine(int i) {
   	   int cpt = 0;
   	   for(int j=0;j<sizeColumn; j++) {
   	   	   cpt += matrice[i][j];
   	   }
   	   return cpt;
   }
   
   public int getValueOfLineFromColumn(int columnIndex, int i) {
   	   int cpt = 0;
   	   for(int j=columnIndex;j<sizeColumn; j++) {
   	   	   cpt += matrice[i][j];
   	   }
   	   return cpt;
   }
   
   public void setNameOfLine(int line, String name) {
   	   try {
   	   	   nameOfRows[line] = name;
   	   } catch(Exception e) {
   	   }
   }
   
   public void setNamesOfLine(String []names) {
   	   try {
   	   	   for(int i=0; i<sizeRow; i++){
   	   	   	   nameOfRows[i] = names[i];
   	   	   }
   	   } catch(Exception e) {
   	   }
   }
   
   public String toString() {
   	   StringBuffer sb = new StringBuffer("Size:" + sizeRow + "x" + sizeColumn+ ":\n");
   	   for(int i=0; i<sizeRow; i++) {
   	   	   sb.append("Row #" + i + " / " + nameOfRows[i] + ": ");  
   	   	   for(int j=0; j<sizeColumn; j++) {
   	   	   	   sb.append(" " + matrice[i][j]);
   	   	   }
   	   	   sb.append("\n");
   	   }
   	   return sb.toString();
   }
   
   public void swapLines(int line0, int line1) {
   	   int tmp;
   	   for(int j=0; j<sizeColumn; j++){
   	   	   tmp = matrice[line0][j];
   	   	   matrice[line0][j] = matrice[line1][j];
   	   	   matrice[line1][j] = tmp;
   	   }
   	   
   	   String tmpName = nameOfRows[line0];
   	   nameOfRows[line0] = nameOfRows[line1];
   	   nameOfRows[line1] = tmpName;
   }
   
   
   // Apply a division on all elements of a line
   public void unitLine(int line0, int diviser) {
   	   for(int j=0; j<sizeColumn; j++){
   	   	   matrice[line0][j] = matrice[line0][j] / diviser;
   	   }
   }
   
   // Combine line line0 minus m times line1 ; line0 gets the result 
   public void linearCombination(int line0, int line1, int m) {
   	   //TraceManager.addDev("combination l0 = " + line0 + " line1 = " + line1 + " multiplier m=" + m);
   	   for(int j=0; j<sizeColumn; j++){
   	   	   matrice[line0][j] = matrice[line0][j] - (m * matrice[line1][j]);
   	   }
   }
   
   // Returns the line number at which there is the first non nul element of column col0
   // Returns -1 in case none is found
   public int rgpivot(int col0, int nbOfLines) {
   	   int i = col0;
   	   while((i<(nbOfLines)) && (matrice[i][col0] == 0)) {
   	   		   i++;
   	   }
   	   if (matrice[i][col0] == 0) {
   	   	   return 0;
   	   } else {
   	   	   return i;
   	   }
   }
   
   public IntMatrix clone() {
   	   IntMatrix im = new IntMatrix(sizeRow, sizeColumn);
   	   for(int i=0; i<sizeRow; i++) {
   	   	   for(int j=0; j<sizeColumn; j++) {
   	   	   	   im.matrice[i][j] = matrice[i][j];
   	   	   }
   	   	   setNameOfLine(i, nameOfRows[i]); 
   	   }
   	   
   	   return im;
   }
   
   public void concatAfter(IntMatrix im) {
   	   int tmp = sizeColumn;
   	   sizeColumn += im.sizeColumn;
   	   int [][] newMatrice = new int[sizeRow][sizeColumn];
   	   for(int i=0; i<sizeRow; i++) {
   	   	   for(int j=0; j<sizeColumn; j++) {
   	   	   	   if (j<tmp) {
   	   	   	   	   newMatrice[i][j] = matrice[i][j]; 
   	   	   	   } else {
   	   	   	   	   newMatrice[i][j] = im.matrice[i][j-tmp];
   	   	   	   }
   	   	   }
   	   }
   	   matrice = newMatrice;
   }
   
   public int[] getLine(int lineIndex) {
   	   int[] line =new int[sizeColumn];
   	   for(int j=0; j<sizeColumn;j++){
   	   	   line[j] = matrice[lineIndex][j];
   	   }
   	   return line;
   }
   
   public String lineToString(int []line) {
   	   String s="";
   	   for(int i=0; i<line.length; i++) {
   	   	   s += line[i] + " ";
   	   }
   	   return s;
   }      
   
   public String namesOfRowToString() {
   	   String s="";
   	   for(int i=0; i<nameOfRows.length; i++) {
   	   	   s += nameOfRows[i] + "\n";
   	   }
   	   return s;
   }
   
   
   // Add a line at the end of the matrix
   public void addLine(int[] newLine, String nameOfRow) {
   	   sizeRow ++;
   	   int [][] newMatrice = new int[sizeRow][sizeColumn];
   	   for(int j=0; j<sizeColumn; j++) {
   	   	   for(int i=0; i<sizeRow-1; i++) {
   	   	   	   newMatrice[i][j] = matrice[i][j];
   	   	   }
   	   	   newMatrice[sizeRow-1][j] = newLine[j];
   	   }
   	   matrice = newMatrice;
   	   
   	   String []newNameOfRows = new String[sizeRow];
   	   for(int k=0; k<sizeRow-1; k++) {
   	   	   newNameOfRows[k] = nameOfRows[k];
   	   }
   	   if(nameOfRow == null) {
   	   	   newNameOfRows[sizeRow-1] = "" + (sizeRow-1);
   	   } else {
   	   	   newNameOfRows[sizeRow-1] = nameOfRow;
   	   }
   	   nameOfRows = newNameOfRows;
   }
   
  
   
   
   public void addLines(LinkedList<IntLine> lines) {
   	   int oldSizeRow = sizeRow;
   	   sizeRow += lines.size();
   	   int [][] newMatrice = new int[sizeRow][sizeColumn];
   	   String []newNameOfRows = new String[sizeRow];
   	   for(int i=0; i<oldSizeRow; i++) {
   	   	   for(int j=0; j<sizeColumn; j++) {
   	   	   	   newMatrice[i][j] = matrice[i][j];
   	   	   }
   	   	   newNameOfRows[i] = nameOfRows[i];
   	   }
   	   matrice = newMatrice;
   	   nameOfRows = newNameOfRows;
   	   
   	   int cpt = oldSizeRow;
   	   for(IntLine il: lines) {
   	   	   matrice[cpt] = il.line;
   	   	   nameOfRows[cpt] = il.nameOfLine;
   	   	   cpt ++;
   	   }
   	   
   	   
   }
   
   
   public void addLinesBitSet(LinkedList<IntLine> lines) {
   	   int oldSizeRow = sizeRow;
   	   sizeRow += lines.size();
   	   int [][] newMatrice = new int[sizeRow][sizeColumn];
   	   String []newNameOfRows = new String[sizeRow];
   	   BitSet []newBitSetOfMatrix = new BitSet[sizeRow];
   	   for(int i=0; i<oldSizeRow; i++) {
   	   	   for(int j=0; j<sizeColumn; j++) {
   	   	   	   newMatrice[i][j] = matrice[i][j];
   	   	   }
   	   	   newNameOfRows[i] = nameOfRows[i];
   	   	   newBitSetOfMatrix[i] = bitSetOfMatrix[i];
   	   }
   	   matrice = newMatrice;
   	   nameOfRows = newNameOfRows;
   	   bitSetOfMatrix = newBitSetOfMatrix;
   	   
   	   int cpt = oldSizeRow;
   	   for(IntLine il: lines) {
   	   	   matrice[cpt] = il.line;
   	   	   nameOfRows[cpt] = il.nameOfLine;
   	   	   bitSetOfMatrix[cpt] = il.bs;
   	   	   cpt ++;
   	   }
   	   
   	   
   }
   
   
   public void removeLine(int lineIndex) {
   	   sizeRow --;
   	    int [][] newMatrice = new int[sizeRow][sizeColumn];
   	    for(int i=0; i<sizeRow+1; i++) {
   	   	   for(int j=0; j<sizeColumn; j++) {
   	   	   	   if (i < lineIndex) {
   	   	   	   	   newMatrice[i][j] = matrice[i][j];
   	   	   	   } else {
   	   	   	   	   if (i>lineIndex){
   	   	   	   	   	   newMatrice[i-1][j] = matrice[i][j];
   	   	   	   	   }
   	   	   	   }
   	   	   }
   	   }
   	   matrice = newMatrice;
   	   
   	   String []newNameOfRows = new String[sizeRow];
   	   int dec=0;
   	   for(int k=0; k<sizeRow+1; k++) {
   	   	   if (k != lineIndex) {
   	   	   	   newNameOfRows[k-dec] = nameOfRows[k];
   	   	   } else {
   	   	   	   dec ++;
   	   	   }
   	   }
   	    nameOfRows = newNameOfRows;
   }
   
   public void makeID() {
   	   for(int i=0; i<sizeRow; i++) {
   	   	   for(int j=0; j<sizeColumn; j++) {
   	   	   	   if (i==j) {
   	   	   	   	   matrice[i][j] = 1;
   	   	   	   } else {
   	   	   	   	   matrice[i][j] = 0;
   	   	   	   }
   	   	   }
   	   }
   }
   
   
   // noMultiplier indicates whether names of lines may contain the "*" sign, or not.
   public void Farkas(boolean noMultiplier) {
   	   int sizeColumBeforeConcat = sizeColumn;
   	   IntMatrix idMat = new IntMatrix(sizeRow, sizeRow);
   	   idMat.makeID();
   	   concatAfter(idMat);
   	   //System.out.println("matconcat=\n" + toString() + "\n\n");
   	   //int[] lined1, lined2, lined;
   	   int[] lined;
   	   int gcd;
   	   int l, i;
   	   String s0, s1;
   	   String nameOfNewLine;
   	   int cpt;
   	   int total = 0;
   	   int tmpSizeRow;
   	   LinkedList<IntLine> ll = new LinkedList<IntLine>();
   	   
   	   for(int j=0; j<sizeColumBeforeConcat; j++) {
   	   	   // Loop on lines to add line combinations
   	   	   tmpSizeRow = sizeRow;
   	   	   for(i=0; i<tmpSizeRow-1; i++) {
   	   	   	   
   	   	   	   //lined1 = getLine(i);
   	   	   	   //tmpSizeRow = sizeRow;
   	   	   	   for(int k=i+1; k<tmpSizeRow; k++) {
   	   	   	   	   percentageCompletion = total++;
   	   	   	   	   if (mustGo == false) {
   	   	   	   	   	   interrupted = true;
   	   	   	   	   	   return;
   	   	   	   	   }
   	   	   	   	   //TraceManager.addDev("Computing k=" + k + " " + sizeRow + "x" + sizeColumn);
   	   	   	   	   //lined2 = getLine(k);
   	   	   	   	   
   	   	   	   	   // lines d1 and 2 have opposite signs?
   	   	   	   	   //if (((lined1[j] < 0) && (lined2[j]>0)) || ((lined1[j]>0) && (lined2[j]<0))) {
   	   	   	   	   if (((matrice[i][j] < 0) && (matrice[k][j]>0)) || ((matrice[i][j]>0) && (matrice[k][j]<0))) {
   	   	   	   	   	   lined = new int[sizeColumn];
   	   	   	   	   	   for(l=0; l<lined.length; l++) {
   	   	   	   	   	   	  lined[l] = Math.abs(matrice[k][j])*matrice[i][l] + Math.abs(matrice[i][j])*matrice[k][l];
   	   	   	   	   	   }
   	   	   	   	   	   if (Math.abs(matrice[k][j]) == 1) {
   	   	   	   	   	   	   s0 =  nameOfRows[i] + " + ";
   	   	   	   	   	   } else {
   	   	   	   	   	   	   if (noMultiplier) {
   	   	   	   	   	   	   	   s0 = nameOfRows[i] + " + ";
   	   	   	   	   	   	   	   for(cpt=Math.abs(matrice[k][j]); cpt>1; cpt--) {
   	   	   	   	   	   	   	   	   s0 += nameOfRows[i] + " + " ;
   	   	   	   	   	   	   	   }
   	   	   	   	   	   	   } else {
   	   	   	   	   	   	   	   s0 = "" + Math.abs(matrice[k][j]) + "*("  + nameOfRows[i] + ") + ";
   	   	   	   	   	   	   }
   	   	   	   	   	   }
   	   	   	   	   	   
   	   	   	   	   	   if (Math.abs(matrice[i][j]) == 1) {
   	   	   	   	   	   	    s1 =  nameOfRows[k];
   	   	   	   	   	   } else {
   	   	   	   	   	   	   if (noMultiplier) {
   	   	   	   	   	   	   	    s1 =  nameOfRows[k];
   	   	   	   	   	   	   	   for(cpt=Math.abs(matrice[i][j]); cpt>1; cpt--) {
   	   	   	   	   	   	   	   	   s1 += " +" + nameOfRows[k];
   	   	   	   	   	   	   	   }
   	   	   	   	   	   	   } else {
   	   	   	   	   	   	   	   s1 = "" + Math.abs(matrice[i][j]) + "*("  + nameOfRows[k] + ") + ";
   	   	   	   	   	   	   }
   	   	   	   	   	   } 
   	   	   	   	   	   
   	   	   	   	   	   //TraceManager.addDev("Name of line=" + s0 + "/" + s1);
   	   	   	   	   	   nameOfNewLine = s0 + s1;
   	   	   	   	   	   gcd = MyMath.gcd(lined);
   	   	   	   	   	   //System.out.println("gcd =" + gcd + " of line =" + lineToString(lined) + " i.e.:" + nameOfNewLine);
   	   	   	   	   	   
   	   	   	   	   	   if (gcd != 0) {
						   for(l=0; l<lined.length; l++) {
							  lined[l] = lined[l] / gcd;
						   }
   	   	   	   	   	   }
   	   	   	   	   	   
   	   	   	   	   	   ll.add(new IntLine(lined, nameOfNewLine));
   	   	   	   	   	   //addLine(lined, nameOfNewLine);
   	   	   	   	   	   //System.out.println("matafterline=\n" + toString() + "\n\n");
   	   	   	   	   }
   	   	   	   }
   	   	   }
   	   	   
   	   	   TraceManager.addDev("Adding lines, size=" + sizeRow + "x" + sizeColumn);
   	   	   addLines(ll);
   	   	   ll.clear();
   	   	   
   	   	    TraceManager.addDev("Removing lines, size=" + sizeRow + "x" + sizeColumn);
   	   	   // Remove lines whose element #j is not 0
   	   	   for(i=0;i<sizeRow; i++) {
   	   	   	   if (matrice[i][j] != 0) {
   	   	   	   	   removeLine(i);
   	   	   	   	   //System.out.println("matafterremove " + i + "=\n" + toString() + "\n\n");
   	   	   	   	   i--;
   	   	   	   }
   	   	   }
   	   	   TraceManager.addDev("Lines removed, size=" + sizeRow + "x" + sizeColumn);
   	   	   
   	   	    //System.out.println("----------------\nD"+ (j+1) +"=\n" + toString() + "\n\n");
   	   	   
   	   }
   	   
   	   // Remove m first columns
   	   
   	   
   	   
   }
   
   // noMultiplier indicates whether names of lines may contain the "*" sign, or not.
   public void FarkasForInvariants(boolean noMultiplier) {
   	   int sizeColumBeforeConcat = sizeColumn;
   	   IntMatrix idMat = new IntMatrix(sizeRow, sizeRow);
   	   idMat.makeID();
   	   concatAfter(idMat);
   	   //System.out.println("matconcat=\n" + toString() + "\n\n");
   	   //int[] lined1, lined2, lined;
   	   int[] lined;
   	   int gcd;
   	   int l, i;
   	   String s0, s1;
   	   String nameOfNewLine;
   	   int cpt;
   	   long total = 0;
   	   int tmpSizeRow;
   	   LinkedList<IntLine> ll = new LinkedList<IntLine>();
   	   
   	  
   	   
   	   
   	   for(int j=0; j<sizeColumBeforeConcat; j++) {
   	   	   // Loop on lines to add line combinations
   	   	   tmpSizeRow = sizeRow;
   	   	   
   	   	   for(i=0; i<tmpSizeRow-1; i++) {
   	   	   	   percentageCompletion = (long)(j*10000.0/sizeColumBeforeConcat)+(long)(10000.0*i/tmpSizeRow/sizeColumBeforeConcat);
   	   	   	   //lined1 = getLine(i);
   	   	   	   //tmpSizeRow = sizeRow;
   	   	   	   for(int k=i+1; k<tmpSizeRow; k++) {
   	   	   	   	   
   	   	   	   	   if (mustGo == false) {
   	   	   	   	   	   interrupted = true;
   	   	   	   	   	   return;
   	   	   	   	   }
   	   	   	   	   //TraceManager.addDev("Computing k=" + k + " " + sizeRow + "x" + sizeColumn);
   	   	   	   	   //lined2 = getLine(k);
   	   	   	   	   
   	   	   	   	   // lines d1 and 2 have opposite signs?
   	   	   	   	   //if (((lined1[j] < 0) && (lined2[j]>0)) || ((lined1[j]>0) && (lined2[j]<0))) {
   	   	   	   	   if (((matrice[i][j] < 0) && (matrice[k][j]>0)) || ((matrice[i][j]>0) && (matrice[k][j]<0))) {
   	   	   	   	   	   lined = new int[sizeColumn];
   	   	   	   	   	   for(l=0; l<lined.length; l++) {
   	   	   	   	   	   	  lined[l] = Math.abs(matrice[k][j])*matrice[i][l] + Math.abs(matrice[i][j])*matrice[k][l];
   	   	   	   	   	   }
   	   	   	   	   	   if (Math.abs(matrice[k][j]) == 1) {
   	   	   	   	   	   	   s0 =  nameOfRows[i] + "+";
   	   	   	   	   	   } else {
   	   	   	   	   	   	   if (noMultiplier) {
   	   	   	   	   	   	   	   s0 = nameOfRows[i] + "+";
   	   	   	   	   	   	   	   for(cpt=Math.abs(matrice[k][j]); cpt>1; cpt--) {
   	   	   	   	   	   	   	   	   s0 += nameOfRows[i] + "+" ;
   	   	   	   	   	   	   	   }
   	   	   	   	   	   	   } else {
   	   	   	   	   	   	   	   s0 = "" + Math.abs(matrice[k][j]) + "*("  + nameOfRows[i] + ") + ";
   	   	   	   	   	   	   }
   	   	   	   	   	   }
   	   	   	   	   	   
   	   	   	   	   	   if (Math.abs(matrice[i][j]) == 1) {
   	   	   	   	   	   	    s1 =  nameOfRows[k];
   	   	   	   	   	   } else {
   	   	   	   	   	   	   if (noMultiplier) {
   	   	   	   	   	   	   	    s1 =  nameOfRows[k];
   	   	   	   	   	   	   	   for(cpt=Math.abs(matrice[i][j]); cpt>1; cpt--) {
   	   	   	   	   	   	   	   	   s1 += "+" + nameOfRows[k];
   	   	   	   	   	   	   	   }
   	   	   	   	   	   	   } else {
   	   	   	   	   	   	   	   s1 = "" + Math.abs(matrice[i][j]) + "*("  + nameOfRows[k] + ") + ";
   	   	   	   	   	   	   }
   	   	   	   	   	   } 
   	   	   	   	   	   
   	   	   	   	   	   //TraceManager.addDev("Name of line=" + s0 + "/" + s1);
   	   	   	   	   	   nameOfNewLine = s0 + s1;
   	   	   	   	   	   gcd = MyMath.gcd(lined);
   	   	   	   	   	   //System.out.println("gcd =" + gcd + " of line =" + lineToString(lined) + " i.e.:" + nameOfNewLine);
   	   	   	   	   	   
   	   	   	   	   	   if (gcd != 0) {
   	   	   	   	   	   for(l=0; l<lined.length; l++) {
   	   	   	   	   	   	  lined[l] = lined[l] / gcd;
   	   	   	   	   	   }
   	   	   	   	   	   }
   	   	   	   	   	   
   	   	   	   	   	   ll.add(new IntLine(lined, nameOfNewLine));
   	   	   	   	   	   //addLine(lined, nameOfNewLine);
   	   	   	   	   	   //System.out.println("matafterline=\n" + toString() + "\n\n");
   	   	   	   	   }
   	   	   	   }
   	   	   }
   	   	   
   	   	   TraceManager.addDev("Adding lines, size=" + sizeRow + "x" + sizeColumn);
   	   	   addLines(ll);
   	   	   ll.clear();
   	   	   
   	   	    TraceManager.addDev("Removing lines, size=" + sizeRow + "x" + sizeColumn);
   	   	   // Remove lines whose element #j is not 0
   	   	   int nbToRemoved = 0;
   	   	   for(i=0;i<sizeRow; i++) {
   	   	   	   if (matrice[i][j] != 0) {
   	   	   	   	   nbToRemoved ++;
   	   	   	   	   //removeLine(i);
   	   	   	   	   //System.out.println("matafterremove " + i + "=\n" + toString() + "\n\n");
   	   	   	   	   //i--;
   	   	   	   }
   	   	   }
   	   	   
   	   	   TraceManager.addDev("# of lines to be removed: " + nbToRemoved);
   	   	   if (nbToRemoved > 0) {
   	   	   	   int index = 0;
   	   	   	   int[][] newMat = new int[sizeRow-nbToRemoved][sizeColumn];
   	   	   	   String []newNames = new String[sizeRow-nbToRemoved];
   	   	   	   for(int ii=0; ii<sizeRow; ii++) {
   	   	   	   	   if (matrice[ii][j] == 0) {
   	   	   	   	   	   //TraceManager.addDev("Copying lines to be removed: " + nbToRemoved);
   	   	   	   	   	   // line copy to index
   	   	   	   	   	   for(int jj=0; jj<sizeColumn; jj++) {
   	   	   	   	   	   	   newMat[index][jj] = matrice[ii][jj];
   	   	   	   	   	   }
   	   	   	   	   	   newNames[index] = nameOfRows[ii];
   	   	   	   	   	   index ++;
   	   	   	   	   }
   	   	   	   }
   	   	   	   matrice = newMat;
   	   	   	   sizeRow -= nbToRemoved;
   	   	   	   nameOfRows = newNames;
   	   	   }
   	   	   
   	   	   
   	   	   
   	   	   TraceManager.addDev("Lines removed, size=" + sizeRow + "x" + sizeColumn);
   	   	   
   	   	    //System.out.println("----------------\nD"+ (j+1) +"=\n" + toString() + "\n\n");
   	   	   
   	   }
   	   
   	   // Remove m first columns
   	   
   	   
   	   
   }
   
   
   // noMultiplier indicates whether names of lines may contain the "*" sign, or not.
   public void FarkasForInvariantsBitSet(boolean withHeuristics) {
   	   int sizeColumBeforeConcat = sizeColumn;
   	   IntMatrix idMat = new IntMatrix(sizeRow, sizeRow);
   	   idMat.makeID();
   	   concatAfter(idMat);
   	   //System.out.println("matconcat=\n" + toString() + "\n\n");
   	   //int[] lined1, lined2, lined;
   	   int[] lined;
   	   int gcd;
   	   int l, i;
   	   String s0, s1;
   	   String nameOfNewLine;
   	   int cpt;
   	   long total = 0;
   	   int tmpSizeRow;
   	   LinkedList<IntLine> ll = new LinkedList<IntLine>();
   	   bitSetOfMatrix = new BitSet[sizeRow];
   	   BitSet bs, bs1, bs2;
   	   
   	   for(int bi=0; bi<sizeRow; bi++) {
   	   	   bitSetOfMatrix[bi] = new BitSet(sizeRow);
   	   	   bitSetOfMatrix[bi].set(bi);
   	   }
   	   
   	  
   	   
   	   for(int j=0; j<sizeColumBeforeConcat; j++) {
   	   	   // Loop on lines to add line combinations
   	   	   tmpSizeRow = sizeRow;
   	   	   
   	   	   for(i=0; i<tmpSizeRow-1; i++) {
   	   	   	   percentageCompletion = (long)(j*10000.0/sizeColumBeforeConcat)+(long)(10000.0*i/tmpSizeRow/sizeColumBeforeConcat);
   	   	   	   //lined1 = getLine(i);
   	   	   	   //tmpSizeRow = sizeRow;
   	   	   	   for(int k=i+1; k<tmpSizeRow; k++) {
   	   	   	   	   
   	   	   	   	   if (mustGo == false) {
   	   	   	   	   	   interrupted = true;
   	   	   	   	   	   return;
   	   	   	   	   }
   	   	   	   	   //TraceManager.addDev("Computing k=" + k + " " + sizeRow + "x" + sizeColumn);
   	   	   	   	   //lined2 = getLine(k);
   	   	   	   	   
   	   	   	   	   // lines d1 and 2 have opposite signs?
   	   	   	   	   //if (((lined1[j] < 0) && (lined2[j]>0)) || ((lined1[j]>0) && (lined2[j]<0))) {
   	   	   	   	   if (((matrice[i][j] < 0) && (matrice[k][j]>0)) || ((matrice[i][j]>0) && (matrice[k][j]<0))) {
   	   	   	   	   	   
   	   	   	   	   	   // Take the bit set of the two lines
   	   	   	   	   	   // Lines not yet taken into account?
   	   	   	   	   	   if (!withHeuristics || (!(bitSetOfMatrix[i].intersects(bitSetOfMatrix[k])))) {
   	   	   	   	   	   
						   lined = new int[sizeColumn];
						   for(l=0; l<lined.length; l++) {
							  lined[l] = Math.abs(matrice[k][j])*matrice[i][l] + Math.abs(matrice[i][j])*matrice[k][l];
						   }
						   
						   gcd = MyMath.gcd(lined);
						   //System.out.println("gcd =" + gcd + " of line =" + lineToString(lined) + " i.e.:" + nameOfNewLine);
						   
						   if (gcd != 0) {
							   for(l=0; l<lined.length; l++) {
								  lined[l] = lined[l] / gcd;
							   }
						   }
						   bs = ((BitSet)(bitSetOfMatrix[i].clone()));
						   bs.or(bitSetOfMatrix[k]);
						  
						   ll.add(new IntLine(lined, bs));
						  
   	   	   	   	   	   }
   	   	   	   	   	   //addLine(lined, nameOfNewLine);
   	   	   	   	   	   //System.out.println("matafterline=\n" + toString() + "\n\n");
   	   	   	   	   }
   	   	   	   }
   	   	   }
   	   	   
   	   	   TraceManager.addDev("Adding lines, size=" + sizeRow + "x" + sizeColumn);
   	   	   addLinesBitSet(ll);
   	   	   ll.clear();
   	   	   
   	   	    TraceManager.addDev("Removing lines, size=" + sizeRow + "x" + sizeColumn);
   	   	   // Remove lines whose element #j is not 0
   	   	   int nbToRemoved = 0;
   	   	   for(i=0;i<sizeRow; i++) {
   	   	   	   if (matrice[i][j] != 0) {
   	   	   	   	   nbToRemoved ++;
   	   	   	   	   //removeLine(i);
   	   	   	   	   //System.out.println("matafterremove " + i + "=\n" + toString() + "\n\n");
   	   	   	   	   //i--;
   	   	   	   }
   	   	   }
   	   	   
   	   	   TraceManager.addDev("# of lines to be removed: " + nbToRemoved);
   	   	   if (nbToRemoved > 0) {
   	   	   	   int index = 0;
   	   	   	   int[][] newMat = new int[sizeRow-nbToRemoved][sizeColumn];
   	   	   	   String []newNames = new String[sizeRow-nbToRemoved];
   	   	   	   BitSet []newBitSet = new BitSet[sizeRow-nbToRemoved];
   	   	   	   for(int ii=0; ii<sizeRow; ii++) {
   	   	   	   	   if (matrice[ii][j] == 0) {
   	   	   	   	   	   //TraceManager.addDev("Copying lines to be removed: " + nbToRemoved);
   	   	   	   	   	   // line copy to index
   	   	   	   	   	   for(int jj=0; jj<sizeColumn; jj++) {
   	   	   	   	   	   	   newMat[index][jj] = matrice[ii][jj];
   	   	   	   	   	   }
   	   	   	   	   	   newNames[index] = nameOfRows[ii];
   	   	   	   	   	   newBitSet[index] = bitSetOfMatrix[ii];
   	   	   	   	   	   index ++;
   	   	   	   	   }
   	   	   	   }
   	   	   	   matrice = newMat;
   	   	   	   sizeRow -= nbToRemoved;
   	   	   	   nameOfRows = newNames;
   	   	   	   bitSetOfMatrix = newBitSet;
   	   	   }
   	   	   
   	   	   
   	   	   
   	   	   TraceManager.addDev("Lines removed, size=" + sizeRow + "x" + sizeColumn);
   	   	   
   	   	    //System.out.println("----------------\nD"+ (j+1) +"=\n" + toString() + "\n\n");
   	   	   
   	   }
   	   
   	   // Remove m first columns
   	   
   	   
   	   
   }
   
   public synchronized void startFarkas(boolean _noMultiplier, boolean _withHeuristics) {
   	   noMultiplier = _noMultiplier;
   	   withHeuristics = _withHeuristics;
   	   Thread t = new Thread(this);
   	   mustGo = true;
   	   finished = false;
   	   interrupted = false;
   	   t.start();
   }
   
   public synchronized void stopComputation() {
   	   mustGo = false;
   	   notifyAll();
   }
   
   public boolean wasInterrupted() {
   	   return interrupted;
   }
   
   public synchronized void callFinished() {
   	   mustGo = false;
   	   notifyAll();
   }
   
   public synchronized boolean isFinished() {
   	   return finished;
   }
   
   public void run() {
   	   try {
   	   	   FarkasForInvariantsBitSet(withHeuristics);
   	   } catch (Error e) {
   	   	   TraceManager.addDev("Exception when executing Farkas algorithm: " + e.getMessage());
   	   	   interrupted = true;
   	   }
   	   if (!interrupted) {
   	   	   stopComputation();
   	   }
   	   finished = true;
   	   TraceManager.addDev("Farkas thread completed");
   }
   
   
  
}