Let's look at this mathematically.
Problem: You have integer variables x[i] ∈ {0,1,2,...,N}
and you want to allow only K of them to be nonzero.
We can do this by introducing a parallel binary variable b[i] ∈ {0,1}
that indicates whether x[i]
is pinned to zero. I use the convention:
b[i] = 0 => x[i] = 0
b[i] = 1 => x[i] ∈ {0,1,2,...,N}
This can be written simply as a set of constraints:
x[i] <= N*b[i]
sum(i,b[i]) = K
If you want to use the slightly different definition:
b[i] = 0 => x[i] = 0
b[i] = 1 => x[i] ∈ {1,2,...,N}
then we need:
x[i] <= N*b[i]
x[i] >= b[i]
sum(i,b[i]) = K
If the integer variables are: x[i] ∈ {-N,...,-2,-1,0,1,2,...,N}
then we can do:
x[i] <= N*b[i]
x[i] >= -N*b[i]
sum(i,b[i]) = K
I assume that CVXPY generates the same thing when you say:
abs(x) <= N*b
sum(b) == K
(The condition abs(x[i]) >= b[i]
is a little bit more messy to linearize in this case).
This should not be too difficult to transcribe into a CVXPY model. Note that we need this explicit upper bound N on x[i]
. Make it not too large.