#include "parser.h"
#include "printer.h"
#include "polynomial.h"
#include "division.h"
#include "buchberger.h"
#include "wallideal.h"
#include "lp.h"
#include "reversesearch.h"
#include "termorder.h"
#include "ep_standard.h"
#include "ep_xfig.h"
#include "gfanapplication.h"
#include "polyhedralcone.h"
#include "polyhedralfan.h"
#include "tropical.h"
#include "tropical2.h"

class TropicalBasisApplication : public GFanApplication
{

  SimpleOption optionHomogenize;
  FieldOption theFieldOption;
public:
  const char *helpText()
  {
    return "This program computes a tropical basis for an ideal defining a tropical curve. Defining a tropical curve means that the Krull dimension of R/I is equal to 1 + the dimension of the homogeneity space of I. The input is a generating set for the ideal. If the input is not homogeneous option -h must be used. If -h is not used the output contains the input as a subset.\n";
  }
  TropicalBasisApplication():
    optionHomogenize("-h","Homogenise the input before computing a tropical basis and dehomogenise the output. This is needed if the ideal is not already homogeneous.")
  {
    registerOptions();
  }
    
  char *name()
  {
    return "_tropicalbasis";
  }
  int main()
  {
    LpSolver::printList(Stderr);
    lpSetSolver("cddgmp");
    

    FileParser P(Stdin);

    StringParser P1("{1+76*a2*b*c+6*a2*c4+72*a*b3*c3,"
		    "46*b3*c+68*b3*a2*c+42*a3*c4+47*b6*a2}");
    StringParser P2("{1-79ab^4-27b^3c^2+32a^4b^2c,"
		    "-36c-35b^3c^3+11a^4b^2c^2+90a^3b^6}");
    
    PolynomialSet theInput=P.parsePolynomialSet();


    if(optionHomogenize.getValue())
      {
	fprintf(Stderr,"Homogenizing...\n");
	IntegerVector grading=IntegerVector::allOnes(theInput.numberOfVariablesInRing());
	
	{
	  WeightReverseLexicographicTermOrder t(grading); 
	  buchberger(&theInput,t);
	}

	PolynomialSet h;
	for(PolynomialSet::const_iterator i=theInput.begin();i!=theInput.end();i++)
	  {
	    h.push_back(i->homogenization(-1,-1,&grading));
	  }
	fprintf(Stderr,"The homogenized ideal:\n");
	AsciiPrinter(Stderr).printPolynomialSet(h);
	
	theInput=h;
      }


    int n=theInput.numberOfVariablesInRing();

    int homog=-1;
    {
      PolynomialSet idealGroebnerBasis=theInput;
      IntegerVector grading=IntegerVector::allOnes(theInput.numberOfVariablesInRing());
      WeightReverseLexicographicTermOrder t(grading); 
      buchberger(&idealGroebnerBasis,t);
      PolyhedralCone hspace=homogeneitySpace(idealGroebnerBasis);
      IntegerVectorList hv=hspace.dualCone().getLinealitySpace();
      homog=hv.size();
    }

    PolynomialSet theOutput=iterativeTropicalBasis(n,theInput,0,homog,true);

    if(optionHomogenize.getValue())
      {
	theOutput=theOutput.deHomogenization();
      }
    AsciiPrinter(Stdout).printPolynomialSet(theOutput);

    return 0;
  }
};

static TropicalBasisApplication theApplication;
