Skip to content

Commit 1a8663c

Browse files
committed
Add set_variable_bounds
1 parent 7cb6bcf commit 1a8663c

17 files changed

+80
-2
lines changed

docs/source/changelog.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Changelog
22

3+
## Unreleased
4+
- Add `model.set_variable_bounds(variable, lb, ub)` to make it easier to change variable bounds
5+
36
## 0.2.8
47
- Fix bugs in HiGHS and MOSEK when the quadratic objective function contains nondiagonal terms
58

docs/source/common_model_interface.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,17 @@ query whether a variable is active
9393
:rtype: bool
9494
```
9595

96+
### Modify the bounds of variable
97+
98+
```{py:function} model.set_variable_bounds(var, lb, ub)
99+
100+
set the lower and upper bounds of a variable
101+
102+
:param var: the handle of the variable
103+
:param float lb: the new lower bound value
104+
:param float ub: the new upper bound value
105+
```
106+
96107
## Expression
97108

98109
### Get the value of an expression (including variable)

docs/source/variable.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ model.set_variable_attribute(x, poi.VariableAttribute.PrimalStart, 0.5)
4747
x_value = model.get_variable_attribute(x, poi.VariableAttribute.Value)
4848
```
4949

50+
The most common operation is to set the bounds of the variable. We can use the [`set_variable_bounds`](#model.set_variable_bounds) method of the model to set the lower and upper bounds of the variable at the same time:
51+
52+
```python
53+
x = model.add_variable(name="x")
54+
model.set_variable_bounds(x, 0.0, 1.0)
55+
```
56+
5057
## Delete variable
5158
We can delete a variable by calling the [`delete_variable`](#model.delete_variable) method of the model:
5259

include/pyoptinterface/copt_model.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class COPTModel
172172
bool is_variable_active(const VariableIndex &variable);
173173
double get_variable_value(const VariableIndex &variable);
174174
std::string pprint_variable(const VariableIndex &variable);
175+
void set_variable_bounds(const VariableIndex &variable, double lb, double ub);
175176

176177
ConstraintIndex add_linear_constraint(const ScalarAffineFunction &function,
177178
ConstraintSense sense, CoeffT rhs,

include/pyoptinterface/gurobi_model.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ class GurobiModel
147147
bool is_variable_active(const VariableIndex &variable);
148148
double get_variable_value(const VariableIndex &variable);
149149
std::string pprint_variable(const VariableIndex &variable);
150+
void set_variable_bounds(const VariableIndex &variable, double lb, double ub);
150151

151152
void set_variable_name(const VariableIndex &variable, const char *name);
152153
void set_constraint_name(const ConstraintIndex &constraint, const char *name);

include/pyoptinterface/highs_model.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class POIHighsModel
122122
bool is_variable_active(const VariableIndex &variable);
123123
double get_variable_value(const VariableIndex &variable);
124124
std::string pprint_variable(const VariableIndex &variable);
125+
void set_variable_bounds(const VariableIndex &variable, double lb, double ub);
125126

126127
ConstraintIndex add_linear_constraint(const ScalarAffineFunction &function,
127128
ConstraintSense sense, CoeffT rhs,

include/pyoptinterface/mosek_model.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ class MOSEKModel
138138
bool is_variable_active(const VariableIndex &variable);
139139
double get_variable_value(const VariableIndex &variable);
140140
std::string pprint_variable(const VariableIndex &variable);
141+
void set_variable_bounds(const VariableIndex &variable, double lb, double ub);
141142

142143
ConstraintIndex add_linear_constraint(const ScalarAffineFunction &function,
143144
ConstraintSense sense, CoeffT rhs,

lib/copt_model.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,16 @@ std::string COPTModel::pprint_variable(const VariableIndex &variable)
259259
return get_variable_name(variable);
260260
}
261261

262+
void COPTModel::set_variable_bounds(const VariableIndex &variable, double lb, double ub)
263+
{
264+
auto column = _checked_variable_index(variable);
265+
int error;
266+
error = copt::COPT_SetColLower(m_model.get(), 1, &column, &lb);
267+
check_error(error);
268+
error = copt::COPT_SetColUpper(m_model.get(), 1, &column, &ub);
269+
check_error(error);
270+
}
271+
262272
ConstraintIndex COPTModel::add_linear_constraint(const ScalarAffineFunction &function,
263273
ConstraintSense sense, CoeffT rhs,
264274
const char *name)

lib/copt_model_ext.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ NB_MODULE(copt_model_ext, m)
4141
BIND_F(delete_variables)
4242
BIND_F(is_variable_active)
4343
// clang-format on
44+
.def("set_variable_bounds", &COPTModelMixin::set_variable_bounds, nb::arg("variable"),
45+
nb::arg("lb"), nb::arg("ub"))
4446

4547
.def("get_value",
4648
nb::overload_cast<const VariableIndex &>(&COPTModelMixin::get_variable_value))

lib/gurobi_model.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,17 @@ std::string GurobiModel::pprint_variable(const VariableIndex &variable)
210210
return get_variable_raw_attribute_string(variable, GRB_STR_ATTR_VARNAME);
211211
}
212212

213+
void GurobiModel::set_variable_bounds(const VariableIndex &variable, double lb, double ub)
214+
{
215+
auto column = _checked_variable_index(variable);
216+
int error;
217+
error = gurobi::GRBsetdblattrelement(m_model.get(), GRB_DBL_ATTR_LB, column, lb);
218+
check_error(error);
219+
error = gurobi::GRBsetdblattrelement(m_model.get(), GRB_DBL_ATTR_UB, column, ub);
220+
check_error(error);
221+
m_update_flag |= m_attribute_update;
222+
}
223+
213224
void GurobiModel::set_variable_name(const VariableIndex &variable, const char *name)
214225
{
215226
set_variable_raw_attribute_string(variable, GRB_STR_ATTR_VARNAME, name);

0 commit comments

Comments
 (0)