Better handling of box cone solutions with SCS
From @bodono in https://github.com/bodono/scs-python/issues/63#issuecomment-1302318079:
Another point is how to restore from the box cone formulation to the original problem when running SCS. This is a minor point, but I wonder if you are dividing by the t scalar variable at termination? I think it's typically better to do that. The box cone is {t * l <= s <= t *u} and we add the constraint that t=1, but if at termination t != 1 then you might need to divide by whatever t is to get a solution that satisfies the conic constraint.
@bodono Currently the function builds the box cone by:
cone["bl"] = lb if lb is not None else np.full((n,), -np.inf)
cone["bu"] = ub if ub is not None else np.full((n,), +np.inf)
zero_row = csc_matrix((1, n))
data["A"] = spa.vstack(
(data["A"], zero_row, -spa.eye(n)),
format="csc",
)
data["b"] = np.hstack((data["b"], 1.0, np.zeros(n)))
And simply returns solution["x"].
If I understand correctly, t == s[i_box] where i_box is the index of the first row of $A$ corresponding to the box cone. Then the proposal here is to record i_box and finally return solution["x"] / solution["s"][i_box].
Yes that's the idea, probably worth making sure that's actually better empirically though.