From 39473c9d7b53329f15d79cf5da2acdad7b1783ff Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 26 Mar 2016 18:29:41 -0700 Subject: [PATCH 1/7] Fix and FIXME --- src/sage/numerical/backends/cvxopt_backend.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/numerical/backends/cvxopt_backend.pyx b/src/sage/numerical/backends/cvxopt_backend.pyx index a23f32caf5c..8778069b802 100644 --- a/src/sage/numerical/backends/cvxopt_backend.pyx +++ b/src/sage/numerical/backends/cvxopt_backend.pyx @@ -191,7 +191,7 @@ cdef class CVXOPTBackend(GenericBackend): 6 """ for i in range(n): - self.add_variable() + self.add_variable() ## FIXME: This forgets to pass arguments return len(self.objective_function) - 1; @@ -419,7 +419,7 @@ cdef class CVXOPTBackend(GenericBackend): (None, 2) """ for i in range(number): - self.add_linear_constraint(zip(range(self.ncols()+1),[0]*(self.ncols()+1)), + self.add_linear_constraint(zip(range(self.ncols()),[0]*(self.ncols())), lower_bound, upper_bound, name=None if names is None else names[i]) From bceca77531cbcc8b8634abdb310d5bb8bb21a699 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 29 Mar 2016 15:21:58 -0700 Subject: [PATCH 2/7] CVXOPTBackend: Use 'is None' instead of '== None' This is only a cosmetic change. --- src/sage/numerical/backends/cvxopt_backend.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/numerical/backends/cvxopt_backend.pyx b/src/sage/numerical/backends/cvxopt_backend.pyx index 8778069b802..56d64b9ff4a 100644 --- a/src/sage/numerical/backends/cvxopt_backend.pyx +++ b/src/sage/numerical/backends/cvxopt_backend.pyx @@ -138,7 +138,7 @@ cdef class CVXOPTBackend(GenericBackend): ... RuntimeError: CVXOPT only supports continuous variables """ - if obj == None: + if obj is None: obj = 0.0 if binary or integer: raise RuntimeError("CVXOPT only supports continuous variables") @@ -1022,7 +1022,7 @@ cdef class CVXOPTBackend(GenericBackend): sage: p.solver_parameter("show_progress") True """ - if value == None: + if value is None: return self.param[name] else: self.param[name] = value From 728750f7d0094bcfb43120d76051917a288cb73c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 29 Mar 2016 15:23:37 -0700 Subject: [PATCH 3/7] CVXOPTBackend.add_variables: Pass arguments to add_variable, correct default for lower_bound --- src/sage/numerical/backends/cvxopt_backend.pyx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/sage/numerical/backends/cvxopt_backend.pyx b/src/sage/numerical/backends/cvxopt_backend.pyx index 56d64b9ff4a..2e48edae514 100644 --- a/src/sage/numerical/backends/cvxopt_backend.pyx +++ b/src/sage/numerical/backends/cvxopt_backend.pyx @@ -150,7 +150,7 @@ cdef class CVXOPTBackend(GenericBackend): return len(self.objective_function) - 1 - cpdef int add_variables(self, int n, lower_bound=None, upper_bound=None, binary=False, continuous=True, integer=False, obj=None, names=None) except -1: + cpdef int add_variables(self, int n, lower_bound=0.0, upper_bound=None, binary=False, continuous=True, integer=False, obj=None, names=None) except -1: """ Add ``n`` variables. @@ -187,11 +187,23 @@ cdef class CVXOPTBackend(GenericBackend): 4 sage: p.ncols() 5 - sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) + sage: p.add_variables(2, lower_bound=-2.0, obj=42.0, names=['a','b']) 6 + + TESTS: + + Check that arguments are used:: + + sage: p.col_bounds(5) # tol 1e-8 + (-2.0, None) + sage: p.col_name(5) + 'a' + sage: p.objective_coefficient(5) # tol 1e-8 + 42.0 """ for i in range(n): - self.add_variable() ## FIXME: This forgets to pass arguments + self.add_variable(lower_bound, upper_bound, binary, continuous, integer, obj, + None if names is None else names[i]) return len(self.objective_function) - 1; From b4a8ed7b4daf59c39301947c87b21fddda9613c7 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 29 Mar 2016 15:48:44 -0700 Subject: [PATCH 4/7] Copy new CVXOPTBackend.add_variables tests to other backends --- src/sage/numerical/backends/coin_backend.pyx | 17 ++++++++++++++--- src/sage/numerical/backends/cplex_backend.pyx | 15 ++++++++++++++- src/sage/numerical/backends/glpk_backend.pyx | 15 ++++++++++++++- src/sage/numerical/backends/gurobi_backend.pyx | 15 ++++++++++++++- src/sage/numerical/backends/ppl_backend.pyx | 13 ++++++++++++- 5 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/sage/numerical/backends/coin_backend.pyx b/src/sage/numerical/backends/coin_backend.pyx index 3a67b413156..6b68f45549f 100644 --- a/src/sage/numerical/backends/coin_backend.pyx +++ b/src/sage/numerical/backends/coin_backend.pyx @@ -179,10 +179,21 @@ cdef class CoinBackend(GenericBackend): 4 sage: p.ncols() # optional - cbc 5 - sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) # optional - cbc + sage: p.add_variables(2, lower_bound=-2.0, integer=True, obj=42.0, names=['a','b']) # optional - cbc 6 - sage: p.col_name(5) # optional - cbc + + TESTS: + + Check that arguments are used:: + + sage: p.col_bounds(5) # tol 1e-8, optional - cbc + (-2.0, None) + sage: p.is_variable_integer(5) # optional - cbc + True + sage: p.col_name(5) # optional - cbc 'a' + sage: p.objective_coefficient(5) # tol 1e-8, optional - cbc + 42.0 """ #cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer)) cdef int vtype = int(binary) + int(continuous) + int(integer) @@ -1685,4 +1696,4 @@ cdef class CoinBackend(GenericBackend): raise MIPSolverException('CBC : Signal sent, getReducedCost() fails') else: cost = [c_cost[i] for i in range(n)] - return cost \ No newline at end of file + return cost diff --git a/src/sage/numerical/backends/cplex_backend.pyx b/src/sage/numerical/backends/cplex_backend.pyx index 99437357349..fb2ebab456b 100644 --- a/src/sage/numerical/backends/cplex_backend.pyx +++ b/src/sage/numerical/backends/cplex_backend.pyx @@ -170,8 +170,21 @@ cdef class CPLEXBackend(GenericBackend): 4 sage: p.ncols() # optional - CPLEX 5 - sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) # optional - CPLEX + sage: p.add_variables(2, lower_bound=-2.0, integer=True, obj=42.0, names=['a','b']) # optional - CPLEX 6 + + TESTS: + + Check that arguments are used:: + + sage: p.col_bounds(5) # tol 1e-8, optional - CPLEX + (-2.0, None) + sage: p.is_variable_integer(5) # optional - CPLEX + True + sage: p.col_name(5) # optional - CPLEX + 'a' + sage: p.objective_coefficient(5) # tol 1e-8, optional - CPLEX + 42.0 """ cdef char * c_name cdef double c_coeff = obj diff --git a/src/sage/numerical/backends/glpk_backend.pyx b/src/sage/numerical/backends/glpk_backend.pyx index 421940145b7..94f690bb28f 100644 --- a/src/sage/numerical/backends/glpk_backend.pyx +++ b/src/sage/numerical/backends/glpk_backend.pyx @@ -174,8 +174,21 @@ cdef class GLPKBackend(GenericBackend): 4 sage: p.ncols() 5 - sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) + sage: p.add_variables(2, lower_bound=-2.0, integer=True, obj=42.0, names=['a','b']) 6 + + TESTS: + + Check that arguments are used:: + + sage: p.col_bounds(5) # tol 1e-8 + (-2.0, None) + sage: p.is_variable_integer(5) + True + sage: p.col_name(5) + 'a' + sage: p.objective_coefficient(5) + 42.0 """ cdef int vtype = int(bool(binary)) + int(bool(continuous)) + int(bool(integer)) if vtype == 0: diff --git a/src/sage/numerical/backends/gurobi_backend.pyx b/src/sage/numerical/backends/gurobi_backend.pyx index 7b0a2e5ac88..08350c28fb6 100644 --- a/src/sage/numerical/backends/gurobi_backend.pyx +++ b/src/sage/numerical/backends/gurobi_backend.pyx @@ -196,8 +196,21 @@ cdef class GurobiBackend(GenericBackend): 4 sage: p.ncols() # optional - Gurobi 5 - sage: p.add_variables(2, lower_bound=-2.0, integer=True, names=['a','b']) # optional - Gurobi + sage: p.add_variables(2, lower_bound=-2.0, integer=True, obj=42.0, names=['a','b']) # optional - Gurobi 6 + + TESTS: + + Check that arguments are used:: + + sage: p.col_bounds(5) # tol 1e-8, optional - Gurobi + (-2.0, None) + sage: p.is_variable_integer(5) # optional - Gurobi + True + sage: p.col_name(5) # optional - Gurobi + 'a' + sage: p.objective_coefficient(5) # tol 1e-8, optional - Gurobi + 42.0 """ cdef int i cdef int value diff --git a/src/sage/numerical/backends/ppl_backend.pyx b/src/sage/numerical/backends/ppl_backend.pyx index b696612fa93..0c85bf0f35e 100644 --- a/src/sage/numerical/backends/ppl_backend.pyx +++ b/src/sage/numerical/backends/ppl_backend.pyx @@ -226,8 +226,19 @@ cdef class PPLBackend(GenericBackend): 4 sage: p.ncols() 5 - sage: p.add_variables(2, lower_bound=-2.0, names=['a','b']) + sage: p.add_variables(2, lower_bound=-2.0, obj=42.0, names=['a','b']) 6 + + TESTS: + + Check that arguments are used:: + + sage: p.col_bounds(5) # tol 1e-8 + (-2.0, None) + sage: p.col_name(5) + 'a' + sage: p.objective_coefficient(5) # tol 1e-8 + 42.0 """ for k in range(n): for i in range(len(self.Matrix)): From b0d89e4989ce9d6db363a33bccf7c87c957cb49c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 29 Mar 2016 15:49:36 -0700 Subject: [PATCH 5/7] GLPKBackend.add_variables: Set column names correctly --- src/sage/numerical/backends/glpk_backend.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/numerical/backends/glpk_backend.pyx b/src/sage/numerical/backends/glpk_backend.pyx index 94f690bb28f..f463d48d763 100644 --- a/src/sage/numerical/backends/glpk_backend.pyx +++ b/src/sage/numerical/backends/glpk_backend.pyx @@ -217,7 +217,7 @@ cdef class GLPKBackend(GenericBackend): self.objective_coefficient(n_var - i - 1, obj) if names is not None: - glp_set_col_name(self.lp, n_var, names[number - i - 1]) + glp_set_col_name(self.lp, n_var - i, names[number - i - 1]) return n_var - 1 From 183ce259998f1a014054045bcad6499f35ac978c Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 29 Mar 2016 15:50:25 -0700 Subject: [PATCH 6/7] PPLBackend.add_variable, add_variables: Don't silently ignore binary=True, integer=True --- src/sage/numerical/backends/ppl_backend.pyx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sage/numerical/backends/ppl_backend.pyx b/src/sage/numerical/backends/ppl_backend.pyx index 0c85bf0f35e..e633fd31f21 100644 --- a/src/sage/numerical/backends/ppl_backend.pyx +++ b/src/sage/numerical/backends/ppl_backend.pyx @@ -178,7 +178,13 @@ cdef class PPLBackend(GenericBackend): 'x' sage: p.objective_coefficient(2) 2/3 + sage: p.add_variable(integer=True) + Traceback (most recent call last): + ... + NotImplementedError: The PPL backend in Sage only supports continuous variables """ + if binary or integer: + raise NotImplementedError("The PPL backend in Sage only supports continuous variables") for i in range(len(self.Matrix)): self.Matrix[i].append(0) self.col_lower_bound.append(lower_bound) @@ -240,6 +246,8 @@ cdef class PPLBackend(GenericBackend): sage: p.objective_coefficient(5) # tol 1e-8 42.0 """ + if binary or integer: + raise NotImplementedError("The PPL backend in Sage only supports continuous variables") for k in range(n): for i in range(len(self.Matrix)): self.Matrix[i].append(0) From e47b608c20f5bc1157e15fd796e85e8ce0c86833 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 29 Mar 2016 16:10:58 -0700 Subject: [PATCH 7/7] CVXOPTBackend.add_linear_constraints: Add doctest, simplify code --- src/sage/numerical/backends/cvxopt_backend.pyx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/sage/numerical/backends/cvxopt_backend.pyx b/src/sage/numerical/backends/cvxopt_backend.pyx index 2e48edae514..37774f0b3b1 100644 --- a/src/sage/numerical/backends/cvxopt_backend.pyx +++ b/src/sage/numerical/backends/cvxopt_backend.pyx @@ -429,10 +429,17 @@ cdef class CVXOPTBackend(GenericBackend): ([], []) sage: p.row_bounds(4) (None, 2) + + TESTS: + + It does not add mysterious new variables:: + + sage: p.ncols() + 5 + """ for i in range(number): - self.add_linear_constraint(zip(range(self.ncols()),[0]*(self.ncols())), - lower_bound, upper_bound, + self.add_linear_constraint([], lower_bound, upper_bound, name=None if names is None else names[i]) cpdef int solve(self) except -1: