\documentclass{article}
\usepackage[english]{babel}
\usepackage{amsmath,amssymb,hyperref,lineno,xcolor,alltt,theorem}
\usepackage{pdfpages}
\usepackage{geometry}
\usepackage{listings}

\lstset{
   basicstyle=\ttfamily\footnotesize,
   frame=single,
   breaklines=true,
   columns=flexible,
   keepspaces=true,
   showstringspaces=false
}

%%%%%%%%%% Start TeXmacs macros
\newcommand{\assign}{:=}
\newcommand{\cdummy}{\cdot}
\newcommand{\tmcolor}[2]{{\color{#1}{#2}}}
\newcommand{\tmem}[1]{{\em #1\/}}
\newcommand{\tmop}[1]{\ensuremath{\operatorname{#1}}}
\newcommand{\tmsamp}[1]{\textsf{#1}}
\newcommand{\tmtextbf}[1]{\text{{\bfseries{#1}}}}
\newcommand{\tmtextit}[1]{\text{{\itshape{#1}}}}
\newcommand{\tmtexttt}[1]{\text{{\ttfamily{#1}}}}
\newenvironment{tmcode}[1][]{\begin{alltt} }{\end{alltt}}
\newenvironment{tmlisting}{\begin{linenumbers} \resetlinenumber}{\end{linenumbers}}
{\theorembodyfont{\rmfamily}\newtheorem{example}{Example}}
%%%%%%%%%% End TeXmacs macros

\begin{document}

\includepdf[pages={1}]{hdsdp_header.pdf}

{\tableofcontents}

\section{Introduction}

HDSDP is a numerical software for general-purpose semidefinite programming
problems (SDP).
\begin{eqnarray*}
  \min_X & \langle C, X \rangle & \\
  \text{subject to} & \mathcal{A}X = b & \\
  & X \succeq 0 & 
\end{eqnarray*}
The solver implements the dual interior point method
{\cite{benson2008algorithm}} and incorporates several important extensions
that enhance the performance of the dual method. HDSDP has been tested over
massive datasets and proves a robust and efficient SDP solver
{\cite{gao2022hdsdp}}.

\subsection{Release note}

\begin{itemize}
  \item Sep 2022
  
  Initial release of {\tmsamp{HDSDP}} 1.0
  
  \item June 2023
  
  The whole repo rewritten based on new design structure
  
  \item March 2024
  
  Added a dedicated LP solver
  
  \item July 2024
  
  Added a primal SDP solver and hybrid primal-primal-dual LP solver
  
  \item Oct 2024
  
  Added new linear system support
\end{itemize}
\section{Installation and requirement}

HDSDP is written in ANSI C and is freely available. Since version 2.0, HDSDP
is maintained as personal repository

{\center{{\tmsamp{{\center{}}\href{}{https://github.com/Gwzwpxz/hdsdp}}}}}

and all the source files for HDSDP are directly available.

\subsection{Package dependence}

HDSDP is a standalone subroutine library, and the only external dependence is
{\tmsamp{LAPACK}} and {\tmsamp{BLAS}}, which are easily accessible for most
platforms. Alternatively, HDSDP can be linked with {\tmsamp{Intel MKL}} and
leverage its multi-thread computing features.

\paragraph{Linking with LAPACK and BLAS.}Different distributions of
{\tmsamp{BLAS}} and {\tmsamp{LAPACK}} sometimes have different ways of naming.
For example, \tmtexttt{ddot} can appear as \tmtexttt{ddot}, \tmtexttt{ddot\_},
\tmtexttt{DDOT}, or \tmtexttt{DDOT\_}. Users can enable the following macros
in \tmtexttt{external/lapack\_names} to ensure that the symbols are correctly
detected:
\begin{itemize}
  \item \tmtexttt{\#define UNDERBLAS}
  
  For \tmtexttt{ddot\_}
  
  \item \tmtexttt{\#define CAPBLAS}
  
  For \tmtexttt{DDOT}
  
  \item \tmtexttt{\#define UNDERCAPBLAS}
  
  For \tmtexttt{DDOT\_}
\end{itemize}

\subsection{Building the HDSDP library and SDPA/MPS solver}

HDSDP can be used in two ways: as a subroutine library or as an SDPA solver.
The subroutine library allows users to call HDSDP within their customized
applications, while the SDPA solver mainly serves for benchmarking purpose.
Both the library and the SDPA solver can be built using the {\tmsamp{CMAKE}}
build system.

The {\tmsamp{CMakeLists.txt}} file located in the repository should be
modified based on the user's local environment.
\begin{itemize}
  \item Line 2. Target architecture
  
  If a MacOS user is using HDSDP linked with MKL, uncomment the following line
  \begin{tmcode}
  \# set(CMAKE_OSX_ARCHITECTURES x86_64)
  \end{tmcode}
  \item Line 30. MKL path
  
  If a user wants to use HDSDP linked with MKL, set the path to the MKL
  libraries according to the instructions in {\tmsamp{CMakeLists.txt}}
\end{itemize}
By default, HDSDP is compiled without MKL, and the only requirements are
{\tmsamp{LAPACK}} and {\tmsamp{BLAS}} routines. Then the library can be built
with

\begin{tmlisting}
  \begin{alltt}
mkdir build
\end{alltt}
  \begin{alltt}
cd build
\end{alltt}
  \begin{alltt}
cmake ..  # Add "-DLINSYS_PARDISO=ON" if MKL is linked
\end{alltt}
  \begin{alltt}
make
\end{alltt}
\end{tmlisting}

and the build system will generate three files
\begin{itemize}
  \item Static library {\tmsamp{\tmtexttt{hdsdp}}}
  
  \item Dynamic library {\tmsamp{\tmtexttt{hdsdp}}}
  
  \item Executable binary {\tmsamp{\tmtexttt{sdpasolve}}}
\end{itemize}

\subsection{Using the executable binary}

The \tmtexttt{sdpasolve} executable is used for benchmarking purpose and
accepts two types of input

\begin{tmlisting}
  \begin{alltt}
./sdpasolve data.dat-s # For SDP problems
\end{alltt}
  \begin{alltt}
./sdpasolve data.mps   # For standard-form LP problems
\end{alltt}
\end{tmlisting}

\section{Data and solver interface}

HDSDP is designed as a stand-alone optimization solver and provides a
self-contained interface. After the data is input, the solver will initiate
the subsequent solution phases automatically until the solution procedure ends
or fails. With the compiled library, the user can call the solver by including
the header \tmtexttt{interface/hdsdp.h} and the data interface
\tmtexttt{interface/hdsdp\_user\_data.h}. See \tmtexttt{test/test\_file\_io.c}
for more examples of calling \tmtexttt{HDSDP}.

The header \tmtexttt{hdsdp.h} defines several utility macros, including return
code, status code, parameters, constants and the solver interface.

The header \tmtexttt{hdsdp\_user\_data.h} defines the user input data
interface of \tmtexttt{HDSDP}.

\subsection{Notations}

\tmtexttt{HDSDP} internally solves the following mixed SDP-LP problem
\begin{eqnarray*}
  \min_{X, x} & \sum_{j = 1}^p \langle C_j, X_j \rangle + \langle c, x \rangle
  & \\
  \text{subject to} & \sum_{j = 1}^p \langle A_{i j}, X_j \rangle + \langle
  a_i, x \rangle = b_i, & i = 1, \ldots, m\\
  & X_j \in \mathbb{S}_+^{n_j}, & j = 1, \ldots, p\\
  & x \in \mathbb{R}^{n_l}_+ . & 
\end{eqnarray*}
We define the following notations
\begin{itemize}
  \item $m$ is the number of constraints
  
  \item $p$ is the number of SDP cones
  
  \item $n_j$ is the cone dimension of the $j$-th SDP cone
  
  \item $n_s = \sum_{j = 1}^p n_j$ is the total SDP cone dimension
  
  \item $n_l$ is the LP cone dimension.
\end{itemize}

\subsection{Return code}

HDSDP subroutines use return code to handle error and exceptions. Subroutines
with return code \tmtexttt{hdsdp\_retcode} returns one of the codes below
\begin{itemize}
  \item \tmtexttt{HDSDP\_RETCODE\_OK}
  
  The subroutine successfully exits
  
  \item \tmtexttt{HDSDP\_RETCODE\_FAILED}
  
  The subroutine exits due to exception or error
  
  \item \tmtexttt{HDSDP\_RETCODE\_MEMORY}
  
  The subroutine exits due to memory allocation issues
\end{itemize}
Users can use the \tmtexttt{HDSDP\_CALL(func)} macro from
\tmtexttt{interface/hdsdp\_utils.h} when calling HDSDP routines, and the macro
will automatically jump to \tmtexttt{exit\_cleanup} label when a non-OK status
code is detected: for example

\begin{tmcode}[cpp]
HDSDP_CALL(HDSDPOptimize(hdsdp, 1));
exit_cleanup:
    HDSDPDestroy(&hdsdp);
\end{tmcode}

\subsection{Data format}

The data interface of HDSDP is defined in
\tmtexttt{interface/hdsdp\_user\_data.h} and allows users to input $\{ C_j \},
\{ A_{i j} \}, \{ a_i \}, c$ using sparse matrix input.

\subsubsection{SDP cone data}

Each SDP cone in HDSDP is determined by $m$ constraint matrices and an
objective matrix
\[ \{ A_1, \ldots, A_m, C \}, \]
where $\{ A_i \}$ and $C$ are all symmetric matrices. Given a symmetric matrix
$A \in \mathbb{S}^n$:
\[ A = \left(\begin{array}{cccc}
     \downarrow \tmcolor{red}{a_{1 1}} &  &  & \\
     \downarrow a_{2 1} & \downarrow a_{2 2} &  & \\
     \vdots & \vdots & \ddots & \\
     \tmcolor{red}{a_{n 1}} & a_{n 2} & \cdots & a_{n n}
   \end{array}\right), \]
we define its vectorization $\tmop{vec} (A) : \mathbb{S}^n \rightarrow
\mathbb{R}^{\tfrac{n \times (n + 1)}{2}}$ as follows
\[ \tmop{vec} (A) \assign (\tmcolor{red}{a_{11}}, a_{21}, \cdots
   \tmcolor{red}{a_{n 1}}, \ldots, a_{22}, a_{23} \ldots, a_{n n})^{\top} . \]
The vectorized version of $A$ only contains the lower triangular part of $A$.
Then, for each SDP block we can concatenate the coefficient matrices by
\[ V_{\tmop{SDP}} \assign \left(\begin{array}{ccccc}
     | & | & | &  & |\\
     \tmop{vec} (C) & \tmop{vec} (A_1) & \tmop{vec} (A_2) & \cdots &
     \tmop{vec} (A_m)\\
     | & | & | &  & |
   \end{array}\right) {\in \mathbb{R}^{\tfrac{n \times (n + 1)}{2} \times (m +
   1)}}  . \]
Then the matrix $V_{\tmop{SDP}}$ is compressed using standard compressed
sparse column (\tmtexttt{CSC}) format.

\begin{example}
  Consider the following 2D SDP
  \begin{eqnarray*}
    \min_X & \left\langle \tmcolor{red}{\left(\begin{array}{cc}
      6 & 2\\
      2 & 3
    \end{array}\right)}, X \right\rangle & \\
    \text{subject to} & \left\langle \tmcolor{blue}{\left(\begin{array}{cc}
      1 & 0\\
      0 & 1
    \end{array}\right)}, X \right\rangle = 1 & \\
    & \left\langle \tmcolor{orange}{\left(\begin{array}{cc}
      0 & 1\\
      1 & 0
    \end{array}\right)}, X \right\rangle = 2 & \\
    & X \succeq 0. & 
  \end{eqnarray*}
  The problem has 2 constraints and an SDP cone. Then the SDP cone can be
  represented by
  \[ V_{\tmop{SDP}} = \left(\begin{array}{ccc}
       6 & 1 & 0\\
       2 & 0 & 2\\
       3 & 1 & 0
     \end{array}\right) \]
  and the cone can be represented by the following sparse matrix format.
  
  \begin{tmlisting}
    \begin{alltt}
Vp[4] = \{0, 3, 5, 6\};
\end{alltt}
    \begin{alltt}
Vi[6] = \{0, 1, 2, 0, 2, 1\};
\end{alltt}
    \begin{alltt}
Vx[6] = \{6, 2, 3, 1, 1, 2\};
\end{alltt}
  \end{tmlisting}
\end{example}

\subsubsection{LP cone data}

LP cone data is similar to SDP, where we concatenate $\{ a_i \}$ by
\[ V_{\tmop{LP}} = \left(\begin{array}{ccccc}
     c & a_1 & a_2 & \cdots & a_m
   \end{array}\right) \in \mathbb{R}^{n \times (m + 1)} \]
and $V_{\tmop{LP}}$ is also compressed by \tmtexttt{CSC} format.

\paragraph{Scalar bound cone.}HDSDP also provides a scalar bound cone for
constraints on the dual variables $l \cdummy e \leq y \leq u \cdummy e$. HDSDP
will detect in the presolve phase whether an LP cone is a scalar bound cone,
and will switch to bound cone when it is detected.

\subsection{Data interface}

\subsubsection{Create user data structure}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern hdsdp_retcode HUserDataCreate( user_data **pHdata );
\end{tmcode}

\tmtextbf{Explanation}

Create an HDSDP user data pointer

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{pHdata}
  
  Type: \tmtexttt{user\_data **}
  
  Address of the pointer to which the user data structure is to be allocated
\end{itemize}
\tmtextbf{Return}

Status of execution

\subsubsection{Set cone data}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HUserDataSetConeData( user_data *Hdata, 
                                  cone_type cone, 
                                  int nRow, 
                                  int nCol,
                                  int *coneMatBeg, 
                                  int *coneMatIdx, 
                                  double *coneMatElem );
\end{tmcode}

\tmtextbf{Explanation}

Set cone data in an existing user data structure

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{Hdata}
  
  Type: \tmtexttt{user\_data *}
  
  Pointer of the user data structure
  
  \item \tmtexttt{cone}
  
  Type: \tmtexttt{cone\_type *}
  
  Type of the cone specified by the user. Possible choices are
  \begin{itemize}
    \item \tmtexttt{HDSDP\_CONETYPE\_LP}
    
    LP cone
    
    \item \tmtexttt{HDSDP\_CONETYPE\_DENSE\_SDP}
    
    SDP cone
    
    \item \tmtexttt{HDSDP\_CONETYPE\_SPARSE\_SDP}
    
    SDP cone where most of the $\{ A_i \}$ are all-zero matrices
  \end{itemize}
  \item \tmtexttt{nRow}
  
  Type: \tmtexttt{int}
  
  Number of constraints of the cone. Should be the same for all the cones
  
  \item \tmtexttt{nCol}
  
  Type: \tmtexttt{int}
  
  Dimension of the cone, $n_l$ or $n_j$
  
  \item \tmtexttt{coneMatBeg}
  
  Type: \tmtexttt{int *}
  
  Column pointer for the \tmtexttt{CSC} sparse matrix
  
  \item \tmtexttt{coneMatIdx}
  
  Type: \tmtexttt{int *}
  
  Row indices for the \tmtexttt{CSC} sparse matrix
  
  \item \tmtexttt{coneMatElem}
  
  Type: \tmtexttt{double *}
  
  Elements for the \tmtexttt{CSC} sparse matrix
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Determine cone type}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern cone_type HUserDataChooseCone( user_data *Hdata );
\end{tmcode}

\tmtextbf{Explanation}

Automatically detect and adjust the cone type based on problem data. The
routine can determine \tmtextbf{1)} whether a dense SDP cone should instead be
specified as a sparse SDP cone \tmtextbf{2)} whether an LP cone is a bound
cone. This routine will be automatically invoked within the HDSDP solver
routine

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{Hdata}
  
  Type: \tmtexttt{user\_data *}
  
  Pointer of the user data structure with cone data available
\end{itemize}
\tmtextbf{Return}

Type of the cone detected by the solver

\subsubsection{Clear user data}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HUserDataClear( user_data *Hdata );
\end{tmcode}

\tmtextbf{Explanation}

Clear the user data

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{Hdata}
  
  Type: \tmtexttt{user\_data *}
  
  Pointer of the user data
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Destroy user data structure}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HUserDataDestroy( user_data **pHdata );
\end{tmcode}

\tmtextbf{Explanation}

Clear and release all the memory of user data

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{pHdata}
  
  Type: \tmtexttt{user\_data **}
  
  Address of the pointer to which the user data structure is allocated
\end{itemize}
\tmtextbf{Return}

No return

\subsection{Solver interface}

\subsubsection{Create the solver structure}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern hdsdp_retcode HDSDPCreate( hdsdp **pHSolver );
\end{tmcode}

\tmtextbf{Explanation}

Create an HDSDP solver data structure

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{pHSolver}
  
  Type: \tmtexttt{hdsdp **}
  
  Address of the pointer to which the solver is to be allocated
\end{itemize}
\tmtextbf{Return}

Status of execution

\subsubsection{Solver initialization}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern hdsdp_retcode HDSDPInit( hdsdp *HSolver, int nRows, int nCones );
\end{tmcode}

\tmtextbf{Explanation}

Initialize solver and allocate solver memory

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{nRows}
  
  Type: \tmtexttt{int}
  
  Number of constraints of the problem
  
  \item \tmtexttt{nCones}
  
  Type: \tmtexttt{int nCones}
  
  Number of cones of the problem
\end{itemize}
\tmtextbf{Return}

Status of execution

\subsubsection{Set conic data}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern hdsdp_retcode HDSDPSetCone( hdsdp *HSolver, int iCone, void *userCone );
\end{tmcode}

\tmtextbf{Explanation}

Set cone data in the solver

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{iCone}
  
  Type: \tmtexttt{int}
  
  Index of the cone. Range between 0 and \tmtexttt{nCones} specified when
  calling \tmtexttt{HDSDPInit}
  
  \item \tmtexttt{userCone}
  
  Type: \tmtexttt{void *}
  
  Pointer to user cone data
\end{itemize}
\tmtextbf{Return}

Status of execution

\subsubsection{Set dual objective}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HDSDPSetDualObjective( hdsdp *HSolver, double *dObj );
\end{tmcode}

\tmtextbf{Explanation}

Set the primal constraint right-hand-side and the dual objective $b$

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{dObj}
  
  Type: \tmtexttt{double *}
  
  Dual objective. A vector of length $m$
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Set dual starting point}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HDSDPSetDualStart( hdsdp *HSolver, double *dStart );
\end{tmcode}

\tmtextbf{Explanation}

Set the starting point for the dual problem $y_0$.

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{dStart}
  
  Type: \tmtexttt{double *}
  
  Dual variable starting point. A vector of length $m$
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Set integer parameter}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HDSDPSetIntParam( hdsdp *HSolver, 
                              int intParam, 
                              int intParamVal );
\end{tmcode}

\tmtextbf{Explanation}

Set an integer parameter (see the next section for the available parameters)

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{intParam}
  
  Type: \tmtexttt{int}
  
  Integer parameter name
  
  \item \tmtexttt{intParamVal}
  
  Type: \tmtexttt{int}
  
  Value of the integer parameter
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Set double parameter}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HDSDPSetDblParam( hdsdp *HSolver, 
                              int dblParam, 
                              double dblParamVal );
\end{tmcode}

\tmtextbf{Explanation}

Set a double parameter (see the next section for the available parameters)

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{dblParam}
  
  Type: \tmtexttt{int}
  
  Double parameter name
  
  \item \tmtexttt{dblParamVal}
  
  Type: \tmtexttt{double}
  
  Value of the double parameter
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Optimization}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern hdsdp_retcode HDSDPOptimize( hdsdp *HSolver, int dOptOnly );
\end{tmcode}

\tmtextbf{Explanation}

Invoke HDSDP optimization routine

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{dOptOnly}
  
  Type: \tmtexttt{int}
  
  Whether HDSDP should only optimize the dual problem. If \tmtexttt{dOptOnly}
  is nonzero, then the algorithm will perform Phase 1 (infeasible-start
  embedding phase) and will not go into primal solution extraction.
\end{itemize}
\tmtextbf{Return}

Status of execution

\subsubsection{Get dual solution}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern hdsdp_retcode HDSDPGetRowDual( hdsdp *HSolver, 
                                      double *pObjVal,
                                      double *dObjVal, 
                                      double *dualVal );
\end{tmcode}

\tmtextbf{Explanation}

Extract dual optimal value after optimization finishes

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{pObjVal}
  
  Type: \tmtexttt{double *}
  
  Optimal primal objective {\tmem{value}}. Can be \tmtexttt{NULL} if objective
  value is not needed
  
  \item \tmtexttt{dObjVal}
  
  Type: \tmtexttt{double *}
  
  Optimal dual objective {\tmem{value}}. Can be \tmtexttt{NULL} if objective
  value is not needed
  
  \item \tmtexttt{dualVal}
  
  Type: \tmtexttt{double *}
  
  Optimal dual objective solution $y^{\star}$. Can be \tmtexttt{NULL} if
  solution is not needed
\end{itemize}
\tmtextbf{Return}

Status of execution

\subsubsection{Get cone solution}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HDSDPGetConeValues( hdsdp *HSolver, 
                                int iCone, 
                                double *conePrimal, 
                                double *coneDual, 
                                double *coneAuxi );
\end{tmcode}

\tmtextbf{Explanation}

Extract the cone primal optimal solution. Auxiliary memory is required for
extraction.

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{iCone}
  
  Type: \tmtexttt{int}
  
  Index of the cone
  
  \item \tmtexttt{conePrimal}
  
  Type: \tmtexttt{double *}
  
  Optimal primal solution $X^{\star}$
  
  \item \tmtexttt{coneDual}
  
  Type: \tmtexttt{double *}
  
  Optimal dual slack $S^{\star}$
  
  \item \tmtexttt{coneAuxi}
  
  Type: \tmtexttt{double *}
  
  Auxiliary memory for extraction of size $n_j$ for SDP) or $n_l$ (for LP).
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Check solution and compute solution metrics}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern hdsdp_retcode HDSDPCheckSolution( hdsdp *HSolver, double diErrors[6] );
\end{tmcode}

\tmtextbf{Explanation}

Check the solution quality and compute the DIMACS errors

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
  
  \item \tmtexttt{diErrors}
  
  Type: \tmtexttt{double *}
  
  The six DIMACS errors indicating the quality of the solution
\end{itemize}
\tmtextbf{Return}

Status of execution

\subsubsection{Release solver memory}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HDSDPClear( hdsdp *HSolver );
\end{tmcode}

\tmtextbf{Explanation}

Release all the internal memory allocated by HDSDP

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{HSolver}
  
  Type: \tmtexttt{hdsdp *}
  
  Pointer of the solver
\end{itemize}
\tmtextbf{Return}

No return

\subsubsection{Destroy solver structure}

\tmtextbf{Function}

\begin{tmcode}[cpp]
extern void HDSDPDestroy( hdsdp **pHSolver );
\end{tmcode}

\tmtextbf{Explanation}

Clear and release all the memory of HDSDP.

\tmtextbf{Argument}
\begin{itemize}
  \item \tmtexttt{pHSolver}
  
  Type: \tmtexttt{hdsdp **}
  
  Pointer of the solver
\end{itemize}
\tmtextbf{Return}

No return

\section{Parameters}

\subsection{Integer parameters}

\subsubsection{INT\_PARAM\_CORRECTORA}

\tmtextbf{Explanation}: Number of corrector steps in HDSDP infeasible
embedding phase. More corrector steps reduce the number of iterations but can
increase time spent per iteration

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: Adjusted by problem feature

\subsubsection{INT\_PARAM\_CORRECTORB}

\tmtextbf{Explanation}: Number of corrector steps in HDSDP feasible dual
potential reduction phase. More corrector steps reduce the number of
iterations but can increase time spent per iteration

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: Adjusted by problem feature

\subsubsection{INT\_PARAM\_MAXITER}

\tmtextbf{Explanation}: Maximum number of potential reduction iterations

\tmtextbf{Range}: $\geq 1$

\tmtextbf{Default}: 500

\subsubsection{INT\_PARAM\_PSDP}

\tmtextbf{Explanation}: {\tmem{Experiment feature}}. Whether primal IPM solver
is turned on when dual SDP is close to convergence

\tmtextbf{Range}: $\{ 0, 1 \}$

\tmtextbf{Default}: 0

\subsubsection{INT\_PARAM\_PRELEVEL}

\tmtextbf{Explanation}: Presolving level for problem data and KKT solver. In
general no benefit using low level presolving

\tmtextbf{Range}: $\{ 0, 1, 2 \}$

\tmtextbf{Default}: 2

\subsubsection{INT\_PARAM\_THREADS}

\tmtextbf{Explanation}: Number of threads for linear algebra subroutines. Only
effective when Intel MKL is linked to HDSDP.

\tmtextbf{Range}: $\geq 1$

\tmtextbf{Default}: 12

\subsection{Double parameters}

\subsubsection{DBL\_PARAM\_RELFEASTOL}

\tmtextbf{Explanation}: Relative feasibility tolerance for $\max \left\{
\frac{\| \mathcal{A}X - b \|}{1 + \| b \|_1}, \frac{\| \mathcal{A}^{\ast} y +
S - C \|_F}{1 + \| C \|_{\tmop{sum}}} \right\}$

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^{- 8}$, also adjusted by problem feature

\subsubsection{DBL\_PARAM\_RELOPTTOL}

\tmtextbf{Explanation}: Relative optimality tolerance for $\frac{| \langle C,
X \rangle - \langle b, y \rangle |}{| \langle C, X \rangle | + | \langle b, y
\rangle | + 1}$

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^{- 8}$, also adjusted by problem feature

\subsubsection{DBL\_PARAM\_ABSFEASTOL}

\tmtextbf{Explanation}: Absolute feasibility tolerance for $\max \{ \|
\mathcal{A}X - b \|, \| \mathcal{A}^{\ast} y + S - C \|_F \}$

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^{- 8}$, also adjusted by problem feature

\subsubsection{DBL\_PARAM\_ABSOPTTOL}

\tmtextbf{Explanation}: Absolute optimality tolerance for $| \langle C, X
\rangle - \langle b, y \rangle |$

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^{- 8}$, also adjusted by problem feature

\subsubsection{DBL\_PARAM\_TIMELIMIT}

\tmtextbf{Explanation}: Solver running time limit

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: 3600.0

\subsubsection{DBL\_PARAM\_POTRHOVAL}

\tmtextbf{Explanation}: Potential function parameter

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: Adjusted by problem feature

\subsubsection{DBL\_PARAM\_HSDGAMMA}

\tmtextbf{Explanation}: Infeasibility elimination aggressiveness in embedding
phase

\tmtextbf{Range}: $[0, 1]$

\tmtextbf{Default}: Adjusted by problem feature

\subsubsection{DBL\_PARAM\_DUALBOX\_LOW}

\tmtextbf{Explanation}: Scalar lower bound on the dual variables $y \geq l
\cdummy e$

\tmtextbf{Range}: $\mathbb{R}$

\tmtextbf{Default}: Adjusted by problem feature

\subsubsection{DBL\_PARAM\_DUALBOX\_UP}

\tmtextbf{Explanation}: Scalar upper bound on the dual variables $y \leq u
\cdummy e$

\tmtextbf{Range}: $\mathbb{R}$

\tmtextbf{Default}: Adjusted by problem feature

\subsubsection{DBL\_PARAM\_BARMUSTART}

\tmtextbf{Explanation}: Starting barrier parameter

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^5$

\subsubsection{DBL\_PARAM\_DUALSTART}

\tmtextbf{Explanation}: Starting dual slack size: $\theta$ in $S_0 = C
-\mathcal{A}^{\ast} y_0 + \theta I$

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^5$

\subsubsection{DBL\_PARAM\_POBJSTART}

\tmtextbf{Explanation}: Initial primal objective guess

\tmtextbf{Range}: $\mathbb{R}$

\tmtextbf{Default}: $10^{10}$

\subsubsection{DBL\_PARAM\_TRXESTIMATE}

\tmtextbf{Explanation}: Primal optimal solution trace estimate

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^8$

\subsubsection{DBL\_PARAM\_PRECORDACC}

\tmtextbf{Explanation}: Accuracy for preparing for primal solution recovery.
When the dual solution is too accurate, extraction of primal solution can fail
due to significant numerical errors. Therefore, this parameter should not be
set too small.

\tmtextbf{Range}: $\geq 0$

\tmtextbf{Default}: $10^{- 8}$

\section{Logging and Examples}

HDSDP has a logging system that allows users to keep track of the optimization
progress.

\subsection{SDP Logging}

\begin{lstlisting}
Filename: ../examples/mcp100.dat-s
Reading SDPA file in 0.000535 seconds
HDSDP: software for semi-definite programming
Wenzhi Gao, Dongdong Ge, Yinyu Ye, 2024
---------------------------------------------
Pre-solver starts
  Processing the cones
   M1: 0  M2: 100  M3: 0  M4: 0  M5: 0
  Starting KKT analysis
   Using dense Schur complement
  Collecting statistics
  Making adjustments
   Scale cone objective by 1.0e+00
   Scale rhs by 1.0e+00
   Hardware has 1 thread(s)
Pre-solver ends. Elapsed time: 0.0 seconds

Statistics
  Number of rows: 100
  Number of cones: 1
  Number of sparse SDP cones: 0
  ...
  Norm of objective: 2.69e+02
  Norm of SDP data: 1.00e+02
  Norm of RHS: 1.00e+02

Parameters
  Maximum iteration : 500
  Infeasible corrector: 4
  Feasible corrector : 0
  ...
  Dual box low : -1.0e+06
  Dual box up  :  1.0e+06
  Starting primal : 1.0e+08

This is a trace-implied SDP problem
Optimizing over 1 thread(s)
Initialize with dual residual 1.0e+05
HDSDP starts. Using infeasible dual method

    nIter    pObj         dObj        dInf     Mu     Step   |P|  T [D]
       1    +7.33331918e+07  -7.35913354e+07  0.00e+00  3.56e+04  0.76  7.2e+00 0.0

Infeasible method finds a dual feasible solution
HDSDP re-starts. Using feasible dual method

    nIter    pObj         dObj        pInf     Mu     Step   |P|  T [P]
       1    +7.33331918e+07  -4.81595948e+07  5.23e-02 4.26e+05 1.00  1.0e+01 0.0
      ...
      34    -2.26157351e+02  -2.26157351e+02  0.00e+00 5.28e-12 0.12 1.2e+01 0.1

Optimization time: 0.1 seconds
DIMACS error metric:
   1.10e-13 0.00e+00 0.00e+00 0.00e+00 6.50e-09 6.50e-09

SDP Status: Primal dual optimal
  pObj -2.2615734854e+02
  dObj -2.2615735148e+02
  PD Gap +2.9464339377e-06
  Time 0.1 seconds
\end{lstlisting}

\subsection{LP Logging}

\begin{lstlisting}
Reading specialized standard form mps ../examples/afiro.mps
Optimizing an LP of 23 variables and 15 constraints
Data statistics: |A| = 1.06e+02 |b| = 9.82e+03 |c| = 2.08e+00 Nnz = 49
Using Hybrid Primal-Primal-Dual solver

    nIter      pObj         dObj        pInf     dInf    Mu    P/D Step  T [PD]
       0    -2.76027927e+02  -1.04931952e+02  8.59e-01 1.91e+00 0.00 0.00  0.0
       1    -2.54976427e+02  -4.55135868e+02  1.83e-02 3.93e-01 0.98 0.79  0.0
       2    -4.33824047e+02  -5.31380377e+02  4.30e-03 4.39e-03 0.76 0.99  0.0
       3    -4.63764901e+02  -4.83113579e+02  5.05e-04 9.48e-04 0.88 0.78  0.0
       4    -4.64643942e+02  -4.65030078e+02  3.98e-15 1.41e-05 1.00 0.99  0.0
       5    -4.64752596e+02  -4.64754528e+02  4.93e-16 7.06e-08 0.99 0.99  0.0
       6    -4.64753140e+02  -4.64753150e+02  2.70e-15 3.53e-10 1.00 1.00  0.0
       7    -4.64753143e+02  -4.64753143e+02  3.22e-15 1.77e-12 1.00 1.00  0.0

LP Status: Primal dual optimal

LP Solution statistic
  pObj: -4.648e+02  dObj: -4.648e+02
  Abs. pInf: 1.152e-11   Rel. pInf: 3.221e-15
  Abs. dInf: 4.266e-12   Rel. dInf: 1.765e-12
  Abs. Gap : 4.830e-08   Rel. gap : 5.191e-11

Linear solver statistic
  Num. Factor: 7 (+1)  Factor Time: 0.00
  Num. Solves: 15 (+1) Solve Time: 0.00

Elapsed Time: 0.000 seconds
\end{lstlisting}

\bibliography{ref.bib}
\bibliographystyle{plain}

\end{document}
