From 6f94849e16c621c45c30eab47c63046b0650abb3 Mon Sep 17 00:00:00 2001 From: zach401 Date: Thu, 13 Jan 2022 09:49:56 -0800 Subject: [PATCH 01/12] Replace calls to LDL with calls to QDLDL. --- .gitmodules | 3 ++ CMakeLists.txt | 6 ++++ Makefile | 4 +-- include/glblopts.h | 2 ++ include/kkt.h | 9 +++--- src/kkt.c | 60 +++++++++++++++++-------------------- src/preproc.c | 39 +++++++++++------------- test/exponential/log_ax_x.h | 2 +- 8 files changed, 65 insertions(+), 60 deletions(-) create mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..87407bc2 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/qdldl"] + path = external/qdldl + url = https://github.com/osqp/qdldl.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f8719c7..ef31a5f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,8 @@ endif() # Add the ECOS headers set(ecos_headers "${CMAKE_CURRENT_SOURCE_DIR}/external/SuiteSparse_config/SuiteSparse_config.h" + "${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl/configure/qdldl_types.h.in" + "${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl/configure/qdldl_version.h.in" "${CMAKE_CURRENT_SOURCE_DIR}/include/cone.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/ctrlc.h" "${CMAKE_CURRENT_SOURCE_DIR}/include/data.h" @@ -58,6 +60,9 @@ set(ecos_sources # LDL "${CMAKE_CURRENT_SOURCE_DIR}/external/ldl/src/ldl.c" + # QDLDL + "${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl/src/qdldl.c" + # ECOS "${CMAKE_CURRENT_SOURCE_DIR}/src/cone.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/ctrlc.c" @@ -97,6 +102,7 @@ target_include_directories(ecos "$" "$" "$" + "$" "$" "$/${CMAKE_INSTALL_INCLUDEDIR}/ecos>" ) diff --git a/Makefile b/Makefile index 73dc6909..02dbe7bb 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ # Configuration of make process in ecos.mk include ecos.mk -CFLAGS += -Iinclude -Iexternal/ldl/include -Iexternal/amd/include -Iexternal/SuiteSparse_config +CFLAGS += -Iinclude -Iexternal/qdldl/include -Iexternal/amd/include -Iexternal/SuiteSparse_config TEST_INCLUDES = -Itest -Itest/generated # Compile all C code, including the C-callable routine @@ -76,7 +76,7 @@ $(SHAREDNAME): $(LDL) $(AMD) $(ECOS_OBJS) TEST_OBJS = qcml_utils.o norm.o sq_norm.o sum_sq.o quad_over_lin.o inv_pos.o .PHONY: test test: ecostester ecos_bb_test -ecostester: test/ecostester.c $(TEST_OBJS) libecos.a +ecostester: test/ecostester.c $(TEST_OBJS) libecos.a external/qdldl/build/out/libqdldl.a $(CC) $(CFLAGS) $(TEST_INCLUDES) -o $@ $^ $(LDFLAGS) ecos_bb_test: test/bb_test.c libecos_bb.a diff --git a/include/glblopts.h b/include/glblopts.h index e63188a6..80c3e0c8 100644 --- a/include/glblopts.h +++ b/include/glblopts.h @@ -50,6 +50,8 @@ #include /* NOTE: Currently, pfloat MUST be double for ecos */ typedef double pfloat; /* for numerical values */ +typedef unsigned char ecos_bool; /* for boolean values */ + #define ECOS_INFINITY (DBL_MAX + DBL_MAX) #define ECOS_NAN (ECOS_INFINITY - ECOS_INFINITY) diff --git a/include/kkt.h b/include/kkt.h index a2f58f69..6de044de 100644 --- a/include/kkt.h +++ b/include/kkt.h @@ -38,7 +38,8 @@ typedef struct kkt{ spmat* PKPt; /* Permuted KKT matrix, upper part only */ spmat* L; /* LDL factor L */ - pfloat* D; /* diagonal matrix D */ + pfloat* D; /* diagonal matrix D */ + pfloat* Dinv; /* inverse of diagonal matrix D */ pfloat* work1; /* workspace needed for factorization */ pfloat* work2; /* workspace needed for factorization */ pfloat* work3; /* workspace needed for factorization */ @@ -58,9 +59,9 @@ typedef struct kkt{ idxint* Pinv; /* reverse permutation */ idxint* PK; /* permutation of row indices of KKT matrix */ idxint* Parent; /* Elimination tree of factorization */ - idxint* Sign; /* Permuted sign vector for regularization */ - idxint* Pattern; /* idxint workspace needed for factorization */ - idxint* Flag; /* idxint workspace needed for factorization */ + idxint* Sign; /* Permuted sign vector for regularization */ + ecos_bool* bwork; /* ecos_bool workspace needed for factorization */ + idxint* iwork; /* idxint workspace needed for factorization */ idxint* Lnz; /* idxint workspace needed for factorization */ pfloat delta; /* size of regularization */ diff --git a/src/kkt.c b/src/kkt.c index d438ca6d..267f3b9c 100644 --- a/src/kkt.c +++ b/src/kkt.c @@ -27,7 +27,7 @@ */ #include "kkt.h" -#include "ldl.h" +#include "qdldl.h" #include "splamm.h" #include "ecos.h" #include "cone.h" @@ -43,30 +43,24 @@ idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta) { idxint nd; - /* returns n if successful, k if D (k,k) is zero */ - nd = LDL_numeric2( - KKT->PKPt->n, /* K and L are n-by-n, where n >= 0 */ - KKT->PKPt->jc, /* input of size n+1, not modified */ - KKT->PKPt->ir, /* input of size nz=Kjc[n], not modified */ - KKT->PKPt->pr, /* input of size nz=Kjc[n], not modified */ - KKT->L->jc, /* input of size n+1, not modified */ - KKT->Parent, /* input of size n, not modified */ - KKT->Sign, /* input, permuted sign vector for regularization */ - eps, /* input, inverse permutation vector */ - delta, /* size of dynamic regularization */ - KKT->Lnz, /* output of size n, not defn. on input */ - KKT->L->ir, /* output of size lnz=Lp[n], not defined on input */ - KKT->L->pr, /* output of size lnz=Lp[n], not defined on input */ - KKT->D, /* output of size n, not defined on input */ - KKT->work1, /* workspace of size n, not defn. on input or output */ - KKT->Pattern, /* workspace of size n, not defn. on input or output */ - KKT->Flag /* workspace of size n, not defn. on input or output */ -#if PROFILING > 1 - , t1, t2 -#endif + nd = QDLDL_factor( + KKT->PKPt->n, /* K and L are n-by-n, where n >= 0 */ + KKT->PKPt->jc, /* input of size n+1, not modified */ + KKT->PKPt->ir, /* input of size nz=Kjc[n], not modified */ + KKT->PKPt->pr, /* input of size nz=Kjc[n], not modified */ + KKT->L->jc, /* input of size n+1, not modified */ + KKT->L->ir, /* output of size lnz=Lp[n], not defined on input */ + KKT->L->pr, /* output of size lnz=Lp[n], not defined on input */ + KKT->D, /* output of size n, not defined on input */ + KKT->Dinv, /* output of size n, not defined on input */ + KKT->Lnz, /* output of size n, not defn. on input */ + KKT->Parent, /* input of size n, not modified */ + KKT->bwork, /* workspace of size n, not defined on input or output */ + KKT->iwork, /* workspace of size 3*n, not defined on input or output */ + KKT->work1 /* workspace of size n, not defined on input or output */ ); - - return nd == KKT->PKPt->n ? KKT_OK : KKT_PROBLEM; + /* Negative return values indicate problems factoring the matrix */ + return nd > 0 ? KKT_OK : KKT_PROBLEM; } @@ -116,10 +110,11 @@ idxint kkt_solve(kkt* KKT, spmat* A, spmat* G, pfloat* Pb, pfloat* dx, pfloat* d pfloat error_threshold = bnorm*LINSYSACC; idxint nK = KKT->PKPt->n; - /* forward - diagonal - backward solves: Px holds solution */ - LDL_lsolve2(nK, Pb, KKT->L->jc, KKT->L->ir, KKT->L->pr, Px ); - LDL_dsolve(nK, Px, KKT->D); - LDL_ltsolve(nK, Px, KKT->L->jc, KKT->L->ir, KKT->L->pr); + /* Initialize Px to the value of Pb */ + for( j=0; j < nK; j++ ){ Px[j] = Pb[j]; } + + /* Solve the system of equations, Px holds the solution */ + QDLDL_solve(nK, KKT->L->jc, KKT->L->ir, KKT->L->pr, KKT->Dinv, Px ); #if PRINTLEVEL > 2 if( p > 0 ){ @@ -245,10 +240,11 @@ idxint kkt_solve(kkt* KKT, spmat* A, spmat* G, pfloat* Pb, pfloat* dx, pfloat* d /* permute */ for( i=0; iL->jc, KKT->L->ir, KKT->L->pr, dPx); - LDL_dsolve(nK, dPx, KKT->D); - LDL_ltsolve(nK, dPx, KKT->L->jc, KKT->L->ir, KKT->L->pr); + /* Initialize dPx to the value of Pe */ + for( j=0; jL->jc, KKT->L->ir, KKT->L->pr, KKT->Dinv, dPx ); /* add refinement to Px */ for( i=0; iKKT->D); /* mywork->KKT->D = (pfloat *)MALLOC(nK*sizeof(pfloat)); */ + FREE(w->KKT->Dinv); /* mywork->KKT->Dinv = (pfloat *)MALLOC(nK*sizeof(pfloat)); */ FREE(w->KKT->dx1); /* mywork->KKT->dx1 = (pfloat *)MALLOC(mywork->n*sizeof(pfloat)); */ FREE(w->KKT->dx2); /* mywork->KKT->dx2 = (pfloat *)MALLOC(mywork->n*sizeof(pfloat)); */ FREE(w->KKT->dy1); /* mywork->KKT->dy1 = (pfloat *)MALLOC(mywork->p*sizeof(pfloat)); */ FREE(w->KKT->dy2); /* mywork->KKT->dy2 = (pfloat *)MALLOC(mywork->p*sizeof(pfloat)); */ FREE(w->KKT->dz1); /* mywork->KKT->dz1 = (pfloat *)MALLOC(mywork->m*sizeof(pfloat)); */ FREE(w->KKT->dz2); /* mywork->KKT->dz2 = (pfloat *)MALLOC(mywork->m*sizeof(pfloat)); */ - FREE(w->KKT->Flag); /* mywork->KKT->Flag = (idxint *)MALLOC(nK*sizeof(idxint)); */ + FREE(w->KKT->iwork); /* mywork->KKT->iwork = (idxint *)MALLOC(3*nK*sizeof(idxint)); */ freeSparseMatrix(w->KKT->L); FREE(w->KKT->Lnz); /* mywork->KKT->Lnz = (idxint *)MALLOC(nK*sizeof(idxint)); */ FREE(w->KKT->Parent); /* mywork->KKT->Parent = (idxint *)MALLOC(nK*sizeof(idxint)); */ - FREE(w->KKT->Pattern); /* mywork->KKT->Pattern = (idxint *)MALLOC(nK*sizeof(idxint)); */ - FREE(w->KKT->Sign); /* mywork->KKT->Sign = (idxint *)MALLOC(nK*sizeof(idxint)); */ + FREE(w->KKT->bwork); /* mywork->KKT->bwork = (ecos_bool *)MALLOC(nK*sizeof(ecos_bool));*/ + FREE(w->KKT->Sign); /* mywork->KKT->Sign = (idxint *)MALLOC(nK*sizeof(idxint)); */ FREE(w->KKT->Pinv); /* mywork->KKT->Pinv = (idxint *)MALLOC(nK*sizeof(idxint)); */ FREE(w->KKT->P); FREE(w->KKT->PK); /* mywork->KKT->PK = (idxint *)MALLOC(KU->nnz*sizeof(idxint)); */ - freeSparseMatrix(w->KKT->PKPt); /* mywork->KKT->PKPt = newSparseMatrix(nK, nK, KU->nnz); */ + freeSparseMatrix(w->KKT->PKPt); /* mywork->KKT->PKPt = newSparseMatrix(nK, nK, KU->nnz); */ FREE(w->KKT->RHS1); /* mywork->KKT->RHS1 = (pfloat *)MALLOC(nK*sizeof(pfloat)); */ FREE(w->KKT->RHS2); /* mywork->KKT->RHS2 = (pfloat *)MALLOC(nK*sizeof(pfloat)); */ FREE(w->KKT->work1); /* mywork->KKT->work1 = (pfloat *)MALLOC(nK*sizeof(pfloat)); */ @@ -888,6 +888,7 @@ pwork* ECOS_setup(idxint n, idxint m, idxint p, idxint l, idxint ncones, idxint* /* allocate memory in KKT system */ mywork->KKT = (kkt *)MALLOC(sizeof(kkt)); mywork->KKT->D = (pfloat *)MALLOC(nK*sizeof(pfloat)); + mywork->KKT->Dinv = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->Parent = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->Pinv = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->work1 = (pfloat *)MALLOC(nK*sizeof(pfloat)); @@ -896,8 +897,8 @@ pwork* ECOS_setup(idxint n, idxint m, idxint p, idxint l, idxint ncones, idxint* mywork->KKT->work4 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->work5 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->work6 = (pfloat *)MALLOC(nK*sizeof(pfloat)); - mywork->KKT->Flag = (idxint *)MALLOC(nK*sizeof(idxint)); - mywork->KKT->Pattern = (idxint *)MALLOC(nK*sizeof(idxint)); + mywork->KKT->iwork = (idxint *)MALLOC(3*nK*sizeof(idxint)); + mywork->KKT->bwork = (ecos_bool *)MALLOC(nK*sizeof(ecos_bool)); mywork->KKT->Lnz = (idxint *)MALLOC(nK*sizeof(idxint)); mywork->KKT->RHS1 = (pfloat *)MALLOC(nK*sizeof(pfloat)); mywork->KKT->RHS2 = (pfloat *)MALLOC(nK*sizeof(pfloat)); @@ -974,19 +975,15 @@ pwork* ECOS_setup(idxint n, idxint m, idxint p, idxint l, idxint ncones, idxint* #if PRINTLEVEL > 2 PRINTTEXT("Allocated memory for cholesky factor L\n"); #endif - LDL_symbolic2( - mywork->KKT->PKPt->n, /* A and L are n-by-n, where n >= 0 */ - mywork->KKT->PKPt->jc, /* input of size n+1, not modified */ - mywork->KKT->PKPt->ir, /* input of size nz=Ap[n], not modified */ - Ljc, /* output of size n+1, not defined on input */ - mywork->KKT->Parent, /* output of size n, not defined on input */ - mywork->KKT->Lnz, /* output of size n, not defined on input */ - mywork->KKT->Flag /* workspace of size n, not defn. on input or output */ - ); - + lnz = QDLDL_etree( + mywork->KKT->PKPt->n, + mywork->KKT->PKPt->jc, + mywork->KKT->PKPt->ir, + mywork->KKT->iwork, + mywork->KKT->Lnz, + mywork->KKT->Parent + ); - /* assign memory for L */ - lnz = Ljc[nK]; #if PRINTLEVEL > 2 PRINTTEXT("Nonzeros in L, excluding diagonal: %d\n", (int)lnz) ; #endif diff --git a/test/exponential/log_ax_x.h b/test/exponential/log_ax_x.h index 65d7b818..60bf4c10 100644 --- a/test/exponential/log_ax_x.h +++ b/test/exponential/log_ax_x.h @@ -46,7 +46,7 @@ pfloat abs_err = fabs(true_x-ecos_x); ECOS_cleanup(mywork, 0); mu_assert("log_ax_x: ECOS failed to produce outputflag OPTIMAL", exitflag == ECOS_OPTIMAL ); -mu_assert("log_ax_x: ECOS failed to produce the desired precision", abs_err < 1e-11); +mu_assert("log_ax_x: ECOS failed to produce the desired precision", abs_err < 1.3e-11); return 0; } From 6ec1dacc6d6f9915e39fc7caeb485474ad8ced22 Mon Sep 17 00:00:00 2001 From: zach401 Date: Thu, 13 Jan 2022 10:34:15 -0800 Subject: [PATCH 02/12] Update CMakeLists and Makefile to use QDLDL. --- CMakeLists.txt | 151 ++++++++++++++++++++----------------------------- Makefile | 2 +- 2 files changed, 63 insertions(+), 90 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ef31a5f3..abd77400 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,18 +1,13 @@ # CMake configuration for ECOS - cmake_minimum_required(VERSION 3.5) - project(ecos VERSION 2.0.8 LANGUAGES C) - # Options option(USE_LONG "Whether to use Long or Int for index type." ON) - # Set compiler flags set(DEBUG_OPTIONS "") set(RELEASE_OPTIONS "") - if(MSVC) list(APPEND DEBUG_OPTIONS "/Od" "/Wall") list(APPEND RELEASE_OPTIONS "/O2") @@ -20,70 +15,58 @@ else() list(APPEND DEBUG_OPTIONS "-O0" "-Wall" "-Wextra") list(APPEND RELEASE_OPTIONS "-O3") endif() - # Add the ECOS headers set(ecos_headers - "${CMAKE_CURRENT_SOURCE_DIR}/external/SuiteSparse_config/SuiteSparse_config.h" - "${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl/configure/qdldl_types.h.in" - "${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl/configure/qdldl_version.h.in" - "${CMAKE_CURRENT_SOURCE_DIR}/include/cone.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/ctrlc.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/data.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos_bb.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/equil.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/expcone.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/glblopts.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/kkt.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/spla.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/splamm.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/timer.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/wright_omega.h" -) - + "${CMAKE_CURRENT_SOURCE_DIR}/external/SuiteSparse_config/SuiteSparse_config.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/cone.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/ctrlc.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/data.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos_bb.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/equil.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/expcone.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/glblopts.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/kkt.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/spla.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/splamm.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/timer.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/wright_omega.h" + ) set(ecos_sources - # AMD - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_1.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_2.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_aat.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_control.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_defaults.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_dump.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_global.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_info.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_order.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_post_tree.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_postorder.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_preprocess.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_valid.c" - - # LDL - "${CMAKE_CURRENT_SOURCE_DIR}/external/ldl/src/ldl.c" - - # QDLDL - "${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl/src/qdldl.c" - - # ECOS - "${CMAKE_CURRENT_SOURCE_DIR}/src/cone.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/ctrlc.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/ecos.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/equil.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/expcone.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/kkt.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/preproc.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/spla.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/splamm.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/timer.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/wright_omega.c" - - # ECOS BB - "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb.c" - "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb_preproc.c" -) - + # AMD + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_1.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_2.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_aat.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_control.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_defaults.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_dump.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_global.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_info.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_order.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_post_tree.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_postorder.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_preprocess.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_valid.c" + # ECOS + "${CMAKE_CURRENT_SOURCE_DIR}/src/cone.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ctrlc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ecos.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/equil.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/expcone.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/kkt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/preproc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/spla.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/splamm.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/timer.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/wright_omega.c" + # ECOS BB + "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb.c" + "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb_preproc.c" + ) +# QDLDL library +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl") # ECOS library add_library(ecos SHARED ${ecos_headers} ${ecos_sources}) - # Set compiler options and definitions target_compile_options(ecos PRIVATE "$<$:${DEBUG_OPTIONS}>") target_compile_options(ecos PRIVATE "$<$:${RELEASE_OPTIONS}>") @@ -91,53 +74,43 @@ target_compile_definitions(ecos PUBLIC CTRLC=1) if(USE_LONG) target_compile_definitions(ecos PUBLIC LDL_LONG DLONG) endif() - # Link math library if(NOT MSVC) target_link_libraries(ecos PRIVATE m) endif() - +# Link QDLDL library +target_link_libraries(ecos PUBLIC qdldl) target_include_directories(ecos - PUBLIC - "$" - "$" - "$" - "$" - "$" - "$/${CMAKE_INSTALL_INCLUDEDIR}/ecos>" -) - + PUBLIC + "$" + "$" + "$" + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}/ecos>" + ) # Installation include(GNUInstallDirs) - install(TARGETS ecos EXPORT ${PROJECT_NAME} ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" -) - + ) install(FILES ${ecos_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ecos") - # Create CMake packages for the build directory include(CMakePackageConfigHelpers) - export(EXPORT ${PROJECT_NAME} - FILE "${CMAKE_CURRENT_BINARY_DIR}/ecos-targets.cmake" - NAMESPACE ecos:: -) - + FILE "${CMAKE_CURRENT_BINARY_DIR}/ecos-targets.cmake" + NAMESPACE ecos:: + ) file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/ecos-config.cmake "include(\"\${CMAKE_CURRENT_LIST_DIR}/ecos-targets.cmake\")\n") - # Create CMake packages for the install directory set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/ecos) - install(EXPORT ${PROJECT_NAME} FILE ecos-targets.cmake NAMESPACE ecos:: DESTINATION ${ConfigPackageLocation} -) - + ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ecos-config.cmake DESTINATION ${ConfigPackageLocation} -) + ) \ No newline at end of file diff --git a/Makefile b/Makefile index 02dbe7bb..61d64f6f 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ test: ecostester ecos_bb_test ecostester: test/ecostester.c $(TEST_OBJS) libecos.a external/qdldl/build/out/libqdldl.a $(CC) $(CFLAGS) $(TEST_INCLUDES) -o $@ $^ $(LDFLAGS) -ecos_bb_test: test/bb_test.c libecos_bb.a +ecos_bb_test: test/bb_test.c libecos_bb.a external/qdldl/build/out/libqdldl.a $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) %.o: test/generated/%.c test/generated/%.h From ff4e893271d0ced3ac9d69f18fd693037518e143 Mon Sep 17 00:00:00 2001 From: zach401 Date: Thu, 13 Jan 2022 16:39:16 -0800 Subject: [PATCH 03/12] Update Makefile to remove LDL and include building QDLDL. --- Makefile | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 61d64f6f..eb153f17 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,8 @@ TEST_INCLUDES = -Itest -Itest/generated .PHONY: all all: libecos.a libecos_bb.a runecos runecosexp -# build Tim Davis' sparse LDL package -$(LDL): - ( cd external/ldl ; $(MAKE) ) - $(AR) -x external/ldl/libldl.a +external/qdldl/build/out/libqdldl.a: + ( mkdir external/qdldl/build ; cd external/qdldl/build ; cmake .. ; cmake --build . ;) # build Tim Davis' AMD package $(AMD): @@ -24,13 +22,13 @@ $(AMD): # build ECOS ECOS_OBJS = ecos.o kkt.o cone.o spla.o ctrlc.o timer.o preproc.o splamm.o equil.o expcone.o wright_omega.o -libecos.a: $(ECOS_OBJS) $(LDL) $(AMD) +libecos.a: $(ECOS_OBJS) $(AMD) external/qdldl/build/out/libqdldl.a $(ARCHIVE) $@ $^ - $(RANLIB) $@ # build ECOS branch-and-bound ECOS_BB_OBJS = $(ECOS_OBJS) ecos_bb_preproc.o ecos_bb.o -libecos_bb.a: $(ECOS_BB_OBJS) $(LDL) $(AMD) +libecos_bb.a: $(ECOS_BB_OBJS) $(AMD) external/qdldl/build/out/libqdldl.a $(ARCHIVE) $@ $^ - $(RANLIB) $@ @@ -58,18 +56,18 @@ wright_omega.o : include/wright_omega.h # ECOS demo .PHONY: demo demo: runecos -runecos: src/runecos.c libecos.a +runecos: src/runecos.c libecos.a external/qdldl/build/out/libqdldl.a $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) echo ECOS successfully built. Type ./runecos to run demo problem. -runecosexp: src/runecos_exp.c libecos.a +runecosexp: src/runecos_exp.c libecos.a external/qdldl/build/out/libqdldl.a $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) echo ECOS-Exp successfully built. Type ./runecosexp to run demo problem. # Shared library .PHONY: shared shared: $(SHAREDNAME) -$(SHAREDNAME): $(LDL) $(AMD) $(ECOS_OBJS) +$(SHAREDNAME): $(AMD) $(ECOS_OBJS) external/qdldl/build/out/libqdldl.a $(CC) $(CFLAGS) -shared -o $@ $^ $(LDFLAGS) # ECOS tester @@ -92,13 +90,12 @@ ecos_bb_test: test/bb_test.c libecos_bb.a external/qdldl/build/out/libqdldl.a # remove object files, but keep the compiled programs and library archives .PHONY: clean clean: - ( cd external/ldl ; $(MAKE) clean ) + ( cd external/qdldl/build ; $(MAKE) clean ) ( cd external/amd ; $(MAKE) clean ) - $(RM) $(CLEAN) # clean, and then remove compiled programs and library archives .PHONY: purge purge: clean - ( cd external/ldl ; $(MAKE) purge ) ( cd external/amd ; $(MAKE) purge ) - $(RM) libecos.a libecos_bb.a runecos runecosexp From ac9eb74b22a2b2031d3b46a150b62dede1ac8e11 Mon Sep 17 00:00:00 2001 From: zach401 Date: Thu, 13 Jan 2022 16:45:52 -0800 Subject: [PATCH 04/12] Update kkt_factor function to not return KKT_PROBLEM for n=0 matrix. --- src/kkt.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/kkt.c b/src/kkt.c index 267f3b9c..195dc753 100644 --- a/src/kkt.c +++ b/src/kkt.c @@ -41,8 +41,10 @@ idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta, pfloat *t1, pfloat* t2) idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta) #endif { - idxint nd; + /* If problem has size zero, there is nothing to factor */ + if (KKT->PKPt->n == 0){ return KKT_OK; } + idxint nd; nd = QDLDL_factor( KKT->PKPt->n, /* K and L are n-by-n, where n >= 0 */ KKT->PKPt->jc, /* input of size n+1, not modified */ @@ -60,7 +62,7 @@ idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta) KKT->work1 /* workspace of size n, not defined on input or output */ ); /* Negative return values indicate problems factoring the matrix */ - return nd > 0 ? KKT_OK : KKT_PROBLEM; + return nd >= 0 ? KKT_OK : KKT_PROBLEM; } From af16377dddddc92050813d7c51eca76bf1e4dcb9 Mon Sep 17 00:00:00 2001 From: zach401 Date: Thu, 13 Jan 2022 17:29:36 -0800 Subject: [PATCH 05/12] Remove unused arguments from kkt_factor function. This includes removing tfactor_t1 and tfactor_t2, which are not provided by QDLDL. --- include/ecos.h | 2 -- include/kkt.h | 15 +++------------ src/ecos.c | 8 ++++---- src/kkt.c | 6 +----- src/preproc.c | 2 -- 5 files changed, 8 insertions(+), 25 deletions(-) diff --git a/include/ecos.h b/include/ecos.h index 8c0385c6..de468fe5 100644 --- a/include/ecos.h +++ b/include/ecos.h @@ -149,8 +149,6 @@ typedef struct stats{ pfloat tkktcreate; pfloat ttranspose; pfloat tperm; - pfloat tfactor_t1; - pfloat tfactor_t2; #endif #ifdef EXPCONE /* Counters for backtracking, each of these counts diff --git a/include/kkt.h b/include/kkt.h index 6de044de..d1644f76 100644 --- a/include/kkt.h +++ b/include/kkt.h @@ -73,19 +73,10 @@ typedef struct kkt{ /* METHODS */ -/** - * Factorization of KKT matrix. Just a convenient wrapper for the LDL call. - * The second argument delta determindes the threshold of dynamic regularization, - * while the last argument is the regularization parameter if it becomes active. - * - * If detailed profiling is turned on, the function returns the accumulated times - * for sparsity pattern computation in t1 and for numerical solve in t2. +/** + * Factorization of KKT matrix. Just a convenient wrapper for the QDLDL call. */ -#if PROFILING > 1 -idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta, pfloat *t1, pfloat *t2); -#else -idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta); -#endif +idxint kkt_factor(kkt* KKT); /** diff --git a/src/ecos.c b/src/ecos.c index e5e321d4..b332f246 100644 --- a/src/ecos.c +++ b/src/ecos.c @@ -320,10 +320,10 @@ idxint init(pwork* w) /* Factor KKT matrix - this is needed in all 3 linear system solves */ #if PROFILING > 1 tic(&tfactor); - KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta, &w->info->tfactor_t1, &w->info->tfactor_t2); + KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT); w->info->tfactor += toc(&tfactor); #else - KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta); + KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT); #endif /* check if factorization was successful, exit otherwise */ @@ -1322,10 +1322,10 @@ idxint ECOS_solve(pwork* w) /* factor KKT matrix */ #if PROFILING > 1 tic(&tfactor); - KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta, &w->info->tfactor_t1, &w->info->tfactor_t2); + KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT); w->info->tfactor += toc(&tfactor); #else - KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT, w->stgs->eps, w->stgs->delta); + KKT_FACTOR_RETURN_CODE = kkt_factor(w->KKT); #endif #if DEBUG > 0 diff --git a/src/kkt.c b/src/kkt.c index 195dc753..1b136da6 100644 --- a/src/kkt.c +++ b/src/kkt.c @@ -35,11 +35,7 @@ #include /* Factorization of KKT matrix. Just a wrapper for some LDL code */ -#if PROFILING > 1 -idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta, pfloat *t1, pfloat* t2) -#else -idxint kkt_factor(kkt* KKT, pfloat eps, pfloat delta) -#endif +idxint kkt_factor(kkt* KKT) { /* If problem has size zero, there is nothing to factor */ if (KKT->PKPt->n == 0){ return KKT_OK; } diff --git a/src/preproc.c b/src/preproc.c index 838d874c..9fa7b51a 100644 --- a/src/preproc.c +++ b/src/preproc.c @@ -739,8 +739,6 @@ pwork* ECOS_setup(idxint n, idxint m, idxint p, idxint l, idxint ncones, idxint* #if PROFILING > 1 mywork->info->tfactor = 0; mywork->info->tkktsolve = 0; - mywork->info->tfactor_t1 = 0; - mywork->info->tfactor_t2 = 0; #endif #if PRINTLEVEL > 2 PRINTTEXT("Memory allocated for info struct\n"); From a4338de90daa96da2ebd3e6f2e1d1e5497c66a55 Mon Sep 17 00:00:00 2001 From: zach401 Date: Fri, 14 Jan 2022 08:20:59 -0800 Subject: [PATCH 06/12] Remove LDL from repository. --- external/ldl/Makefile | 28 --- external/ldl/README.txt | 138 ------------ external/ldl/include/ldl.h | 98 --------- external/ldl/src/ldl.c | 441 ------------------------------------- 4 files changed, 705 deletions(-) delete mode 100644 external/ldl/Makefile delete mode 100644 external/ldl/README.txt delete mode 100644 external/ldl/include/ldl.h delete mode 100644 external/ldl/src/ldl.c diff --git a/external/ldl/Makefile b/external/ldl/Makefile deleted file mode 100644 index 72a5ec25..00000000 --- a/external/ldl/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -#------------------------------------------------------------------------------- -# Makefile for the LDL library -#------------------------------------------------------------------------------- - -default: all - -include ../../ecos.mk - -INCLUDES = -I../SuiteSparse_config -Iinclude - -C = $(CC) $(CFLAGS) $(INCLUDES) - -all: libldl.a - -#------------------------------------------------------------------------------- -# the ldl library: -#------------------------------------------------------------------------------- - -libldl.a: src/ldl.c include/ldl.h ../../include/glblopts.h ../../include/ecos.h - $(C) -c src/ldl.c -o ldl.o - $(C) -DLDL_LONG -c src/ldl.c -o ldll.o - $(ARCHIVE) libldl.a ldl.o ldll.o - - $(RANLIB) libldl.a - -purge: - - $(RM) libldl.a -clean: - - $(RM) $(CLEAN) diff --git a/external/ldl/README.txt b/external/ldl/README.txt deleted file mode 100644 index 0fc44768..00000000 --- a/external/ldl/README.txt +++ /dev/null @@ -1,138 +0,0 @@ -LDL Copyright (c) 2005-2012 by Timothy A. Davis. http://www.suitesparse.com - -LDL: a sparse LDL' factorization and solve package. - Written in C, with both a C and MATLAB mexFunction interface. - -These routines are not terrifically fast (they do not use dense matrix kernels), -but the code is very short and concise. The purpose is to illustrate the -algorithms in a very concise and readable manner, primarily for educational -purposes. Although the code is very concise, this package is slightly faster -than the built-in sparse Cholesky factorization in MATLAB 6.5 (chol), when -using the same input permutation. - -Requires SuiteSparse_config, in the ../SuiteSparse_config directory relative to -this directory. - -Quick start (Unix, or Windows with Cygwin): - - To compile, test, and install LDL, you may wish to first obtain a copy of - AMD v2.0 from http://www.suitesparse.com and place it in the - ../AMD directory, relative to this directory. Next, type "make", which - will compile the LDL library and three demo main programs (one of which - requires AMD). It will also compile the LDL MATLAB mexFunction (if you - have MATLAB). Typing "make clean" will remove non-essential files. - AMD v2.0 or later is required. Its use is optional. - -Quick start (for MATLAB users); - - To compile, test, and install the LDL mexFunctions (ldlsparse and - ldlsymbol), start MATLAB in this directory and type ldl_install. - This works on any system supported by MATLAB. - --------------------------------------------------------------------------------- - - -LDL License: - - Your use or distribution of LDL or any modified version of - LDL implies that you agree to this License. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 - USA - - Permission is hereby granted to use or copy this program under the - terms of the GNU LGPL, provided that the Copyright, this License, - and the Availability of the original version is retained on all copies. - User documentation of any code that uses this code or any modified - version of this code must cite the Copyright, this License, the - Availability note, and "Used by permission." Permission to modify - the code and to distribute modified code is granted, provided the - Copyright, this License, and the Availability note are retained, - and a notice that the code was modified is included. - -Availability: - - http://www.suitesparse.com - -Acknowledgements: - - This work was supported by the National Science Foundation, under - grant CCR-0203270. - - Portions of this work were done while on sabbatical at Stanford University - and Lawrence Berkeley National Laboratory (with funding from the SciDAC - program). I would like to thank Gene Golub, Esmond Ng, and Horst Simon - for making this sabbatical possible. I would like to thank Pete Stewart - for his comments on a draft of this software and paper. - --------------------------------------------------------------------------------- -Files and directories in this distribution: --------------------------------------------------------------------------------- - - Documentation, and compiling: - - README.txt this file - Makefile for compiling LDL - ChangeLog changes since V1.0 (Dec 31, 2003) - License license - lesser.txt the GNU LGPL license - - ldl_userguide.pdf user guide in PDF - ldl_userguide.ps user guide in postscript - ldl_userguide.tex user guide in Latex - ldl.bib bibliography for user guide - - The LDL library itself: - - ldl.c the C-callable routines - ldl.h include file for any code that calls LDL - - A simple C main program that demonstrates how to use LDL: - - ldlsimple.c a stand-alone C program, uses the basic features of LDL - ldlsimple.out output of ldlsimple - - ldllsimple.c long integer version of ldlsimple.c - - Demo C program, for testing LDL and providing an example of its use - - ldlmain.c a stand-alone C main program that uses and tests LDL - Matrix a directory containing matrices used by ldlmain.c - ldlmain.out output of ldlmain - ldlamd.out output of ldlamd (ldlmain.c compiled with AMD) - ldllamd.out output of ldllamd (ldlmain.c compiled with AMD, long) - - MATLAB-related, not required for use in a regular C program - - Contents.m a list of the MATLAB-callable routines - ldl.m MATLAB help file for the LDL mexFunction - ldldemo.m MATLAB demo of how to use the LDL mexFunction - ldldemo.out diary output of ldldemo - ldltest.m to test the LDL mexFunction - ldltest.out diary output of ldltest - ldlmex.c the LDL mexFunction for MATLAB - ldlrow.m the numerical algorithm that LDL is based on - ldlmain2.m compiles and runs ldlmain.c as a MATLAB mexFunction - ldlmain2.out output of ldlmain2.m - ldlsymbolmex.c symbolic factorization using LDL (see SYMBFACT, ETREE) - ldlsymbol.m help file for the LDLSYMBOL mexFunction - - ldl_install.m compile, install, and test LDL functions - ldl_make.m compile LDL (ldlsparse and ldlsymbol) - - ldlsparse.m help for ldlsparse - -See ldl.c for a description of how to use the code from a C program. Type -"help ldl" in MATLAB for information on how to use LDL in a MATLAB program. diff --git a/external/ldl/include/ldl.h b/external/ldl/include/ldl.h deleted file mode 100644 index e468818f..00000000 --- a/external/ldl/include/ldl.h +++ /dev/null @@ -1,98 +0,0 @@ -/* ========================================================================== */ -/* === ldl.h: include file for the LDL package ============================= */ -/* ========================================================================== */ - -/* Copyright (c) Timothy A Davis, http://www.suitesparse.com. - * All Rights Reserved. See README for the License. - * - * Stripped down by Alexander Domahidi, 2012. - */ - -#include "../../include/glblopts.h" -#include "../../include/ecos.h" - -#include "SuiteSparse_config.h" - -#ifdef LDL_LONG -#define LDL_int SuiteSparse_long -#define LDL_ID SuiteSparse_long_id - -#define LDL_symbolic2 ldl_l_symbolic2 -#define LDL_numeric2 ldl_l_numeric2 -#define LDL_lsolve ldl_l_lsolve -#define LDL_lsolve2 ldl_l_lsolve2 -#define LDL_dsolve ldl_l_dsolve -#define LDL_ltsolve ldl_l_ltsolve - -#else -#define LDL_int int -#define LDL_ID "%d" - -#define LDL_symbolic2 ldl_symbolic2 -#define LDL_numeric2 ldl_numeric2 -#define LDL_lsolve ldl_lsolve -#define LDL_lsolve2 ldl_lsolve2 -#define LDL_dsolve ldl_dsolve -#define LDL_ltsolve ldl_ltsolve - -#endif - -/* ========================================================================== */ -/* === int version ========================================================== */ -/* ========================================================================== */ - -void ldl_symbolic2 (int n, int Ap [ ], int Ai [ ], int Lp [ ], int Parent [ ], int Lnz [ ], int Flag [ ]) ; - -int ldl_numeric2 (int n, int Ap [ ], int Ai [ ], double Ax [ ], - int Lp [ ], int Parent [ ], int Sign[], double eps, double delta, int Lnz [ ], int Li [ ], double Lx [ ], - double D [ ], double Y [ ], int Pattern [ ], int Flag [ ] -#if PROFILING > 1 - ,double *t1, double *t2 -#endif - ) ; - -void ldl_lsolve (int n, double B [], int Lp [ ], int Li [ ], double Lx [ ]) ; -void ldl_lsolve2 (int n, double B [], int Lp [ ], int Li [ ], double Lx [ ], double X [ ]) ; - -void ldl_dsolve (int n, double X [ ], double D [ ]) ; - -void ldl_ltsolve (int n, double X [ ], int Lp [ ], int Li [ ], - double Lx [ ]) ; - -/* ========================================================================== */ -/* === long version ========================================================= */ -/* ========================================================================== */ - -void ldl_l_symbolic2 (SuiteSparse_long n, SuiteSparse_long Ap [ ], - SuiteSparse_long Ai [ ], SuiteSparse_long Lp [ ], - SuiteSparse_long Parent [ ], SuiteSparse_long Lnz [ ], - SuiteSparse_long Flag [ ]); - -SuiteSparse_long ldl_l_numeric2 (SuiteSparse_long n, SuiteSparse_long Ap [ ], - SuiteSparse_long Ai [ ], double Ax [ ], SuiteSparse_long Lp [ ], - SuiteSparse_long Parent [ ], SuiteSparse_long Sign [ ], double eps, double delta, SuiteSparse_long Lnz [ ], - SuiteSparse_long Li [ ], double Lx [ ], double D [ ], double Y [ ], - SuiteSparse_long Pattern [ ], SuiteSparse_long Flag [ ] -#if PROFILING > 1 - ,double *t1, double *t2 -#endif - ) ; - -void ldl_l_lsolve (SuiteSparse_long n, double B [ ], SuiteSparse_long Lp [ ], SuiteSparse_long Li [ ], double Lx [ ]) ; -void ldl_l_lsolve2 (SuiteSparse_long n, double B [ ], SuiteSparse_long Lp [ ], SuiteSparse_long Li [ ], double Lx [ ], double X [ ]) ; - -void ldl_l_dsolve (SuiteSparse_long n, double X [ ], double D [ ]) ; - -void ldl_l_ltsolve (SuiteSparse_long n, double X [ ], SuiteSparse_long Lp [ ], - SuiteSparse_long Li [ ], double Lx [ ]) ; - -/* ========================================================================== */ -/* === LDL version ========================================================== */ -/* ========================================================================== */ - -#define LDL_DATE "April 6, 2013, with dynamic regularization by A. Domahidi" -#define LDL_VERSION_CODE(main,sub) ((main) * 1000 + (sub)) -#define LDL_MAIN_VERSION 2 -#define LDL_SUB_VERSION 1 -#define LDL_SUBSUB_VERSION 0 -#define LDL_VERSION LDL_VERSION_CODE(LDL_MAIN_VERSION,LDL_SUB_VERSION) diff --git a/external/ldl/src/ldl.c b/external/ldl/src/ldl.c deleted file mode 100644 index 274515dc..00000000 --- a/external/ldl/src/ldl.c +++ /dev/null @@ -1,441 +0,0 @@ -/* ========================================================================== */ -/* === ldl.c: sparse LDL' factorization and solve package =================== */ -/* ========================================================================== */ - -/* LDL: a simple set of routines for sparse LDL' factorization. These routines - * are not terrifically fast (they do not use dense matrix kernels), but the - * code is very short. The purpose is to illustrate the algorithms in a very - * concise manner, primarily for educational purposes. Although the code is - * very concise, this package is slightly faster than the built-in sparse - * Cholesky factorization in MATLAB 7.0 (chol), when using the same input - * permutation. - * - * The routines compute the LDL' factorization of a real sparse symmetric - * matrix A (or PAP' if a permutation P is supplied), and solve upper - * and lower triangular systems with the resulting L and D factors. If A is - * positive definite then the factorization will be accurate. A can be - * indefinite (with negative values on the diagonal D), but in this case no - * guarantee of accuracy is provided, since no numeric pivoting is performed. - * - * The n-by-n sparse matrix A is in compressed-column form. The nonzero values - * in column j are stored in Ax [Ap [j] ... Ap [j+1]-1], with corresponding row - * indices in Ai [Ap [j] ... Ap [j+1]-1]. Ap [0] = 0 is required, and thus - * nz = Ap [n] is the number of nonzeros in A. Ap is an int array of size n+1. - * The int array Ai and the double array Ax are of size nz. This data structure - * is identical to the one used by MATLAB, except for the following - * generalizations. The row indices in each column of A need not be in any - * particular order, although they must be in the range 0 to n-1. Duplicate - * entries can be present; any duplicates are summed. That is, if row index i - * appears twice in a column j, then the value of A (i,j) is the sum of the two - * entries. The data structure used here for the input matrix A is more - * flexible than MATLAB's, which requires sorted columns with no duplicate - * entries. - * - * Only the diagonal and upper triangular part of A (or PAP' if a permutation - * P is provided) is accessed. The lower triangular parts of the matrix A or - * PAP' can be present, but they are ignored. - * - * The optional input permutation is provided as an array P of length n. If - * P [k] = j, the row and column j of A is the kth row and column of PAP'. - * If P is present then the factorization is LDL' = PAP' or L*D*L' = A(P,P) in - * 0-based MATLAB notation. If P is not present (a null pointer) then no - * permutation is performed, and the factorization is LDL' = A. - * - * The lower triangular matrix L is stored in the same compressed-column - * form (an int Lp array of size n+1, an int Li array of size Lp [n], and a - * double array Lx of the same size as Li). It has a unit diagonal, which is - * not stored. The row indices in each column of L are always returned in - * ascending order, with no duplicate entries. This format is compatible with - * MATLAB, except that it would be more convenient for MATLAB to include the - * unit diagonal of L. Doing so here would add additional complexity to the - * code, and is thus omitted in the interest of keeping this code short and - * readable. - * - * The elimination tree is held in the Parent [0..n-1] array. It is normally - * not required by the user, but it is required by ldl_numeric. The diagonal - * matrix D is held as an array D [0..n-1] of size n. - * - * -------------------- - * C-callable routines: - * -------------------- - * - * ldl_symbolic: Given the pattern of A, computes the Lp and Parent arrays - * required by ldl_numeric. Takes time proportional to the number of - * nonzeros in L. Computes the inverse Pinv of P if P is provided. - * Also returns Lnz, the count of nonzeros in each column of L below - * the diagonal (this is not required by ldl_numeric). - * ldl_numeric: Given the pattern and numerical values of A, the Lp array, - * the Parent array, and P and Pinv if applicable, computes the - * pattern and numerical values of L and D. - * ldl_lsolve: Solves Lx=b for a dense vector b. - * ldl_dsolve: Solves Dx=b for a dense vector b. - * ldl_ltsolve: Solves L'x=b for a dense vector b. - * ldl_perm: Computes x=Pb for a dense vector b. - * ldl_permt: Computes x=P'b for a dense vector b. - * ldl_valid_perm: checks the validity of a permutation vector - * ldl_valid_matrix: checks the validity of the sparse matrix A - * - * ---------------------------- - * Limitations of this package: - * ---------------------------- - * - * In the interest of keeping this code simple and readable, ldl_symbolic and - * ldl_numeric assume their inputs are valid. You can check your own inputs - * prior to calling these routines with the ldl_valid_perm and ldl_valid_matrix - * routines. Except for the two ldl_valid_* routines, no routine checks to see - * if the array arguments are present (non-NULL). Like all C routines, no - * routine can determine if the arrays are long enough and don't overlap. - * - * The ldl_numeric does check the numerical factorization, however. It returns - * n if the factorization is successful. If D (k,k) is zero, then k is - * returned, and L is only partially computed. - * - * No pivoting to control fill-in is performed, which is often critical for - * obtaining good performance. I recommend that you compute the permutation P - * using AMD or SYMAMD (approximate minimum degree ordering routines), or an - * appropriate graph-partitioning based ordering. See the ldldemo.m routine for - * an example in MATLAB, and the ldlmain.c stand-alone C program for examples of - * how to find P. Routines for manipulating compressed-column matrices are - * available in UMFPACK. AMD, SYMAMD, UMFPACK, and this LDL package are all - * available at http://www.suitesparse.com. - * - * ------------------------- - * Possible simplifications: - * ------------------------- - * - * These routines could be made even simpler with a few additional assumptions. - * If no input permutation were performed, the caller would have to permute the - * matrix first, but the computation of Pinv, and the use of P and Pinv could be - * removed. If only the diagonal and upper triangular part of A or PAP' are - * present, then the tests in the "if (i < k)" statement in ldl_symbolic and - * "if (i <= k)" in ldl_numeric, are always true, and could be removed (i can - * equal k in ldl_symbolic, but then the body of the if statement would - * correctly do no work since Flag [k] == k). If we could assume that no - * duplicate entries are present, then the statement Y [i] += Ax [p] could be - * replaced with Y [i] = Ax [p] in ldl_numeric. - * - * -------------------------- - * Description of the method: - * -------------------------- - * - * LDL computes the symbolic factorization by finding the pattern of L one row - * at a time. It does this based on the following theory. Consider a sparse - * system Lx=b, where L, x, and b, are all sparse, and where L comes from a - * Cholesky (or LDL') factorization. The elimination tree (etree) of L is - * defined as follows. The parent of node j is the smallest k > j such that - * L (k,j) is nonzero. Node j has no parent if column j of L is completely zero - * below the diagonal (j is a root of the etree in this case). The nonzero - * pattern of x is the union of the paths from each node i to the root, for - * each nonzero b (i). To compute the numerical solution to Lx=b, we can - * traverse the columns of L corresponding to nonzero values of x. This - * traversal does not need to be done in the order 0 to n-1. It can be done in - * any "topological" order, such that x (i) is computed before x (j) if i is a - * descendant of j in the elimination tree. - * - * The row-form of the LDL' factorization is shown in the MATLAB function - * ldlrow.m in this LDL package. Note that row k of L is found via a sparse - * triangular solve of L (1:k-1, 1:k-1) \ A (1:k-1, k), to use 1-based MATLAB - * notation. Thus, we can start with the nonzero pattern of the kth column of - * A (above the diagonal), follow the paths up to the root of the etree of the - * (k-1)-by-(k-1) leading submatrix of L, and obtain the pattern of the kth row - * of L. Note that we only need the leading (k-1)-by-(k-1) submatrix of L to - * do this. The elimination tree can be constructed as we go. - * - * The symbolic factorization does the same thing, except that it discards the - * pattern of L as it is computed. It simply counts the number of nonzeros in - * each column of L and then constructs the Lp index array when it's done. The - * symbolic factorization does not need to do this in topological order. - * Compare ldl_symbolic with the first part of ldl_numeric, and note that the - * while (len > 0) loop is not present in ldl_symbolic. - * - * Copyright (c) 2006 by Timothy A Davis, http://www.suitesparse.com. - * All Rights Reserved. Developed while on sabbatical - * at Stanford University and Lawrence Berkeley National Laboratory. Refer to - * the README file for the License. - */ - -#include "ldl.h" - -#include "../../include/glblopts.h" -#include "../../include/ecos.h" - - -/* ========================================================================== */ -/* === ldl_symbolic2 ======================================================== */ -/* ========================================================================== */ - -/* The input to this routine is a sparse matrix A, stored in column form, and - * an optional permutation P. The output is the elimination tree - * and the number of nonzeros in each column of L. Parent [i] = k if k is the - * parent of i in the tree. The Parent array is required by ldl_numeric. - * Lnz [k] gives the number of nonzeros in the kth column of L, excluding the - * diagonal. - * - * One workspace vector (Flag) of size n is required. - * - * If P is NULL, then it is ignored. The factorization will be LDL' = A. - * Pinv is not computed. In this case, neither P nor Pinv are required by - * ldl_numeric. - * - * If P is not NULL, then it is assumed to be a valid permutation. If - * row and column j of A is the kth pivot, the P [k] = j. The factorization - * will be LDL' = PAP', or A (p,p) in MATLAB notation. The inverse permutation - * Pinv is computed, where Pinv [j] = k if P [k] = j. In this case, both P - * and Pinv are required as inputs to ldl_numeric. - * - * The floating-point operation count of the subsequent call to ldl_numeric - * is not returned, but could be computed after ldl_symbolic is done. It is - * the sum of (Lnz [k]) * (Lnz [k] + 2) for k = 0 to n-1. - * - * This is essentially ldl_symbolic, but with the following simplifications - * implemented (as stated above) by A. Domahidi: - * - * These routines could be made even simpler with a few additional assumptions. - * If no input permutation were performed, the caller would have to permute the - * matrix first, but the computation of Pinv, and the use of P and Pinv could be - * removed. If only the diagonal and upper triangular part of A or PAP' are - * present, then the tests in the "if (i < k)" statement in ldl_symbolic and - * "if (i <= k)" in ldl_numeric, are always true, and could be removed (i can - * equal k in ldl_symbolic, but then the body of the if statement would - * correctly do no work since Flag [k] == k). - */ - -void LDL_symbolic2 -( - LDL_int n, /* A and L are n-by-n, where n >= 0 */ - LDL_int Ap [ ], /* input of size n+1, not modified */ - LDL_int Ai [ ], /* input of size nz=Ap[n], not modified */ - LDL_int Lp [ ], /* output of size n+1, not defined on input */ - LDL_int Parent [ ], /* output of size n, not defined on input */ - LDL_int Lnz [ ], /* output of size n, not defined on input */ - LDL_int Flag [ ] /* workspace of size n, not defn. on input or output */ -) -{ - LDL_int i, k, p, p2 ; - - for (k = 0 ; k < n ; k++){ - /* L(k,:) pattern: all nodes reachable in etree from nz in A(0:k-1,k) */ - Parent [k] = -1 ; /* parent of k is not yet known */ - Flag [k] = k ; /* mark node k as visited */ - Lnz [k] = 0 ; /* count of nonzeros in column k of L */ - p2 = Ap [k+1] ; - for (p = Ap [k] ; p < p2 ; p++) { - /* A (i,k) is nonzero (original or permuted A) */ - i = Ai [p]; - - /* follow path from i to root of etree, stop at flagged node */ - for ( ; Flag [i] != k ; i = Parent [i]){ - /* find parent of i if not yet determined */ - if (Parent [i] == -1) Parent [i] = k ; - Lnz [i]++ ; /* L (k,i) is nonzero */ - Flag [i] = k ; /* mark i as visited */ - } - } - } - - /* construct Lp index array from Lnz column counts */ - Lp [0] = 0 ; - for (k = 0 ; k < n ; k++){ - Lp [k+1] = Lp [k] + Lnz [k] ; - } -} - -/* ========================================================================== */ -/* === ldl_numeric2 ========================================================== */ -/* ========================================================================== */ - -/* Given a sparse matrix A (the arguments n, Ap, Ai, and Ax) and its symbolic - * analysis (Lp and Parent, and optionally P and Pinv), compute the numeric LDL' - * factorization of A or PAP'. The outputs of this routine are arguments Li, - * Lx, and D. It also requires three size-n workspaces (Y, Pattern, and Flag). - * - * This is essentially ldl_numeric, but with the following simplifications - * implemented (as stated above) by A. Domahidi: - * - * These routines could be made even simpler with a few additional assumptions. - * If no input permutation were performed, the caller would have to permute the - * matrix first, but the computation of Pinv, and the use of P and Pinv could be - * removed. If only the diagonal and upper triangular part of A or PAP' are - * present, then the tests in the "if (i < k)" statement in ldl_symbolic and - * "if (i <= k)" in ldl_numeric, are always true, and could be removed (i can - * equal k in ldl_symbolic, but then the body of the if statement would - * correctly do no work since Flag [k] == k). If we could assume that no - * duplicate entries are present, then the statement Y [i] += Ax [p] could be - * replaced with Y [i] = Ax [p] in ldl_numeric. - */ -LDL_int LDL_numeric2 /* returns n if successful, k if D (k,k) is zero */ -( - LDL_int n, /* A and L are n-by-n, where n >= 0 */ - LDL_int Ap [ ], /* input of size n+1, not modified */ - LDL_int Ai [ ], /* input of size nz=Ap[n], not modified */ - double Ax [ ], /* input of size nz=Ap[n], not modified */ - LDL_int Lp [ ], /* input of size n+1, not modified */ - LDL_int Parent [ ], /* input of size n, not modified */ - LDL_int Sign[ ], /* input of size n, sign vector of diagonal entries for regularization */ - double eps, /* input, regularization threshold */ - double delta, /* input, regularization parameter */ - LDL_int Lnz [ ], /* output of size n, not defn. on input */ - LDL_int Li [ ], /* output of size lnz=Lp[n], not defined on input */ - double Lx [ ], /* output of size lnz=Lp[n], not defined on input */ - double D [ ], /* output of size n, not defined on input */ - double Y [ ], /* workspace of size n, not defn. on input or output */ - LDL_int Pattern [ ], /* workspace of size n, not defn. on input or output */ - LDL_int Flag [ ] /* workspace of size n, not defn. on input or output */ -#if PROFILING > 1 - ,double *t1, /* time for non-zero pattern computation */ - double *t2 /* time for back-solves */ -#endif -) -{ - double yi, l_ki; - LDL_int i, k, p, p2, len, top; - -#if PROFILING > 1 - timer clock; -#endif - - /* go row-wise about this */ - for (k = 0 ; k < n ; k++){ - -#if PROFILING > 1 - tic(&clock); -#endif - /* compute nonzero Pattern of kth row of L, in topological order */ - Y [k] = 0.0 ; /* Y(0:k) is now all zero */ - top = n ; /* stack for pattern is empty */ - Flag [k] = k ; /* mark node k as visited */ - Lnz [k] = 0 ; /* count of nonzeros in column k of L */ - p2 = Ap [k+1] ; - for (p = Ap [k] ; p < p2 ; p++){ - i = Ai [p]; /* get A(i,k) */ - Y [i] = Ax [p] ; - for (len = 0 ; Flag [i] != k ; i = Parent [i]){ - Pattern [len++] = i ; /* L(k,i) is nonzero */ - Flag [i] = k ; /* mark i as visited */ - } - while (len > 0) Pattern [--top] = Pattern [--len] ; - } -#if PROFILING > 1 - *t1 += toc(&clock); - tic(&clock); -#endif - /* compute numerical values kth row of L (a sparse triangular solve) */ - D [k] = Y [k] ; /* get D(k,k) and clear Y(k) */ - Y [k] = 0.0 ; - for ( ; top < n ; top++){ - i = Pattern [top] ; /* Pattern [top:n-1] is pattern of L(:,k) */ - yi = Y [i] ; /* get and clear Y(i) */ - Y [i] = 0.0 ; - p2 = Lp [i] + Lnz [i] ; - for (p = Lp [i] ; p < p2 ; p++){ - Y [Li [p]] -= Lx [p] * yi ; - } - l_ki = yi / D [i] ; /* the nonzero entry L(k,i) */ - D [k] -= l_ki * yi ; - Li [p] = k ; /* store L(k,i) in column form of L */ - Lx [p] = l_ki ; - Lnz [i]++ ; /* increment count of nonzeros in col i */ - } - - /* Dynamic regularization */ - D[k] = Sign[k]*D[k] <= eps ? Sign[k]*delta : D[k]; - -#if PROFILING > 1 - *t2 += toc(&clock); -#endif - /* FOR DEBUG - if( Sign[k]*D[k] <= eps ) - { - PRINTTEXT( "Sign[%d]=%d, D[%d] = %6.4e, regularizing to %4.2e\n", (int)k, (int)Sign[k], (int)k, D[k], Sign[k]*delta); - D[k] = Sign[k]*delta; - } - */ - } - return (n) ; /* success, diagonal of D is all nonzero */ -} - - -/* ========================================================================== */ -/* === ldl_lsolve: solve Lx=b ============================================== */ -/* ========================================================================== */ - -void LDL_lsolve -( - LDL_int n, /* L is n-by-n, where n >= 0 */ - double X [ ], /* size n. right-hand-side on input, soln. on output */ - LDL_int Lp [ ], /* input of size n+1, not modified */ - LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */ - double Lx [ ] /* input of size lnz=Lp[n], not modified */ -){ - LDL_int j, p, p2 ; - for (j = 0 ; j < n ; j++){ - p2 = Lp [j+1] ; - for (p = Lp [j] ; p < p2 ; p++){ - X [Li [p]] -= Lx [p] * X [j] ; - } - } -} - -/* MODIFIED BY ALEXANDER DOMAHIDI */ -/* ========================================================================== */ -/* === ldl_lsolve2: solve Lx=b ============================================= */ -/* ========================================================================== */ - -void LDL_lsolve2 -( - LDL_int n, /* L is n-by-n, where n >= 0 */ - double b [ ], /* size n. input. right-hand-side */ - LDL_int Lp [ ], /* input of size n+1, not modified */ - LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */ - double Lx [ ], /* input of size lnz=Lp[n], not modified */ - double x [ ] /* size n. output. solution to Lx=b */ -) -{ - LDL_int j, p, p2 ; - for( j=0; j < n; j++ ){ x[j] = b[j]; } - for (j = 0 ; j < n ; j++){ - p2 = Lp [j+1] ; - for (p = Lp [j] ; p < p2 ; p++){ - x [Li [p]] -= Lx [p] * x [j]; - } - } -} - - -/* ========================================================================== */ -/* === ldl_dsolve: solve Dx=b ============================================== */ -/* ========================================================================== */ - -void LDL_dsolve -( - LDL_int n, /* D is n-by-n, where n >= 0 */ - double X [ ], /* size n. right-hand-side on input, soln. on output */ - double D [ ] /* input of size n, not modified */ -) -{ - LDL_int j ; - for (j = 0 ; j < n ; j++){ X [j] /= D [j]; } -} - - -/* ========================================================================== */ -/* === ldl_ltsolve: solve L'x=b ============================================ */ -/* ========================================================================== */ - -void LDL_ltsolve -( - LDL_int n, /* L is n-by-n, where n >= 0 */ - double X [ ], /* size n. right-hand-side on input, soln. on output */ - LDL_int Lp [ ], /* input of size n+1, not modified */ - LDL_int Li [ ], /* input of size lnz=Lp[n], not modified */ - double Lx [ ] /* input of size lnz=Lp[n], not modified */ -) -{ - LDL_int j, p, p2 ; - for (j = n-1 ; j >= 0 ; j--){ - p2 = Lp [j+1] ; - for (p = Lp [j] ; p < p2 ; p++){ - X [j] -= Lx [p] * X [Li [p]] ; - } - } -} From caaa5b45b2c2f58e00721caf3beea2b4acb8efa6 Mon Sep 17 00:00:00 2001 From: zach401 Date: Fri, 14 Jan 2022 08:46:41 -0800 Subject: [PATCH 07/12] Minimize diff for CMakeList.txt. --- CMakeLists.txt | 139 ++++++++++++++++++++++++++++--------------------- 1 file changed, 81 insertions(+), 58 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index abd77400..1f3204f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,18 @@ # CMake configuration for ECOS + cmake_minimum_required(VERSION 3.5) + project(ecos VERSION 2.0.8 LANGUAGES C) + # Options option(USE_LONG "Whether to use Long or Int for index type." ON) + # Set compiler flags set(DEBUG_OPTIONS "") set(RELEASE_OPTIONS "") + if(MSVC) list(APPEND DEBUG_OPTIONS "/Od" "/Wall") list(APPEND RELEASE_OPTIONS "/O2") @@ -15,58 +20,65 @@ else() list(APPEND DEBUG_OPTIONS "-O0" "-Wall" "-Wextra") list(APPEND RELEASE_OPTIONS "-O3") endif() + # Add the ECOS headers set(ecos_headers - "${CMAKE_CURRENT_SOURCE_DIR}/external/SuiteSparse_config/SuiteSparse_config.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/cone.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/ctrlc.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/data.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos_bb.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/equil.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/expcone.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/glblopts.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/kkt.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/spla.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/splamm.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/timer.h" - "${CMAKE_CURRENT_SOURCE_DIR}/include/wright_omega.h" - ) + "${CMAKE_CURRENT_SOURCE_DIR}/external/SuiteSparse_config/SuiteSparse_config.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/cone.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/ctrlc.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/data.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/ecos_bb.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/equil.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/expcone.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/glblopts.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/kkt.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/spla.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/splamm.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/timer.h" + "${CMAKE_CURRENT_SOURCE_DIR}/include/wright_omega.h" +) + set(ecos_sources - # AMD - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_1.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_2.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_aat.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_control.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_defaults.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_dump.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_global.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_info.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_order.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_post_tree.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_postorder.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_preprocess.c" - "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_valid.c" - # ECOS - "${CMAKE_CURRENT_SOURCE_DIR}/src/cone.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/ctrlc.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/ecos.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/equil.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/expcone.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/kkt.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/preproc.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/spla.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/splamm.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/timer.c" - "${CMAKE_CURRENT_SOURCE_DIR}/src/wright_omega.c" - # ECOS BB - "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb.c" - "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb_preproc.c" - ) + # AMD + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_1.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_2.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_aat.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_control.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_defaults.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_dump.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_global.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_info.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_order.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_post_tree.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_postorder.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_preprocess.c" + "${CMAKE_CURRENT_SOURCE_DIR}/external/amd/src/amd_valid.c" + + # ECOS + "${CMAKE_CURRENT_SOURCE_DIR}/src/cone.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ctrlc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ecos.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/equil.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/expcone.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/kkt.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/preproc.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/spla.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/splamm.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/timer.c" + "${CMAKE_CURRENT_SOURCE_DIR}/src/wright_omega.c" + + # ECOS BB + "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb.c" + "${CMAKE_CURRENT_SOURCE_DIR}/ecos_bb/ecos_bb_preproc.c" +) + # QDLDL library add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/external/qdldl") + # ECOS library add_library(ecos SHARED ${ecos_headers} ${ecos_sources}) + # Set compiler options and definitions target_compile_options(ecos PRIVATE "$<$:${DEBUG_OPTIONS}>") target_compile_options(ecos PRIVATE "$<$:${RELEASE_OPTIONS}>") @@ -74,20 +86,24 @@ target_compile_definitions(ecos PUBLIC CTRLC=1) if(USE_LONG) target_compile_definitions(ecos PUBLIC LDL_LONG DLONG) endif() + # Link math library if(NOT MSVC) target_link_libraries(ecos PRIVATE m) endif() + # Link QDLDL library target_link_libraries(ecos PUBLIC qdldl) + target_include_directories(ecos - PUBLIC - "$" - "$" - "$" - "$" - "$/${CMAKE_INSTALL_INCLUDEDIR}/ecos>" - ) + PUBLIC + "$" + "$" + "$" + "$" + "$/${CMAKE_INSTALL_INCLUDEDIR}/ecos>" +) + # Installation include(GNUInstallDirs) install(TARGETS ecos @@ -95,22 +111,29 @@ install(TARGETS ecos ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" - ) +) + install(FILES ${ecos_headers} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ecos") + # Create CMake packages for the build directory include(CMakePackageConfigHelpers) + export(EXPORT ${PROJECT_NAME} - FILE "${CMAKE_CURRENT_BINARY_DIR}/ecos-targets.cmake" - NAMESPACE ecos:: - ) + FILE "${CMAKE_CURRENT_BINARY_DIR}/ecos-targets.cmake" + NAMESPACE ecos:: +) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/ecos-config.cmake "include(\"\${CMAKE_CURRENT_LIST_DIR}/ecos-targets.cmake\")\n") + # Create CMake packages for the install directory set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/ecos) + install(EXPORT ${PROJECT_NAME} FILE ecos-targets.cmake NAMESPACE ecos:: DESTINATION ${ConfigPackageLocation} - ) +) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ecos-config.cmake DESTINATION ${ConfigPackageLocation} - ) \ No newline at end of file +) From ea6c9b4be8cef8f15004184ba541ab5bd90f1b4f Mon Sep 17 00:00:00 2001 From: zach401 Date: Fri, 14 Jan 2022 08:52:37 -0800 Subject: [PATCH 08/12] Replace spaces with tabs for consistency in kkt.h. --- include/kkt.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/kkt.h b/include/kkt.h index d1644f76..91d23c8e 100644 --- a/include/kkt.h +++ b/include/kkt.h @@ -39,7 +39,7 @@ typedef struct kkt{ spmat* L; /* LDL factor L */ pfloat* D; /* diagonal matrix D */ - pfloat* Dinv; /* inverse of diagonal matrix D */ + pfloat* Dinv; /* inverse of diagonal matrix D */ pfloat* work1; /* workspace needed for factorization */ pfloat* work2; /* workspace needed for factorization */ pfloat* work3; /* workspace needed for factorization */ @@ -54,13 +54,13 @@ typedef struct kkt{ pfloat* dy2; /* search direction of size p */ pfloat* dz1; /* search direction of size m */ pfloat* dz2; /* search direction of size m */ - - idxint* P; /* permutation */ + + idxint* P; /* permutation */ idxint* Pinv; /* reverse permutation */ idxint* PK; /* permutation of row indices of KKT matrix */ idxint* Parent; /* Elimination tree of factorization */ - idxint* Sign; /* Permuted sign vector for regularization */ - ecos_bool* bwork; /* ecos_bool workspace needed for factorization */ + idxint* Sign; /* Permuted sign vector for regularization */ + ecos_bool* bwork; /* ecos_bool workspace needed for factorization */ idxint* iwork; /* idxint workspace needed for factorization */ idxint* Lnz; /* idxint workspace needed for factorization */ From 09ba4c5f449a0d643b8c15150373b585618e520b Mon Sep 17 00:00:00 2001 From: zach401 Date: Fri, 14 Jan 2022 10:40:57 -0800 Subject: [PATCH 09/12] Remove references to delta and eps which are no longer used in the factorization. --- include/ecos.h | 2 -- include/kkt.h | 2 -- src/ecos.c | 3 --- src/preproc.c | 2 -- 4 files changed, 9 deletions(-) diff --git a/include/ecos.h b/include/ecos.h index de468fe5..d7851a26 100644 --- a/include/ecos.h +++ b/include/ecos.h @@ -98,8 +98,6 @@ extern "C" { /* SETTINGS STRUCT ----------------------------------------------------- */ typedef struct settings{ pfloat gamma; /* scaling the final step length */ - pfloat delta; /* regularization parameter */ - pfloat eps; /* regularization threshold */ pfloat feastol; /* primal/dual infeasibility tolerance */ pfloat abstol; /* absolute tolerance on duality gap */ pfloat reltol; /* relative tolerance on duality gap */ diff --git a/include/kkt.h b/include/kkt.h index 91d23c8e..a8373f2a 100644 --- a/include/kkt.h +++ b/include/kkt.h @@ -63,8 +63,6 @@ typedef struct kkt{ ecos_bool* bwork; /* ecos_bool workspace needed for factorization */ idxint* iwork; /* idxint workspace needed for factorization */ idxint* Lnz; /* idxint workspace needed for factorization */ - - pfloat delta; /* size of regularization */ } kkt; /* Return codes */ diff --git a/src/ecos.c b/src/ecos.c index b332f246..29e5d2c6 100644 --- a/src/ecos.c +++ b/src/ecos.c @@ -267,9 +267,6 @@ idxint init(pwork* w) timer tfactor, tkktsolve; #endif - /* set regularization parameter */ - w->KKT->delta = w->stgs->delta; - /* Initialize KKT matrix */ kkt_init(w->KKT->PKPt, w->KKT->PK, w->C); diff --git a/src/preproc.c b/src/preproc.c index 9fa7b51a..b3eea236 100644 --- a/src/preproc.c +++ b/src/preproc.c @@ -759,8 +759,6 @@ pwork* ECOS_setup(idxint n, idxint m, idxint p, idxint l, idxint ncones, idxint* mywork->stgs = (settings *)MALLOC(sizeof(settings)); mywork->stgs->maxit = MAXIT; mywork->stgs->gamma = GAMMA; - mywork->stgs->delta = DELTA; - mywork->stgs->eps = EPS; mywork->stgs->nitref = NITREF; mywork->stgs->abstol = ABSTOL; mywork->stgs->feastol = FEASTOL; From 6be09ed821f99aacedeef70605332c9d21160aa6 Mon Sep 17 00:00:00 2001 From: zach401 Date: Fri, 14 Jan 2022 12:58:31 -0800 Subject: [PATCH 10/12] Add qdldl submodule. --- external/qdldl | 1 + 1 file changed, 1 insertion(+) create mode 160000 external/qdldl diff --git a/external/qdldl b/external/qdldl new file mode 160000 index 00000000..f2665f89 --- /dev/null +++ b/external/qdldl @@ -0,0 +1 @@ +Subproject commit f2665f898d88ef7d3b1d8770cad3cff547c846c5 From 206703478121de613296dbf23650ebe233051303 Mon Sep 17 00:00:00 2001 From: zach401 Date: Fri, 14 Jan 2022 13:05:22 -0800 Subject: [PATCH 11/12] Set qdldl to track v0.1.5 release. --- external/qdldl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/qdldl b/external/qdldl index f2665f89..7d16b70a 160000 --- a/external/qdldl +++ b/external/qdldl @@ -1 +1 @@ -Subproject commit f2665f898d88ef7d3b1d8770cad3cff547c846c5 +Subproject commit 7d16b70a10a152682204d745d814b6eb63dc5cd2 From 848c8007715228fcff94b9ea30cb6d87f0626e13 Mon Sep 17 00:00:00 2001 From: zach401 Date: Fri, 14 Jan 2022 13:24:52 -0800 Subject: [PATCH 12/12] Update SuiteSparse_config.h to use long long instead of long for consistency with QDLDL. --- external/SuiteSparse_config/SuiteSparse_config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/external/SuiteSparse_config/SuiteSparse_config.h b/external/SuiteSparse_config/SuiteSparse_config.h index d601732e..7c6c5ffb 100644 --- a/external/SuiteSparse_config/SuiteSparse_config.h +++ b/external/SuiteSparse_config/SuiteSparse_config.h @@ -55,8 +55,8 @@ extern "C" { #define SuiteSparse_long_max _I64_MAX #define SuiteSparse_long_idd "I64d" #else -#define SuiteSparse_long long -#define SuiteSparse_long_max LONG_MAX +#define SuiteSparse_long long long +#define SuiteSparse_long_max LLONG_MAX #define SuiteSparse_long_idd "ld" #endif #define SuiteSparse_long_id "%" SuiteSparse_long_idd