//---------------------------------------------------------------------------

#ifndef orthogonalizeH
#define orthogonalizeH
//---------------------------------------------------------------------------

class Ortho {
    private:
 		
		PLA *pla;
		PLA *ok_terms;

		struct splitvar {
			unsigned int var;
			short pol;		// -1 = negative, 1 = positive, 0 = no difference
		} s_var;

		struct splitterm {
			unsigned int var;
			short pol;		// -1 = negative, 1 = positive, 0 = no difference
			list<Term>::iterator ti;
		} s_term;

		vector< vector<int> > matrix;		// rectangular matrix of intersections

        void Orthogonalize(void);             // Orthogonalize the PLA
		void Orthogonalize2(void);
		void Orthogonalize2a(void);
		void Orthogonalize3(void);
		void Orthogonalize4(void);
		void Orthogonalize5(void);
		void MoveOKTerms(void);				// move non-intersecting terms from pla to ok_terms
		void MoveOKTerms2(void);

		void GenerateMatrix(void);				// Generates matrix from scratch
		void RecomputeMatrixRow( const TermList::iterator ti );		// Recomputes values for term ti
		void RecomputeMatrix(void);			// recomputes the whole matrix, does not change its size
		void AppendMatrixRow( const TermList::iterator ti );		// Increases matrix by 1 and computes values for added term ti
		void RemoveAbsorbed(void);
		bool RemoveAbsorbed( const TermList::iterator ti );		// removes ti from PLA, if it is completely absorbed by another term, or merges outputs, if equal to another term
		bool TryToMerge( const TermList::iterator ti );  // Tries to merge the term
		bool IsAbsorbed( const Term &t ) const;		// returns true, if it is completely absorbed by another term.  Merges outputs, if equal to another term
		bool WillBeAbsorbed( const TermList::iterator ti ) const;

    public:
		Ortho ( PLA *_pla );
		~Ortho(void) {};
		
		PLA *Run( const unsigned int method );
        bool IsOrthogonal( PLA *_pla );
};
#endif
