From 976516d8cd46d41061f1ac234e54c780113a3c82 Mon Sep 17 00:00:00 2001 From: maximilianschaller <79449026+maxschaller@users.noreply.github.com> Date: Sun, 21 Apr 2024 12:54:24 -0700 Subject: [PATCH 1/7] Fixed undefined solver name for HTML file. --- cvxpygen/cpg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cvxpygen/cpg.py b/cvxpygen/cpg.py index f288b62..ab9561c 100644 --- a/cvxpygen/cpg.py +++ b/cvxpygen/cpg.py @@ -54,7 +54,7 @@ def generate_code(problem, code_dir='CPG_code', solver=None, solver_opts=None, interface_class, cvxpy_interface_class = get_interface_class(solver_name) # configuration - configuration = get_configuration(code_dir, solver, unroll, prefix) + configuration = get_configuration(code_dir, solver_name, unroll, prefix) # cone problems check if hasattr(param_prob, 'cone_dims'): From dde1e5bdebc8a4b231da4462364eb92dce6e46d9 Mon Sep 17 00:00:00 2001 From: maximilianschaller <79449026+maxschaller@users.noreply.github.com> Date: Sun, 21 Apr 2024 13:09:54 -0700 Subject: [PATCH 2/7] Indentation. --- cvxpygen/utils.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/cvxpygen/utils.py b/cvxpygen/utils.py index a20daca..03f1ece 100644 --- a/cvxpygen/utils.py +++ b/cvxpygen/utils.py @@ -632,7 +632,7 @@ def write_workspace_prot(f, configuration, variable_info, dual_variable_info, pa f.write('typedef struct {\n') for p_id in parameter_canon.p.keys(): if p_id.isupper(): - f.write(f' cpg_csc *{(p_id+";").ljust(8)} // Canonical parameter {p_id}\n') + f.write(f' cpg_csc *{(p_id+";").ljust(8)} // Canonical parameter {p_id}\n') else: if p_id == 'd': s = '' @@ -644,7 +644,7 @@ def write_workspace_prot(f, configuration, variable_info, dual_variable_info, pa f.write('// Flags indicating outdated canonical parameters\n') f.write('typedef struct {\n') for p_id in parameter_canon.p.keys(): - f.write(f' int {(p_id + ";").ljust(8)} // Bool, if canonical parameter {p_id} outdated\n') + f.write(f' int {(p_id + ";").ljust(10)} // Bool, if canonical parameter {p_id} outdated\n') f.write('} Canon_Outdated_t;\n\n') f.write('// Primal solution\n') @@ -672,17 +672,17 @@ def write_workspace_prot(f, configuration, variable_info, dual_variable_info, pa f.write('typedef struct {\n') f.write(' cpg_float obj_val; // Objective function value\n') f.write(' cpg_int iter; // Number of iterations\n') - f.write(f' {"cpg_int " if solver_interface.status_is_int else "char *"}status; // Solver status\n') + f.write(f' {"cpg_int status; " if solver_interface.status_is_int else "char *status; "}// Solver status\n') f.write(' cpg_float pri_res; // Primal residual\n') f.write(' cpg_float dua_res; // Dual residual\n') f.write('} CPG_Info_t;\n\n') f.write('// Solution and solver information\n') f.write('typedef struct {\n') - f.write(' CPG_Prim_t *prim; // Primal solution\n') + f.write(' CPG_Prim_t *prim; // Primal solution\n') if len(dual_variable_info.name_to_init) > 0: - f.write(' CPG_Dual_t *dual; // Dual solution\n') - f.write(' CPG_Info_t *info; // Solver info\n') + f.write(' CPG_Dual_t *dual; // Dual solution\n') + f.write(' CPG_Info_t *info; // Solver info\n') f.write('} CPG_Result_t;\n\n') f.write('// Solver settings\n') @@ -1414,7 +1414,7 @@ def replace_html_data(text, configuration, variable_info, dual_variable_info, pa CPGINFOTYPEDEF += 'typedef struct {\n' CPGINFOTYPEDEF += ' cpg_float obj_val; // Objective function value\n' CPGINFOTYPEDEF += ' cpg_int iter; // Number of iterations\n' - CPGINFOTYPEDEF += (f' {"cpg_int " if solver_interface.status_is_int else "char *"}status; // Solver status\n') + CPGINFOTYPEDEF += (f' {"cpg_int status; " if solver_interface.status_is_int else "char *status; "}// Solver status\n') CPGINFOTYPEDEF += ' cpg_float pri_res; // Primal residual\n' CPGINFOTYPEDEF += ' cpg_float dua_res; // Dual residual\n' CPGINFOTYPEDEF += '} CPG_Info_t;\n' @@ -1423,10 +1423,10 @@ def replace_html_data(text, configuration, variable_info, dual_variable_info, pa # type definition of CPG_Result_t CPGRESULTTYPEDEF = '\n// Struct type with user-defined objective value and solution as fields\n' CPGRESULTTYPEDEF += 'typedef struct {\n' - CPGRESULTTYPEDEF += ' CPG_Prim_t *prim; // Primal solution\n' + CPGRESULTTYPEDEF += ' CPG_Prim_t *prim; // Primal solution\n' if len(dual_variable_info.name_to_init) > 0: - CPGRESULTTYPEDEF += ' CPG_Dual_t *dual; // Dual solution\n' - CPGRESULTTYPEDEF += ' CPG_Info_t *info; // Solver information\n' + CPGRESULTTYPEDEF += ' CPG_Dual_t *dual; // Dual solution\n' + CPGRESULTTYPEDEF += ' CPG_Info_t *info; // Solver information\n' CPGRESULTTYPEDEF += '} CPG_Result_t;\n' text = text.replace('$CPGRESULTTYPEDEF', CPGRESULTTYPEDEF) From d22ae6d1011a5e54b4f9d975747715d63bf15ae6 Mon Sep 17 00:00:00 2001 From: maximilianschaller <79449026+maxschaller@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:08:43 -0700 Subject: [PATCH 3/7] Changed copying logic for preconditioning. --- cvxpygen/solvers.py | 19 ++++++++++++++----- cvxpygen/utils.py | 32 ++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/cvxpygen/solvers.py b/cvxpygen/solvers.py index 5322a29..ad29075 100644 --- a/cvxpygen/solvers.py +++ b/cvxpygen/solvers.py @@ -709,7 +709,8 @@ def __init__(self, data, p_prob, enable_settings): self.parameter_update_structure = { 'init': ParameterUpdateLogic( update_pending_logic=UpdatePendingLogic([], extra_condition='!{prefix}ecos_workspace', functions_if_false=['AbcGh']), - function_call=f'{{prefix}}ecos_workspace = ECOS_setup({canon_constants["n"]}, {canon_constants["m"]}, {canon_constants["p"]}, {canon_constants["l"]}, {canon_constants["n_cones"]}' + function_call=f'{{prefix}}cpg_copy_all();\n' + f' {{prefix}}ecos_workspace = ECOS_setup({canon_constants["n"]}, {canon_constants["m"]}, {canon_constants["p"]}, {canon_constants["l"]}, {canon_constants["n_cones"]}' f', {"0" if canon_constants["n_cones"] == 0 else "(int *) &{prefix}ecos_q"}, {canon_constants["e"]}' f', {{prefix}}Canon_Params_conditioning.G->x, {{prefix}}Canon_Params_conditioning.G->p, {{prefix}}Canon_Params_conditioning.G->i' f', {"0" if canon_constants["p"] == 0 else "{prefix}Canon_Params_conditioning.A->x"}' @@ -720,16 +721,23 @@ def __init__(self, data, p_prob, enable_settings): ), 'AbcGh': ParameterUpdateLogic( update_pending_logic=UpdatePendingLogic(['A', 'b', 'G'], '||', ['c', 'h']), - function_call=f'ECOS_updateData({{prefix}}ecos_workspace, {{prefix}}Canon_Params_conditioning.G->x, {"0" if canon_constants["p"] == 0 else "{prefix}Canon_Params_conditioning.A->x"}' + function_call=f'{{prefix}}cpg_copy_A();\n' + f' {{prefix}}cpg_copy_b();\n' + f' {{prefix}}cpg_copy_c();\n' + f' {{prefix}}cpg_copy_G();\n' + f' {{prefix}}cpg_copy_h();\n' + f' ECOS_updateData({{prefix}}ecos_workspace, {{prefix}}Canon_Params_conditioning.G->x, {"0" if canon_constants["p"] == 0 else "{prefix}Canon_Params_conditioning.A->x"}' f', {{prefix}}Canon_Params_conditioning.c, {{prefix}}Canon_Params_conditioning.h, {"0" if canon_constants["p"] == 0 else "{prefix}Canon_Params_conditioning.b"})' ), 'c': ParameterUpdateLogic( update_pending_logic=UpdatePendingLogic(['c']), - function_call=f'for (i=0; i<{canon_constants["n"]}; i++) {{{{ ecos_updateDataEntry_c({{prefix}}ecos_workspace, i, {{prefix}}Canon_Params_conditioning.c[i]); }}}}' + function_call=f'{{prefix}}cpg_copy_c();\n' + f' for (i=0; i<{canon_constants["n"]}; i++) {{{{ ecos_updateDataEntry_c({{prefix}}ecos_workspace, i, {{prefix}}Canon_Params_conditioning.c[i]); }}}}' ), 'h': ParameterUpdateLogic( update_pending_logic=UpdatePendingLogic(['h']), - function_call=f'for (i=0; i<{canon_constants["m"]}; i++) {{{{ ecos_updateDataEntry_h({{prefix}}ecos_workspace, i, {{prefix}}Canon_Params_conditioning.h[i]); }}}}' + function_call=f'{{prefix}}cpg_copy_h();\n' + f' for (i=0; i<{canon_constants["m"]}; i++) {{{{ ecos_updateDataEntry_h({{prefix}}ecos_workspace, i, {{prefix}}Canon_Params_conditioning.h[i]); }}}}' ) } @@ -929,7 +937,8 @@ def __init__(self, data, p_prob, enable_settings): 'init': ParameterUpdateLogic( update_pending_logic=UpdatePendingLogic([], extra_condition=extra_condition, functions_if_false=[]), function_call= \ - f'clarabel_CscMatrix_init(&{{prefix}}P, {canon_constants["n"]}, {canon_constants["n"]}, {P_p}, {P_i}, {P_x});\n' + f'{{prefix}}cpg_copy_all();\n' + f' clarabel_CscMatrix_init(&{{prefix}}P, {canon_constants["n"]}, {canon_constants["n"]}, {P_p}, {P_i}, {P_x});\n' f' clarabel_CscMatrix_init(&{{prefix}}A, {canon_constants["m"]}, {canon_constants["n"]}, {{prefix}}Canon_Params_conditioning.A->p, {{prefix}}Canon_Params_conditioning.A->i, {{prefix}}Canon_Params_conditioning.A->x);\n' \ f' {{prefix}}settings = clarabel_DefaultSettings_default()' ) diff --git a/cvxpygen/utils.py b/cvxpygen/utils.py index 03f1ece..50bc226 100644 --- a/cvxpygen/utils.py +++ b/cvxpygen/utils.py @@ -845,7 +845,26 @@ def write_solve_def(f, configuration, variable_info, dual_variable_info, paramet f.write(f' {configuration.prefix}CPG_Info.pri_res = {result_prefix}{solver_interface.ws_ptrs.primal_residual};\n') f.write(f' {configuration.prefix}CPG_Info.dua_res = {result_prefix}{solver_interface.ws_ptrs.dual_residual};\n') f.write('}\n\n') - + + if solver_interface.inmemory_preconditioning: + f.write('// Copy canonical parameters for preconditioning\n') + for p_id, size in parameter_canon.p_id_to_size.items(): + f.write(f'void {configuration.prefix}cpg_copy_{p_id}(){{\n') + if size == 1: + f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id} = {configuration.prefix}Canon_Params.{p_id};\n') + elif size > 1: + f.write(f' for (i=0; i<{size}; i++){{\n') + if p_id.isupper(): + f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}->x[i] = {configuration.prefix}Canon_Params.{p_id}->x[i];\n') + else: + f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}[i] = {configuration.prefix}Canon_Params.{p_id}[i];\n') + f.write(' }\n') + f.write('}\n\n') + f.write(f'void {configuration.prefix}cpg_copy_all(){{\n') + for p_id in parameter_canon.p.keys(): + f.write(f' {configuration.prefix}cpg_copy_{p_id}();\n') + f.write('}\n\n') + f.write('// Solve via canonicalization, canonical solve, retrieval\n') f.write(f'void {configuration.prefix}cpg_solve(){{\n') f.write(' // Canonicalize if necessary\n') @@ -855,17 +874,6 @@ def write_solve_def(f, configuration, variable_info, dual_variable_info, paramet f.write(f' if ({configuration.prefix}Canon_Outdated.{p_id}) {{\n') f.write(f' {configuration.prefix}cpg_canonicalize_{p_id}();\n') f.write(' }\n') - if solver_interface.inmemory_preconditioning: - size = parameter_canon.p_id_to_size[p_id] - if size == 1: - f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id} = {configuration.prefix}Canon_Params.{p_id};\n') - elif size > 1: - f.write(f' for (i=0; i<{size}; i++){{\n') - if p_id.isupper(): - f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}->x[i] = {configuration.prefix}Canon_Params.{p_id}->x[i];\n') - else: - f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}[i] = {configuration.prefix}Canon_Params.{p_id}[i];\n') - f.write(' }\n') pus = solver_interface.parameter_update_structure write_update_structure(f, configuration, parameter_canon, pus, *analyze_pus(pus, parameter_canon.p_id_to_changes)) From 41f7672a3e5faff9aefe2ce1c42b80f6b15d9279 Mon Sep 17 00:00:00 2001 From: maximilianschaller <79449026+maxschaller@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:09:03 -0700 Subject: [PATCH 4/7] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 37eacd9..161d276 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ MAJOR = 0 MINOR = 3 -MICRO = 2 +MICRO = 3 VERSION = '%d.%d.%d' % (MAJOR, MINOR, MICRO) From 39e02a8c63b873479c6b0990799ea0eea2f616d5 Mon Sep 17 00:00:00 2001 From: maximilianschaller <79449026+maxschaller@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:17:30 -0700 Subject: [PATCH 5/7] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 161d276..b39dce6 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ def readme(): 'pybind11 >= 2.8', 'osqp >= 0.6.2, < 1.0.0', 'clarabel >= 0.6.0', - 'scipy >= 1.1.0', + 'scipy >= 1.1.0, <1.12.0', 'numpy >= 1.15', ], extras_require={ From c975e160ce07629292f16011e49ecd5e84e61ba9 Mon Sep 17 00:00:00 2001 From: maximilianschaller <79449026+maxschaller@users.noreply.github.com> Date: Sun, 21 Apr 2024 15:19:25 -0700 Subject: [PATCH 6/7] Update setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index b39dce6..c0d42f7 100644 --- a/setup.py +++ b/setup.py @@ -44,7 +44,7 @@ def readme(): 'osqp >= 0.6.2, < 1.0.0', 'clarabel >= 0.6.0', 'scipy >= 1.1.0, <1.12.0', - 'numpy >= 1.15', + 'numpy >= 1.15, <1.28.0', ], extras_require={ 'dev': [ From ac7320c44a7836f67933952c66c8f9622ff67605 Mon Sep 17 00:00:00 2001 From: maximilianschaller <79449026+maxschaller@users.noreply.github.com> Date: Sun, 21 Apr 2024 16:07:03 -0700 Subject: [PATCH 7/7] Simplified function calls. --- cvxpygen/solvers.py | 6 +----- cvxpygen/utils.py | 33 +++++++++++++++++++++------------ 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/cvxpygen/solvers.py b/cvxpygen/solvers.py index ad29075..5c747f4 100644 --- a/cvxpygen/solvers.py +++ b/cvxpygen/solvers.py @@ -721,11 +721,7 @@ def __init__(self, data, p_prob, enable_settings): ), 'AbcGh': ParameterUpdateLogic( update_pending_logic=UpdatePendingLogic(['A', 'b', 'G'], '||', ['c', 'h']), - function_call=f'{{prefix}}cpg_copy_A();\n' - f' {{prefix}}cpg_copy_b();\n' - f' {{prefix}}cpg_copy_c();\n' - f' {{prefix}}cpg_copy_G();\n' - f' {{prefix}}cpg_copy_h();\n' + function_call=f'{{prefix}}cpg_copy_all();\n' f' ECOS_updateData({{prefix}}ecos_workspace, {{prefix}}Canon_Params_conditioning.G->x, {"0" if canon_constants["p"] == 0 else "{prefix}Canon_Params_conditioning.A->x"}' f', {{prefix}}Canon_Params_conditioning.c, {{prefix}}Canon_Params_conditioning.h, {"0" if canon_constants["p"] == 0 else "{prefix}Canon_Params_conditioning.b"})' ), diff --git a/cvxpygen/utils.py b/cvxpygen/utils.py index 50bc226..3a9b931 100644 --- a/cvxpygen/utils.py +++ b/cvxpygen/utils.py @@ -849,20 +849,22 @@ def write_solve_def(f, configuration, variable_info, dual_variable_info, paramet if solver_interface.inmemory_preconditioning: f.write('// Copy canonical parameters for preconditioning\n') for p_id, size in parameter_canon.p_id_to_size.items(): - f.write(f'void {configuration.prefix}cpg_copy_{p_id}(){{\n') - if size == 1: - f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id} = {configuration.prefix}Canon_Params.{p_id};\n') - elif size > 1: - f.write(f' for (i=0; i<{size}; i++){{\n') - if p_id.isupper(): - f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}->x[i] = {configuration.prefix}Canon_Params.{p_id}->x[i];\n') - else: - f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}[i] = {configuration.prefix}Canon_Params.{p_id}[i];\n') - f.write(' }\n') - f.write('}\n\n') + if p_id != 'd': + f.write(f'void {configuration.prefix}cpg_copy_{p_id}(){{\n') + if size == 1: + f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id} = {configuration.prefix}Canon_Params.{p_id};\n') + elif size > 1: + f.write(f' for (i=0; i<{size}; i++){{\n') + if p_id.isupper(): + f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}->x[i] = {configuration.prefix}Canon_Params.{p_id}->x[i];\n') + else: + f.write(f' {configuration.prefix}Canon_Params_conditioning.{p_id}[i] = {configuration.prefix}Canon_Params.{p_id}[i];\n') + f.write(' }\n') + f.write('}\n\n') f.write(f'void {configuration.prefix}cpg_copy_all(){{\n') for p_id in parameter_canon.p.keys(): - f.write(f' {configuration.prefix}cpg_copy_{p_id}();\n') + if p_id != 'd': + f.write(f' {configuration.prefix}cpg_copy_{p_id}();\n') f.write('}\n\n') f.write('// Solve via canonicalization, canonical solve, retrieval\n') @@ -947,6 +949,13 @@ def write_solve_prot(f, configuration, variable_info, dual_variable_info, parame f.write('\n// Retrieve solver information\n') f.write(f'extern void {configuration.prefix}cpg_retrieve_info();\n') + if solver_interface.inmemory_preconditioning: + f.write('\n// Copy canonical parameters for preconditioning\n') + for p_id in parameter_canon.p_id_to_size.keys(): + if p_id != 'd': + f.write(f'extern void {configuration.prefix}cpg_copy_{p_id}();\n') + f.write(f'extern void {configuration.prefix}cpg_copy_all();\n') + f.write('\n// Solve via canonicalization, canonical solve, retrieval\n') f.write(f'extern void {configuration.prefix}cpg_solve();\n')