addVar in highs.py doesn't add columns to the model
Hence, if highspy calls are made to change model data for columns, they fail
needs self.update() call?
See mats.py
Correct, this was by design so that we can efficiently add a batch of variables. It's not ideal for people to add many variables one-by-one - but obviously it's still possible for them to do so.
For the mats.py example, instead of:
for i in range(nvars):
h.addVar(0, inf)
h.changeColCost(i, 1)
we can simply use:
for i in range(nvars):
h.addVar(0, inf, 1)
h.update() # needed since calling low-level addRow afterwards (instead of addConstr)
or (horribly):
for i in range(nvars):
h.addVar(0, inf)
h.update()
h.changeColCost(i, 1)
That said, this also connects to #1679, and so it depends if we want the default API to use the new highspy interface, or directly access the base HiGHS class.
BTW: I believe with the new highspy, mats.py can be rewritten from:
for i in range(nvars):
h.addVar(0, inf)
h.changeColCost(i, 1)
row_nnz = 2
index = np.array([0, 1])
value = np.array([1, 1], dtype=np.double)
for i in range(nvars - 1):
index[0] = i
index[1] = i+1
h.addRow(1, inf, row_nnz, index, value)
h.run()
to:
X = [h.addVar(0, inf, 1) for _ in range(nvars)]
C = [h.addConstr(X[i] + X[i+1] >= 1) for i in range(nvars - 1)]
h.run()
mats.py was actually my attempt to re-write
https://github.com/ERGO-Code/HiGHS/blob/highspy-modelling/examples/scip.py
when we lost the ability to build highspy with your modelling language.
Your version is even more succinct, although (keeping within the modelling language) it would work with
X = [h.addVar(obj=1) for _ in range(nvars)] C = [h.addConstr(X[i] + X[i+1] >= 1) for i in range(nvars - 1)]
h.run()
Good point. Referring to comment in #1679, if we also support addVars/addConstrs in highspy, we could simplify even further:
X = h.addVars(nvars, obj=1)
C = h.addConstrs(X[i] + X[i+1] >= 1 for i in range(nvars - 1))
h.run()
That highspy code would look something like the following:
def addVars(self, nvars, lb = 0, ub = kHighsInf, obj = 0, type=HighsVarType.kContinuous, name_prefix = None):
return [self.addVar(lb, ub, obj, type, None if name_prefix == None else name_prefix + str(_)) for _ in range(nvars)]
def addConstrs(self, generator, name_prefix=None):
self.update()
lower = []
upper = []
starts = [0]
indices = []
values = []
nnz = 0;
for cons in generator:
# if we have duplicate variables, add the vals together
vars,vals = zip(*[(var, sum(v[1] for v in Vals)) for var, Vals in groupby(sorted(zip(cons.vars, cons.vals)), key=itemgetter(0))])
lower.append(cons.LHS - cons.constant)
upper.append(cons.RHS - cons.constant)
indices.extend(vars)
values.extend(vals)
nnz += len(vars)
starts.append(nnz)
new_rows = len(lower)
super().addRows(new_rows, lower, upper, nnz, starts, indices, values);
cons = [highs_cons(self.numConstrs - new_rows + n, self, None if name_prefix == None else name_prefix + str(n)) for n in range(new_rows)]
self._cons.extend(cons)
return cons
Closed by #1753