/* $Id: CouenneExprDiv.hpp 615 2011-06-08 20:36:24Z pbelotti $
 *
 * Name:    exprDiv.hpp
 * Author:  Pietro Belotti
 * Purpose: definition of divisions
 *
 * (C) Carnegie-Mellon University, 2006-10.
 * This file is licensed under the Eclipse Public License (EPL)
 */

#ifndef COUENNE_EXPRDIV_HPP
#define COUENNE_EXPRDIV_HPP

#include "CouenneExprOp.hpp"
#include "CouennePrecisions.hpp"

namespace Couenne {

#define BR_NEXT_ZERO 1e-3
#define BR_MULT      1e-3

/// class for divisions, \f$ \frac{f(x)}{g(x)} \f$

class exprDiv: public exprOp {

 public:

  /// Constructor
  exprDiv (expression **al, int n = 2): 
    exprOp (al, n) {} //< non-leaf expression, with argument list

  /// Constructor with two arguments given explicitly
  exprDiv (expression *arg0, expression *arg1):
    exprOp (arg0, arg1) {}

  /// Cloning method
  expression *clone (Domain *d = NULL) const
    {return new exprDiv (clonearglist (d), nargs_);}

  /// Print operator
  std::string printOp () const
    {return "/";}

  /// Function for the evaluation of the expression
  inline CouNumber operator () ();

  /// return l-2 norm of gradient at given point
  CouNumber gradientNorm (const double *x);

  /// Differentiation
  expression *differentiate (int index); 

  /// Simplification
  expression *simplify ();

  /// Get a measure of "how linear" the expression is (see CouenneTypes.h)
  inline int Linearity () {

    if (arglist_ [1] -> Type () == CONST)
      return arglist_ [0] -> Linearity ();
    else return NONLINEAR;
  }

  /// Get lower and upper bound of an expression (if any)
  void getBounds (expression *&lb, expression *&ub);

  /// Get value of lower and upper bound of an expression (if any)
  void getBounds (CouNumber &lb, CouNumber &ub);

  /// Reduce expression in standard form, creating additional aux
  /// variables (and constraints)
  exprAux *standardize (CouenneProblem *p, bool addAux = true);

  /// Generate equality between *this and *w
  void generateCuts (expression *w, //const OsiSolverInterface &si, 
		     OsiCuts &cs, const CouenneCutGenerator *cg, 
		     t_chg_bounds * = NULL, int = -1, 
		     CouNumber = -COUENNE_INFINITY, 
		     CouNumber =  COUENNE_INFINITY);

  /// Code for comparisons
  virtual enum expr_type code () {return COU_EXPRDIV;}

  /// is this expression integer?
  bool isInteger ();

  /// Implied bound processing
  bool impliedBound (int, CouNumber *, CouNumber *, t_chg_bounds *, enum auxSign = expression::AUX_EQ);

  /// Set up branching object by evaluating many branching points for
  /// each expression's arguments
  virtual CouNumber selectBranch (const CouenneObject *obj, 
				  const OsiBranchingInformation *info,
				  expression * &var, 
				  double * &brpts, 
 				  double * &brDist, // distance of current LP
					  	    // point to new convexifications
				  int &way);

  /// compute $y^{lv}$ and  $y^{uv}$ for Violation Transfer algorithm
  virtual void closestFeasible (expression *varind,
				expression *vardep, 
				CouNumber &left,
				CouNumber &right) const;

  /// can this expression be further linearized or are we on its
  /// concave ("bad") side
  virtual bool isCuttable (CouenneProblem *problem, int index) const
  {return false;} // concave on both sides, as for products
};


/// Compute division

inline CouNumber exprDiv::operator () ()
  {return ((*(*arglist_)) () / (*(arglist_ [1])) ());}


#define SAFE_COEFFICIENT 1e9

/// check if bounding box is suitable for a multiplication/division
/// convexification constraint

inline bool is_boundbox_regular (register CouNumber b1, register CouNumber b2) {

  // Why SAFE_COEFFICIENT and not COUENNE_INFINITY? Because
  // OsiRowCut::set[LU]b do not work for values more than
  // SAFE_COEFFICIENT and apparently makes the convexification
  // infeasible.
  return 
    (fabs (b1)    < SAFE_COEFFICIENT) && 
    (fabs (b2)    < SAFE_COEFFICIENT) && 
    (fabs (b1*b2) < SAFE_COEFFICIENT);
    //    && ((fabs (b1) > COUENNE_EPS) || (fabs (b2) > COUENNE_EPS));
}

}

#endif
