#ifndef POLYHEDRALCONE_H_INCLUDED
#define POLYHEDRALCONE_H_INCLUDED

#include "vektor.h"
#include "printer.h"

/*
A cone is represented by halfSpaces and linearitySpace. The halfSpaces is a list of non-strict inequalities while linearitySpace is a list of equations.

A cone can be in one of the four states:
0) Nothing has been done to remove redundancies. This is the initial state.
1) A basis for the true linearity space has been computed. This means that the implied equations have been computed. In particular the dimension of the cone is known.
2) Redundant inequalities have been computed and have been eliminated. This means that the true set of facets is known - one for each element in halfSpaces.
3) The inequalites and equations from 2) have been transformed into a canonical form. Besides having a unique representation for the cone this also allows comparisons between cones with operator<().

It is not clear have this class is designed optimally. Should the user of this class know about the states?

Always putting the cone in state 1 after something has changed helps a lot. Then all operations can be performed except comparing and getting facets with out taking the cone to a special state.

Old explanation

 The idea is that linearitySpace is always updated by calling computeAndReduceLinearitySpace() when something is changed. If an element in halfSpaces is implied by linearitySpace it might be removed during this process. The set of halfspaces is not minimised until reduce() is called. The reason for this is that most functions do not require the heavy reduction computation. canonicalize() will (when implemented correctly) make sure that the defining set of equalities and inequalities depends deterministically on the actual set of points in the cone. The isCanonicalized variable will be set to true after this process, and polyhedral cones with this flag set can be ordered with operator<().

Under the assumption that computeAndReducedLinearitySpace is implemented correctly (and int is 32 and long long 64) getRelativeInteriorPoint() is cuaranteed to produce correct output if it returns, otherwise it will assert(0). 

The ordering will make highdimensional cones largest.
 */
class PolyhedralCone
{
  int state;
  int n;
  IntegerVectorList halfSpaces;
  IntegerVectorList linearitySpace;  // Is "linearity space" the right word?
  void ensureStateAsMinimum(int s);
 public:
  bool isInStateMinimum(int s)const;
  IntegerVectorList getHalfSpaces()const;
  const IntegerVectorList &getLinealitySpace()const;

  void canonicalize();
  void findFacets();

  PolyhedralCone(int ambientDimension);
  PolyhedralCone(IntegerVectorList const &halfSpaces_, IntegerVectorList const &linearitySpace_, int ambientDimension=-1);
  IntegerVector getRelativeInteriorPoint()const;
  int ambientDimension()const;
  int dimension()const;
  int dimensionOfLinealitySpace()const;
  int dimensionOfLargestContainedSubspace()const;
  bool isZero()const;
  friend PolyhedralCone intersection(const PolyhedralCone &a, const PolyhedralCone &b);
  static PolyhedralCone positiveOrthant(int dimension); 
  void print(class Printer *p)const;
  PolyhedralCone withLastCoordinateRemoved()const;
  friend bool operator<(PolyhedralCone const &a, PolyhedralCone const &b);
  friend bool operator!=(PolyhedralCone const &a, PolyhedralCone const &b);
  bool containsPositiveVector()const;
  bool contains(IntegerVector const &v)const;
  bool contains(PolyhedralCone const &c)const;
  bool containsRelatively(IntegerVector const &v)const;
  bool isSimplicial()const;
  PolyhedralCone permuted(IntegerVector const &v)const;
  PolyhedralCone dualCone()const;//only implemented for subspaces
  IntegerVectorList extremeRays()const; //only implemented for full dimensional cones
  bool checkDual(PolyhedralCone const &c)const;//check some necessary conditions 
};

#endif
