// Context for SSXLS
//   -- semismooth (SS) - function not differentiable
//                      - merit function continuously differentiable
//                      - Fischer-Burmeister reformulation of complementarity
//                        - Billups composition for two finite bounds
//   -- infeasible (I)  - iterates not guaranteed to remain within bounds
//   -- feasible (F)    - iterates guaranteed to remain within bounds
//   -- linesearch (LS) - Armijo rule on direction
//
// Many other reformulations are possible and combinations of 
// feasible/infeasible and linesearch/trust region are possible.
//
// Basic theory 
//   Fischer-Burmeister reformulation is semismooth with a continuously
//   differentiable merit function and strongly semismooth if the F has
//   lipschitz continuous derivatives.
//
//   Every accumulation point generated by the algorithm is a stationary
//   point for the merit function.  Stationary points of the merit function
//   are solutions of the complementarity problem if
//     a.  the stationary point has a BD-regular subdifferential, or
//     b.  the Schur complement F'/F'_ff is a P_0-matrix where ff is the
//         index set corresponding to the free variables.
//
//   If one of the accumulation points has a BD-regular subdifferential then
//     a.  the entire sequence converges to this accumulation point at
//         a local q-superlinear rate
//     b.  if in addition the reformulation is strongly semismooth near
//         this accumulation point, then the algorithm converges at a
//         local q-quadratic rate.
//
// The theory for the feasible version follows from the feasible descent
// algorithm framework.
//
// References:
//   Billups, "Algorithms for Complementarity Problems and Generalized
//     Equations," Ph.D thesis, University of Wisconsin - Madison, 1995.
//   De Luca, Facchinei, Kanzow, "A Semismooth Equation Approach to the
//     Solution of Nonlinear Complementarity Problems," Mathematical
//     Programming, 75, pages 407-439, 1996.
//   Ferris, Kanzow, Munson, "Feasible Descent Algorithms for Mixed
//     Complementarity Problems," Mathematical Programming, 86,
//     pages 475-497, 1999.
//   Fischer, "A Special Newton-type Optimization Method," Optimization,
//     24, pages 269-284, 1992
//   Munson, Facchinei, Ferris, Fischer, Kanzow, "The Semismooth Algorithm
//     for Large Scale Complementarity Problems," Technical Report 99-06,
//     University of Wisconsin - Madison, 1999.

#ifndef __TAO_SSLS_H
#define __TAO_SSLS_H
#include "src/tao_impl.h"

typedef struct {
  TaoVec *g;

  TaoVec *ff;	// fischer function
  TaoVec *dpsi;	// gradient of psi
  
  TaoVec *d;	// direction
  TaoVec *w;	// linesearch work vector

  TaoVec *da;	// work vector for subdifferential calculation (diag pert)
  TaoVec *db;	// work vector for subdifferential calculation (row scale)
  TaoVec *dm;   // work vector for subdifferential calculation (mu vector)

  TaoVec *t1;	// work vector
  TaoVec *t2;	// work vector

  TaoVec *xl;
  TaoVec *xu;

  double merit; // merit function value (norm(fischer))
  double merit_eqn;
  double merit_mu;

  double delta;
  double rho;

  double rtol;	// Solution tolerances
  double atol;

  double identifier;	// Active-set identification

  // Interior-point method data
  double mu_init; // initial smoothing parameter value
  double mu;      // smoothing parameter
  double dmu;	  // direction in smoothing parameter
  double mucon;   // smoothing parameter constraint
  double d_mucon; // derivative of smoothing constraint with respect to mu
  double g_mucon; // gradient of merit function with respect to mu

  TaoVec *f;	// constraint function
} TAO_SSLS;

int TaoSetUp_SSLS(TAO_SOLVER, void *);
int TaoSetDown_SSLS(TAO_SOLVER, void *);
int TaoSetOptions_SSLS(TAO_SOLVER, void *);
int TaoView_SSLS(TAO_SOLVER, void *);

int Tao_SSLS_Function(TAO_SOLVER, TaoVec *, double *, void *);
int Tao_SSLS_FunctionGradient(TAO_SOLVER, TaoVec *, double *, TaoVec *, void *);
int Tao_ASLS_FunctionGradient(TAO_SOLVER, TaoVec *, double *, TaoVec *, void *);
int Tao_ISLS_FunctionGradient(TAO_SOLVER, TaoVec *, double *, TaoVec *, void *);

#endif

