Skip to content

Commit

Permalink
Bump Version
Browse files Browse the repository at this point in the history
  • Loading branch information
pedromxavier committed Nov 25, 2023
1 parent dda3f47 commit 34f2178
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 59 deletions.
20 changes: 10 additions & 10 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
name = "ToQUBO"
uuid = "9a412ddf-83fa-43b6-9748-7843c851aa65"
name = "ToQUBO"
uuid = "9a412ddf-83fa-43b6-9748-7843c851aa65"
authors = ["pedromxavier <[email protected]>", "pedroripper <[email protected]>", "joaquimg <[email protected]>", "AndradeTiago <[email protected]>", "bernalde <[email protected]>"]
version = "0.1.7"
version = "0.1.8-dev"

[deps]
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
PseudoBooleanOptimization = "c8fa9a04-bc42-452d-8558-dc51757be744"
QUBOTools = "60eb5b62-0a39-4ddc-84c5-97d2adff9319"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
QUBOTools = "60eb5b62-0a39-4ddc-84c5-97d2adff9319"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
TOML = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[compat]
MathOptInterface = "1"
MathOptInterface = "1"
PseudoBooleanOptimization = "0.2"
QUBOTools = "0.9"
julia = "1.9"
QUBOTools = "0.9"
julia = "1.9"
2 changes: 1 addition & 1 deletion src/attributes/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ When set, this boolean flag guarantees that every coefficient in the final formu
struct Discretize <: CompilerAttribute end

function MOI.get(model::Optimizer, ::Discretize)::Bool
return get(model.compiler_settings, :discretize, false)
return get(model.compiler_settings, :discretize, true)
end

