1"""
2Copyright 2013 Steven Diamond
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15"""
16import logging
17import sys
18
19LOGGER = logging.getLogger("__cvxpy__")
20LOGGER.propagate = False
21LOGGER.setLevel(logging.INFO)
22_stream_handler = logging.StreamHandler(sys.stdout)
23_stream_handler.setLevel(logging.INFO)
24_formatter = logging.Formatter(
25    fmt="(CVXPY) %(asctime)s: %(message)s", datefmt="%b %d %I:%M:%S %p"
26)
27_stream_handler.setFormatter(_formatter)
28LOGGER.addHandler(_stream_handler)
29
30
31# Constants for operators.
32PLUS = "+"
33MINUS = "-"
34MUL = "*"
35
36# Prefix for default named variables.
37VAR_PREFIX = "var"
38# Prefix for default named parameters.
39PARAM_PREFIX = "param"
40
41# Used to trick Numpy so cvxpy can overload ==.
42NP_EQUAL_STR = "equal"
43
44# Constraint types
45EQ_CONSTR = "=="
46INEQ_CONSTR = "<="
47
48# Solver Constants
49OPTIMAL = "optimal"
50OPTIMAL_INACCURATE = "optimal_inaccurate"
51INFEASIBLE = "infeasible"
52INFEASIBLE_INACCURATE = "infeasible_inaccurate"
53UNBOUNDED = "unbounded"
54UNBOUNDED_INACCURATE = "unbounded_inaccurate"
55USER_LIMIT = "user_limit"
56SOLVER_ERROR = "solver_error"
57# Statuses that indicate a solution was found.
58SOLUTION_PRESENT = [OPTIMAL, OPTIMAL_INACCURATE, USER_LIMIT]
59# Statuses that indicate the problem is infeasible or unbounded.
60INF_OR_UNB = [INFEASIBLE, INFEASIBLE_INACCURATE,
61              UNBOUNDED, UNBOUNDED_INACCURATE]
62# Statuses that indicate an inaccurate solution.
63INACCURATE = [OPTIMAL_INACCURATE, INFEASIBLE_INACCURATE,
64              UNBOUNDED_INACCURATE, USER_LIMIT]
65# Statuses that indicate an error.
66ERROR = [SOLVER_ERROR]
67
68# Solver names.
69CVXOPT = "CVXOPT"
70GLPK = "GLPK"
71GLPK_MI = "GLPK_MI"
72CBC = "CBC"
73ECOS = "ECOS"
74ECOS_BB = "ECOS_BB"
75SCS = "SCS"
76DIFFCP = "DIFFCP"
77GUROBI = "GUROBI"
78OSQP = "OSQP"
79CPLEX = "CPLEX"
80MOSEK = "MOSEK"
81XPRESS = "XPRESS"
82NAG = "NAG"
83SCIP = "SCIP"
84SCIPY = "SCIPY"
85SOLVERS = [ECOS, CVXOPT, GLPK,
86           GLPK_MI, SCS, GUROBI, OSQP, CPLEX,
87           MOSEK, CBC, XPRESS, NAG, SCIP, SCIPY]
88
89# Xpress-specific items
90XPRESS_IIS = "XPRESS_IIS"
91XPRESS_TROW = "XPRESS_TROW"
92
93# Parameterized problem.
94PARAM_PROB = "param_prob"
95
96# Parallel (meta) solver.
97PARALLEL = "parallel"
98
99# Robust CVXOPT LDL KKT solver.
100ROBUST_KKTSOLVER = "robust"
101
102# Map of constraint types.
103# TODO(akshayka): These should be defined in a solver module.
104EQ, LEQ, SOC, SOC_EW, PSD, EXP, BOOL, INT = range(8)
105
106# Keys in the dictionary of cone dimensions.
107# TODO(akshayka): These should be defined in a solver module.
108#   Riley follow-up on this: cone dims are now defined in matrix
109#   stuffing modules (e.g. cone_matrix_stuffing.py), rather than
110#   the solver module.
111
112EQ_DIM = "f"
113LEQ_DIM = "l"
114SOC_DIM = "q"
115PSD_DIM = "s"
116EXP_DIM = "ep"
117# Keys for non-convex constraints.
118BOOL_IDS = "bool_ids"
119BOOL_IDX = "bool_idx"
120INT_IDS = "int_ids"
121INT_IDX = "int_idx"
122
123# Keys for results_dict.
124STATUS = "status"
125VALUE = "value"
126OBJ_OFFSET = "obj_offset"
127PRIMAL = "primal"
128EQ_DUAL = "eq_dual"
129INEQ_DUAL = "ineq_dual"
130SOLVE_TIME = "solve_time"  # in seconds
131SETUP_TIME = "setup_time"  # in seconds
132NUM_ITERS = "num_iters"  # number of iterations
133EXTRA_STATS = "solver_specific_stats"
134
135# Keys for problem data dict.
136C = "c"
137OFFSET = "offset"
138P = "P"
139Q = "q"
140A = "A"
141B = "b"
142G = "G"
143H = "h"
144F = "F"
145DIMS = "dims"
146BOOL_IDX = "bool_vars_idx"
147INT_IDX = "int_vars_idx"
148
149# Keys for curvature and sign.
150CONSTANT = "CONSTANT"
151AFFINE = "AFFINE"
152CONVEX = "CONVEX"
153CONCAVE = "CONCAVE"
154QUASILINEAR = "QUASILINEAR"
155QUASICONVEX = "QUASICONVEX"
156QUASICONCAVE = "QUASICONCAVE"
157LOG_LOG_CONSTANT = "LOG-LOG CONSTANT"
158LOG_LOG_AFFINE = "LOG-LOG AFFINE"
159LOG_LOG_CONVEX = "LOG-LOG CONVEX"
160LOG_LOG_CONCAVE = "LOG-LOG CONCAVE"
161ZERO = "ZERO"
162NONNEG = "NONNEGATIVE"
163NONPOS = "NONPOSITIVE"
164UNKNOWN = "UNKNOWN"
165
166# Numerical tolerances
167EIGVAL_TOL = 1e-10
168PSD_NSD_PROJECTION_TOL = 1e-8
169GENERAL_PROJECTION_TOL = 1e-10
170SPARSE_PROJECTION_TOL = 1e-10
171ATOM_EVAL_TOL = 1e-4
172
173# threads to use during compilation
174# -1 defaults to system default (configurable via the OMP_NUM_THREADS
175# environment variable)
176NUM_THREADS = -1
177
178
179def set_num_threads(num_threads: int) -> None:
180    global NUM_THREADS
181    NUM_THREADS = num_threads
182
183
184def get_num_threads() -> int:
185    return NUM_THREADS
186