123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- # Compatibility with Python 2
- from __future__ import print_function
- from scipy import sparse
- import numpy as np
- def write_int(f, x, name, *args):
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s = %i;\n" % (name, x))
- else:
- f.write("c_int %s = %i;\n" % (name, x))
- def write_float(f, x, name, *args):
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s = %.20f;\n" % (name, x))
- else:
- f.write("c_float %s = %.20f;\n" % (name, x))
- def write_vec_int(f, x, name, *args):
- n = len(x)
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- else:
- f.write("c_int * ")
- f.write("%s = (c_int*) c_malloc(%i * sizeof(c_int));\n" % (name, n))
- for i in range(n):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s[%i] = " % (name, i))
- f.write("%i;\n" % x[i])
- def write_vec_float(f, x, name, *args):
- n = len(x)
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- else:
- f.write("c_float * ")
- f.write("%s = (c_float*) c_malloc(%i * sizeof(c_float));\n" % (name, n))
- for i in range(n):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s[%i] = " % (name, i))
- if x[i] == np.inf:
- f.write("OSQP_INFTY;\n")
- elif x[i] == -np.inf:
- f.write("-OSQP_INFTY;\n")
- else:
- f.write("%.20f;\n" % x[i])
- def clean_vec(f, name, *args):
- f.write("c_free(")
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- # else:
- # f.write("c_float * ")
- f.write("%s);\n" % name)
- def write_mat_sparse(f, A, name, *args):
- m = A.shape[0]
- n = A.shape[1]
- f.write("\n// Matrix " + name + "\n")
- f.write("//")
- f.write("-"*(len("Matrix ") + len(name)) + "\n")
- # Allocate Matrix
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- else:
- f.write("csc * ")
- f.write(name + " = (csc*) c_malloc(sizeof(csc));\n")
- # Write dimensions and number of nonzeros
- if any(args):
- write_int(f, m, "m", args, name)
- write_int(f, n, "n", args, name)
- write_int(f, -1, "nz", args, name)
- write_int(f, A.nnz, "nzmax", args, name)
- else:
- write_int(f, m, "m", name)
- write_int(f, n, "n", name)
- write_int(f, -1, "nz", name)
- write_int(f, A.nnz, "nzmax", name)
- for arg in args:
- f.write("%s->" % arg)
- if min(m,n) == 0:
- f.write("%s->x = OSQP_NULL;\n" % name)
- else:
- f.write("%s->" % name)
- f.write("x = (c_float*) c_malloc(%i * sizeof(c_float));\n" % A.nnz)
- for i in range(A.nnz):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s->" % name)
- f.write("x[%i] = %.20f;\n" % (i, A.data[i]))
- for arg in args:
- f.write("%s->" % arg)
- if min(m,n) == 0:
- f.write("%s->i = OSQP_NULL;\n" % name)
- else:
- f.write("%s->" % name)
- f.write("i = (c_int*) c_malloc(%i * sizeof(c_int));\n" % A.nnz)
- for i in range(A.nnz):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s->" % name)
- f.write("i[%i] = %i;\n" % (i, A.indices[i]))
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s->" % name)
- f.write("p = (c_int*) c_malloc((%i + 1) * sizeof(c_int));\n" % n)
- for i in range(A.shape[1] + 1):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s->" % name)
- f.write("p[%i] = %i;\n" % (i, A.indptr[i]))
- # Do the same for i and p
- f.write("\n")
- def clean_mat(f, name, *args):
- # Clean data vector
- f.write("c_free(")
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s->x);\n" % name)
- # Clean index vector
- f.write("c_free(")
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s->i);\n" % name)
- # Clean col pointer vector
- f.write("c_free(")
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s->p);\n" % name)
- # Clean matrix
- f.write("c_free(")
- if any(args):
- for arg in args:
- f.write("%s->" % arg)
- f.write("%s);\n" % name)
- def generate_problem_data(P, q, A, l, u, problem_name, sols_data={}):
- """
- Generate test problem data.
- The additional structure sols_data defines the additional vectors/scalars
- we need to perform the tests
- """
- # Get problem dimension
- n = P.shape[0]
- m = A.shape[0]
- #
- # GENERATE HEADER FILE
- #
- f = open(problem_name + "/data.h", "w")
- # Add definition check
- f.write("#ifndef " + problem_name.upper() + "_DATA_H\n")
- f.write("#define " + problem_name.upper() + "_DATA_H\n")
- # Add Includes
- f.write("#include \"osqp.h\"\n")
- f.write("\n\n")
- #
- # Create additional data structure
- #
- f.write("/* create additional data and solutions structure */\n")
- f.write("typedef struct {\n")
- # Generate further data and solutions
- for key, value in sols_data.items():
- if isinstance(value, str):
- # Status test get from C code
- f.write("c_int %s;\n" % key)
- # Check if it is an array or a scalar
- elif isinstance(value, np.ndarray):
- if isinstance(value.flatten(order='F')[0], int):
- f.write("c_int * %s;\n" % key)
- elif isinstance(value.flatten(order='F')[0], float):
- f.write("c_float * %s;\n" % key)
- else:
- if isinstance(value, int):
- f.write("c_int %s;\n" % key)
- elif isinstance(value, float):
- f.write("c_float %s;\n" % key)
- f.write("} %s_sols_data;\n\n" % problem_name)
- # prototypes
- f.write("/* function prototypes */\n")
- f.write("OSQPData * generate_problem_%s();\n" % problem_name)
- f.write("void clean_problem_%s(OSQPData * data);\n" % problem_name)
- f.write("%s_sols_data * generate_problem_%s_sols_data();\n" % (problem_name, problem_name))
- f.write("void clean_problem_%s_sols_data(%s_sols_data * data);\n" % (problem_name, problem_name))
- f.write("\n\n")
- #
- # Generate QP problem data
- #
- f.write("/* function to generate QP problem data */\n")
- f.write("OSQPData * generate_problem_%s(){\n\n" % problem_name)
- # Initialize structure data
- f.write("OSQPData * data = (OSQPData *)c_malloc(sizeof(OSQPData));\n\n")
- # Write problem dimensions
- f.write("// Problem dimensions\n")
- write_int(f, n, "n", "data")
- write_int(f, m, "m", "data")
- f.write("\n")
- # Write problem vectors
- f.write("// Problem vectors\n")
- write_vec_float(f, l, "l", "data")
- write_vec_float(f, u, "u", "data")
- write_vec_float(f, q, "q", "data")
- f.write("\n")
- # Write matrix A
- write_mat_sparse(f, A, "A", "data")
- write_mat_sparse(f, P, "P", "data")
- # Return data and end function
- f.write("return data;\n\n")
- f.write("}\n\n")
- #
- # Generate QP problem data
- #
- f.write("/* function to clean problem data structure */\n")
- f.write("void clean_problem_%s(OSQPData * data){\n\n" % problem_name)
- # Free vectors
- f.write("// Clean vectors\n")
- clean_vec(f, "l", "data")
- clean_vec(f, "u", "data")
- clean_vec(f, "q", "data")
- f.write("\n")
- # Free matrices
- f.write("//Clean Matrices\n")
- clean_mat(f, "A", "data")
- clean_mat(f, "P", "data")
- f.write("\n")
- f.write("c_free(data);\n\n")
- f.write("}\n\n")
- #
- # Generate additional problem data for solutions
- #
- f.write("/* function to define solutions and additional data struct */\n")
- f.write("%s_sols_data * generate_problem_%s_sols_data(){\n\n" % (problem_name, problem_name))
- # Initialize structure data
- f.write("%s_sols_data * data = (%s_sols_data *)c_malloc(sizeof(%s_sols_data));\n\n" % (problem_name, problem_name, problem_name))
- # Generate further data and solutions
- for key, value in sols_data.items():
- if isinstance(value, str):
- # Status test get from C code
- if value == 'optimal':
- f.write("data->%s = %s;\n" % (key, 'OSQP_SOLVED'))
- elif value == 'optimal_inaccurate':
- f.write("data->%s = %s;\n" % (key, 'OSQP_SOLVED_INACCURATE'))
- elif value == 'primal_infeasible':
- f.write("data->%s = %s;\n" % (key, 'OSQP_PRIMAL_INFEASIBLE'))
- elif value == 'primal_infeasible_inaccurate':
- f.write("data->%s = %s;\n" %
- (key, 'OSQP_PRIMAL_INFEASIBLE_INACCURATE'))
- elif value == 'dual_infeasible':
- f.write("data->%s = %s;\n" % (key, 'OSQP_DUAL_INFEASIBLE'))
- elif value == 'dual_infeasible_inaccurate':
- f.write("data->%s = %s;\n" % (key, 'OSQP_DUAL_INFEASIBLE_INACCURATE'))
- # Check if it is an array or a scalar
- if type(value) is np.ndarray:
- if isinstance(value.flatten(order='F')[0], int):
- write_vec_int(f, value.flatten(order='F'), key, "data")
- elif isinstance(value.flatten(order='F')[0], float):
- write_vec_float(f, value.flatten(order='F'), key, "data")
- else:
- if isinstance(value, int):
- write_int(f, value, key, "data")
- elif isinstance(value, float):
- write_float(f, value, key, "data")
- # Return data and end function
- f.write("\nreturn data;\n\n")
- f.write("}\n\n")
- #
- # Clean additional problem data for solutions
- #
- f.write("/* function to clean solutions and additional data struct */\n")
- f.write("void clean_problem_%s_sols_data(%s_sols_data * data){\n\n" % (problem_name, problem_name))
- # Generate further data and solutions
- for key, value in sols_data.items():
- # Check if it is an array or a scalar
- if type(value) is np.ndarray:
- clean_vec(f, key, "data")
- f.write("\nc_free(data);\n\n")
- f.write("}\n\n")
- f.write("#endif\n")
- f.close()
- def generate_data(problem_name, sols_data):
- """
- Generate test data vectors.
- The additional structure sols_data defines the additional vectors/scalars
- we need to perform the tests
- """
- #
- # GENERATE HEADER FILE
- #
- f = open(problem_name + "/data.h", "w")
- # Add definition check
- f.write("#ifndef " + problem_name.upper() + "_DATA_H\n")
- f.write("#define " + problem_name.upper() + "_DATA_H\n")
- # Add Includes
- f.write("#include \"osqp.h\"\n")
- f.write("\n\n")
- #
- # Create additional data structure
- #
- f.write("/* create data and solutions structure */\n")
- f.write("typedef struct {\n")
- # Generate further data and solutions
- for key, value in sols_data.items():
- if isinstance(value, str):
- # Status test get from C code
- f.write("c_int %s;\n" % key)
- # Check if it is an array or a scalar
- elif sparse.issparse(value): # Sparse matrix
- f.write("csc * %s;\n" % key)
- elif isinstance(value, np.ndarray):
- if isinstance(value.flatten(order='F')[0], int):
- f.write("c_int * %s;\n" % key)
- elif isinstance(value.flatten(order='F')[0], float):
- f.write("c_float * %s;\n" % key)
- else:
- if isinstance(value, int):
- f.write("c_int %s;\n" % key)
- elif isinstance(value, float):
- f.write("c_float %s;\n" % key)
- f.write("} %s_sols_data;\n\n" % problem_name)
- # prototypes
- f.write("/* function prototypes */\n")
- f.write("%s_sols_data * generate_problem_%s_sols_data();\n" % (problem_name, problem_name))
- f.write("void clean_problem_%s_sols_data(%s_sols_data * data);\n" % (problem_name, problem_name))
- f.write("\n\n")
- #
- # Generate additional problem data for solutions
- #
- f.write("/* function to define problem data */\n")
- f.write("%s_sols_data * generate_problem_%s_sols_data(){\n\n" % (problem_name, problem_name))
- # Initialize structure data
- f.write("%s_sols_data * data = (%s_sols_data *)c_malloc(sizeof(%s_sols_data));\n\n" % (problem_name, problem_name, problem_name))
- # Generate further data and solutions
- for key, value in sols_data.items():
- if isinstance(value, str):
- # Status test get from C code
- if value == 'optimal':
- f.write("data->%s = %s;\n" % (key, 'OSQP_SOLVED'))
- elif value == 'primal_infeasible':
- f.write("data->%s = %s;\n" % (key, 'OSQP_PRIMAL_INFEASIBLE'))
- elif value == 'dual_infeasible':
- f.write("data->%s = %s;\n" % (key, 'OSQP_DUAL_INFEASIBLE'))
- # Check if it is an array or a scalar
- elif sparse.issparse(value): # Sparse matrix
- write_mat_sparse(f, value, key, "data")
- elif type(value) is np.ndarray:
- if isinstance(value.flatten(order='F')[0], int):
- write_vec_int(f, value.flatten(order='F'), key, "data")
- elif isinstance(value.flatten(order='F')[0], float):
- write_vec_float(f, value.flatten(order='F'), key, "data")
- else:
- if isinstance(value, int):
- write_int(f, value, key, "data")
- elif isinstance(value, float):
- write_float(f, value, key, "data")
- # Return data and end function
- f.write("\nreturn data;\n\n")
- f.write("}\n\n")
- #
- # Clean data
- #
- f.write("/* function to clean data struct */\n")
- f.write("void clean_problem_%s_sols_data(%s_sols_data * data){\n\n" % (problem_name, problem_name))
- # Generate further data and solutions
- for key, value in sols_data.items():
- # Check if it is an array or a scalar
- if sparse.issparse(value): # Sparse matrix
- clean_mat(f, key, "data")
- elif type(value) is np.ndarray:
- clean_vec(f, key, "data")
- f.write("\nc_free(data);\n\n")
- f.write("}\n\n")
- f.write("#endif\n")
- f.close()
|