function MOI.set(model::Optimizer, ::Discretize, flag::Bool)
Expand Down
55 changes: 39 additions & 16 deletions src/compiler/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ function constraint(
# Scalar Affine Equality Constraint: g(x) = a'x - b = 0
g = _parse(model, f, s, arch)

PBO.discretize!(g)
if Attributes.discretize(model)
PBO.discretize!(g)
end

# Bounds & Slack Variable
l, u = PBO.bounds(g)
Expand Down Expand Up @@ -136,7 +138,9 @@ function constraint(
# Scalar Affine Inequality Constraint: g(x) = a'x - b ≤ 0
g = _parse(model, f, s, arch)

PBO.discretize!(g)
if Attributes.discretize(model)
PBO.discretize!(g)
end

# Bounds & Slack Variable
l, u = PBO.bounds(g)
Expand All @@ -152,9 +156,12 @@ function constraint(
end

# Slack Variable
e = Attributes.slack_variable_encoding_method(model, ci)
S = (zero(T), abs(l))
z = Encoding.encode!(model, ci, e, S)
z = if Attributes.discretize(model)
variable_ℤ!(model, ci, S)
else
variable_ℝ!(model, ci, S)
end

for (ω, c) in Virtual.expansion(z)
g[ω] += c
Expand Down Expand Up @@ -198,7 +205,9 @@ function constraint(
# Scalar Affine Inequality Constraint: g(x) = a'x - b ≥ 0
g = _parse(model, f, s, arch)

PBO.discretize!(g)
if Attributes.discretize(model)
PBO.discretize!(g)
end

# Bounds & Slack Variable
l, u = PBO.bounds(g)
Expand All @@ -214,9 +223,12 @@ function constraint(
end

# Slack Variable
e = Attributes.slack_variable_encoding_method(model, ci)
S = (zero(T), abs(u))
z = Encoding.encode!(model, ci, e, S)
z = if Attributes.discretize(model)
variable_ℤ!(model, ci, S)
else
variable_ℝ!(model, ci, S)
end

for (ω, c) in Virtual.expansion(z)
g[ω] -= c
Expand Down Expand Up @@ -260,7 +272,9 @@ function constraint(
# Scalar Quadratic Equality Constraint: g(x) = x' Q x + a' x - b = 0
g = _parse(model, f, s, arch)

PBO.discretize!(g)
if Attributes.discretize(model)
PBO.discretize!(g)
end

# Bounds & Slack Variable
l, u = PBO.bounds(g)
Expand Down Expand Up @@ -320,7 +334,9 @@ function constraint(
# Scalar Quadratic Inequality Constraint: g(x) = x' Q x + a' x - b ≤ 0
g = _parse(model, f, s, arch)

PBO.discretize!(g)
if Attributes.discretize(model)
PBO.discretize!(g)
end

# Bounds & Slack Variable
l, u = PBO.bounds(g)
Expand All @@ -339,9 +355,12 @@ function constraint(
end

# Slack Variable
e = Attributes.slack_variable_encoding_method(model, ci)
S = (zero(T), abs(l))
z = Encoding.encode!(model, ci, e, S)
z = if Attributes.discretize(model)
variable_ℤ!(model, ci, S)
else
variable_ℝ!(model, ci, S)
end

for (ω, c) in Virtual.expansion(z)
g[ω] += c
Expand Down Expand Up @@ -388,7 +407,9 @@ function constraint(
# Scalar Quadratic Inequality Constraint: g(x) = x' Q x + a' x - b ≥ 0
g = _parse(model, f, s, arch)

PBO.discretize!(g)
if Attributes.discretize(model)
PBO.discretize!(g)
end

# Bounds & Slack Variable
l, u = PBO.bounds(g)
Expand All @@ -404,9 +425,12 @@ function constraint(
end

# Slack Variable
e = Attributes.slack_variable_encoding_method(model, ci)
S = (zero(T), abs(u))
z = Encoding.encode!(model, ci, e, S)
z = if Attributes.discretize(model)
variable_ℤ!(model, ci, S)
else
variable_ℝ!(model, ci, S)
end

for (ω, c) in Virtual.expansion(z)
g[ω] -= c
Expand Down Expand Up @@ -475,8 +499,7 @@ function constraint(
end

# Slack variable
e = Encoding.Mirror{T}()
z = Encoding.encode!(model, ci, e)
z = variable_𝔹!(model, ci)

for (ω, c) in Virtual.expansion(z)
g[ω] += c
Expand Down
70 changes: 50 additions & 20 deletions src/compiler/variables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,17 @@ function variables!(model::Virtual.Model{T}, ::AbstractArchitecture) where {T}
end
end

# Encode Variables
if Attributes.stable_compilation(model)
sort!(Ω; by = x -> x.value)
end


# Encode Variables
for x in Ω
# If variable was already encoded, skip
if haskey(model.source, x)
continue

Check warning on line 82 in src/compiler/variables.jl

View check run for this annotation

Codecov / codecov/patch

src/compiler/variables.jl#L82

Added line #L82 was not covered by tests
end

if haskey(ℤ, x)
variable_ℤ!(model, x, ℤ[x])
elseif haskey(ℝ, x)
Expand All @@ -89,29 +94,37 @@ function variables!(model::Virtual.Model{T}, ::AbstractArchitecture) where {T}
return nothing
end

function variable_𝔹!(model::Virtual.Model{T}, x::VI) where {T}
Encoding.encode!(model, x, Encoding.Mirror{T}())

return nothing
function variable_𝔹!(model::Virtual.Model{T}, i::Union{VI,CI}) where {T}
return Encoding.encode!(model, i, Encoding.Mirror{T}())
end

function variable_ℤ!(model::Virtual.Model{T}, x::VI, (a, b)::Tuple{T,T}) where {T}
function variable_ℤ!(model::Virtual.Model{T}, vi::VI, (a, b)::Tuple{T,T}) where {T}
if isnothing(a) || isnothing(b)
error("Unbounded variable $(x) ∈ ℤ")
error("Unbounded variable $(vi) ∈ ℤ")

Check warning on line 103 in src/compiler/variables.jl

View check run for this annotation

Codecov / codecov/patch

src/compiler/variables.jl#L103

Added line #L103 was not covered by tests
else
let e = Attributes.variable_encoding_method(model, x)
let e = Attributes.variable_encoding_method(model, vi)
S = (a, b)

Encoding.encode!(model, x, e, S)
return Encoding.encode!(model, vi, e, S)
end
end
end

return nothing
function variable_ℤ!(model::Virtual.Model{T}, ci::CI, (a, b)::Tuple{T,T}) where {T}
if isnothing(a) || isnothing(b)
error("Unbounded variable $(ci) ∈ ℤ")

Check warning on line 115 in src/compiler/variables.jl

View check run for this annotation

Codecov / codecov/patch

src/compiler/variables.jl#L115

Added line #L115 was not covered by tests
else
let e = Attributes.slack_variable_encoding_method(model, ci)
S = (a, b)

return Encoding.encode!(model, ci, e, S)
end
end
end

function variable_ℝ!(model::Virtual.Model{T}, x::VI, (a, b)::Tuple{T,T}) where {T}
function variable_ℝ!(model::Virtual.Model{T}, vi::VI, (a, b)::Tuple{T,T}) where {T}
if isnothing(a) || isnothing(b)
error("Unbounded variable $(x) ∈ ℝ")
error("Unbounded variable $(vi) ∈ ℝ")

Check warning on line 127 in src/compiler/variables.jl

View check run for this annotation

Codecov / codecov/patch

src/compiler/variables.jl#L127

Added line #L127 was not covered by tests
else
# TODO: Solve this bit-guessing magic??? (DONE)
# IDEA:
Expand All @@ -122,23 +135,40 @@ function variable_ℝ!(model::Virtual.Model{T}, x::VI, (a, b)::Tuple{T,T}) where
#
# For 𝔼[|xᵢ - x̂|] ≤ τ we have
# N ≥ log₂(1 + |b - a| / 4τ)
#
#
# where τ is the (absolute) tolerance
# TODO: Add τ as parameter (DONE)
# TODO: Move this comment to the documentation
let e = Attributes.variable_encoding_method(model, x)
n = Attributes.variable_encoding_bits(model, x)
let e = Attributes.variable_encoding_method(model, vi)
n = Attributes.variable_encoding_bits(model, vi)
S = (a, b)

if !isnothing(n)
Encoding.encode!(model, x, e, S, n)
return Encoding.encode!(model, vi, e, S, n)
else
tol = Attributes.variable_encoding_atol(model, x)
tol = Attributes.variable_encoding_atol(model, vi)

Encoding.encode!(model, x, e, S; tol)
return Encoding.encode!(model, vi, e, S; tol)
end
end
end
end

return nothing
function variable_ℝ!(model::Virtual.Model{T}, ci::CI, (a, b)::Tuple{T,T}) where {T}
if isnothing(a) || isnothing(b)
error("Unbounded slack variable $(ci) ∈ ℝ")

Check warning on line 159 in src/compiler/variables.jl

View check run for this annotation

Codecov / codecov/patch

src/compiler/variables.jl#L159

Added line #L159 was not covered by tests
else
let e = Attributes.slack_variable_encoding_method(model, ci)
n = Attributes.slack_variable_encoding_bits(model, ci)
S = (a, b)

if !isnothing(n)
return Encoding.encode!(model, ci, e, S, n)
else
tol = Attributes.slack_variable_encoding_atol(model, ci)

return Encoding.encode!(model, ci, e, S; tol)
end
end
end
end
9 changes: 7 additions & 2 deletions src/encoding/variables/interval/binary.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ function encode(var::Function, e::Binary{T}, S::Tuple{T,T}; tol::Union{T,Nothing

a, b = integer_interval(S)

@assert b > a
if a == b
y = VI[]
ξ = PBO.PBF{VI,T}(a)

return (y, ξ, nothing)
end

M = trunc(Int, b - a)
N = ceil(Int, log2(M + 1))
Expand All @@ -56,7 +61,7 @@ function encode(var::Function, e::Binary{T}, S::Tuple{T,T}; tol::Union{T,Nothing
)
end

return (y, ξ, nothing) # No penalty function
return (y, ξ, nothing)
end

function encoding_bits(::Binary{T}, S::Tuple{T,T}, tol::T) where {T}
Expand Down
2 changes: 2 additions & 0 deletions test/integration/examples/quadratic/quadratic.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
include("quadratic_1.jl")
include("quadratic_2.jl")
include("primes.jl")

function test_quadratic()
@testset "Quadratic Programs" verbose = true begin
test_quadratic_1()
test_quadratic_2()
test_primes()
end
end
34 changes: 34 additions & 0 deletions test/integration/examples/quadratic/quadratic_2.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
QUBOTools.PBO.varshow(v::VI) = QUBOTools.PBO.varshow(v.value)


"""
min x₁ + x₂
st x₁² + x₂² >= 1
x₁, x₂ ∈ {0, 1}
min x₁ + x₂ + ρ (x₁² + x₂² - 1 + s)²
st x₁, x₂ ∈ {0, 1}
s ∈ [0, 1]
"""
function test_quadratic_2()
model = Model(() -> ToQUBO.Optimizer())

@variable(model, x[1:2], Bin)
@objective(model, Min, x[1] + x[2])
@constraint(model, c, x[1] * x[2] >= 1)

optimize!(model)

n, l, q, α, β = QUBOTools.qubo(model, :dense)

Q = q + diagm(l)

@show n
@show Q

@test termination_status(model) === MOI.LOCALLY_SOLVED
@test get_attribute(model, Attributes.CompilationStatus()) === MOI.LOCALLY_SOLVED

return nothing
end
Loading

0 comments on commit 34f2178

Please sign in to comment.