Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Support Boolean Indexing for Constraints #707

Closed
RoyiAvital opened this issue Oct 26, 2024 · 3 comments · Fixed by #708
Closed

[Feature Request] Support Boolean Indexing for Constraints #707

RoyiAvital opened this issue Oct 26, 2024 · 3 comments · Fixed by #708

Comments

@RoyiAvital
Copy link
Contributor

RoyiAvital commented Oct 26, 2024

It seems there is no support for using BitVector in constraints.

A simple (Stupid) example:

using Convex;
using ECOS;

numSamples = 100;
vY = rand(numSamples);

valThr = sort(vY, rev = true)[5];
vP = vY .>= valThr; #<! Set of boolean indices

vX = Variable(numSamples);
sConvProb = minimize( 0.5 * sumsquares(vX - vY), [vX[vP] == vY[vP]] ); #<! Will fail
solve!(sConvProb, ECOS.Optimizer; silent = true);

If one define vPi = findall(vP); then [vX[vPi] == vY[vPi]] will work.

@odow
Copy link
Member

odow commented Oct 26, 2024

PRs accepted.

It's pretty much just this method, but for BitVector:

function Base.getindex(x::AbstractExpr, I::AbstractMatrix{Bool})
return [xi for (xi, ii) in zip(x, I) if ii]
end
function Base.getindex(x::AbstractExpr, I::AbstractVector{Bool})
return [xi for (xi, ii) in zip(x, I) if ii]
end

@RoyiAvital
Copy link
Contributor Author

I can add those with BitVector and BitMatrix.
I tried looking at the tests, should a specific test be added?

@odow
Copy link
Member

odow commented Oct 26, 2024

Add a new function after:

### affine/IndexAtom
function test_IndexAtom()
target = """
variables: x1, x2
minobjective: [1.0 * x1, 1.0 * x2]
"""
_test_atom(target) do context
return Variable(2)[:, 1]
end
x = Variable(2)
@test x[:, :] === x
target = """
variables: x1, x2, x3
minobjective: [1.0 * x1, 1.0 * x3]
"""
_test_atom(target) do context
return Variable(3)[[1, 3]]
end
target = """
variables: x1, x2, x3
minobjective: [1.0 * x1, 1.0 * x3]
"""
_test_atom(target) do context
return Variable(2, 2)[1, :]
end
target = """
variables: x1, x2, x3, x4
minobjective: [1.0 * x2, 1.0 * x4]
"""
_test_atom(target) do context
return Variable(2, 2)[2, :]
end
_test_atom(target) do context
return Variable(2, 2)[2:2, :]
end
target = """
variables: x1, x2
minobjective: [1.0 * x1, 1.0 * x2]
"""
_test_atom(target) do context
return Variable(2, 2)[:, 1]
end
target = """
variables: x1, x2, x3, x4
minobjective: [1.0 * x3, 1.0 * x4]
"""
_test_atom(target) do context
return Variable(2, 2)[:, 2]
end
y = [true, false, true]
x = Variable(3)
@test string(x[y]) == string([x[1], x[3]])
return
end
function test_IndexAtom_issue_509()
# *Scalar* indexing creates a column vector
# https://github.com/jump-dev/Convex.jl/issues/509
x = rand(2, 3)
ϕ = Variable(2, 3)
Convex.set_value!(ϕ, rand(2, 3))
i = j = 1
# "column-vector" in Convex.jl is a 1 column matrix
@test size(ϕ[i, :]) == (3, 1)
@test size(ϕ[i, 1:2]) == (2, 1)
@test size(ϕ[i, [2, 1]]) == (2, 1)
@test size(ϕ[i:i, :]) == (1, 3)
@test size(evaluate(ϕ[i, :])) == (3,)
@test size(evaluate(ϕ[i:i, :])) == (1, 3)
# "Column vector", not 3x3 matrix!
atom = broadcast(*, ϕ[i, :] - ϕ[j, :], x[i, :] - x[j, :])
@test size(evaluate(atom)) == (3, 1)
return
end

I assume you want something like:

     target = """ 
     variables: x1, x2, x3 
     minobjective: [1.0 * x1, 1.0 * x3] 
     """ 
     _test_atom(target) do context 
         x = Variable(3)
         y = BitVector([true, false, true])
         return x[y] 
     end 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

2 participants