Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
Merge pull request #31 from psrenergy/px/dev
Browse files Browse the repository at this point in the history
Update Interface to match `QUBOTools v0.5.2`
  • Loading branch information
pedromxavier authored Dec 15, 2022
2 parents 7e9cb76 + 8cde2e4 commit 1aa8f0c
Show file tree
Hide file tree
Showing 13 changed files with 195 additions and 159 deletions.
24 changes: 12 additions & 12 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Anneal"
uuid = "e4d9eb7f-b088-426e-aeb5-1c0dae3d8abb"
version = "0.5.4"
name = "Anneal"
uuid = "e4d9eb7f-b088-426e-aeb5-1c0dae3d8abb"
version = "0.5.5"
authors = [
"pedromxavier <pedroxavier@psr-inc.com>",
"pedroripper <pedroripper@psr-inc.com>",
Expand All @@ -10,16 +10,16 @@ authors = [
]

[deps]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
QUBOTools = "60eb5b62-0a39-4ddc-84c5-97d2adff9319"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
QUBOTools = "60eb5b62-0a39-4ddc-84c5-97d2adff9319"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[compat]
BenchmarkTools = "1.3"
JuMP = "1"
BenchmarkTools = "1.3"
JuMP = "1"
MathOptInterface = "1"
QUBOTools = "0.4.4"
julia = "1.6"
QUBOTools = "0.5.2"
julia = "1.6"
14 changes: 7 additions & 7 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[deps]
Anneal = "e4d9eb7f-b088-426e-aeb5-1c0dae3d8abb"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
Anneal = "e4d9eb7f-b088-426e-aeb5-1c0dae3d8abb"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
QUBOTools = "60eb5b62-0a39-4ddc-84c5-97d2adff9319"
QUBOTools = "60eb5b62-0a39-4ddc-84c5-97d2adff9319"

[compat]
Documenter = "0.27"
JuMP = "1"
Documenter = "0.27"
JuMP = "1"
MathOptInterface = "1"
QUBOTools = "0.4"
QUBOTools = "0.5"
1 change: 0 additions & 1 deletion docs/src/interface.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# A new Sampler
This guide aims to provide a tutorial on how to implement new sampler interfaces using [Anneal.jl](https://github.com/psrenergy/Anneal.jl).


## The `@anew` macro
Using the [`Anneal.@anew`](@ref anew-macro) macro is the most straightforward way to get your sampler running right now.
Apart from the macro call it is needed to implement the [`Anneal.sample`](@ref) method.
Expand Down
4 changes: 3 additions & 1 deletion docs/src/manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,4 +195,6 @@ In order to consistently support [semantic versioning](https://semver.org/) it i

```julia
version = v"1.0.2"
```
```

# Model Mapping
24 changes: 22 additions & 2 deletions src/interface/abstract/wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,27 @@ MOI.get(::AbstractSampler, ::MOI.DualStatus) = MOI.NO_SOLUTION

# ~ Introduce `reads(model; result = i)` interface.
# The `reads` function is exported.
QUBOTools.reads(model::JuMP.Model; result::Integer) = QUBOTools.reads(model, result)
function QUBOTools.reads(model::JuMP.Model; result::Integer = 1)
return QUBOTools.reads(model, result)
end

# ~ Give access to QUBOTools' queries.
QUBOTools.backend(model::JuMP.Model) = QUBOTools.backend(JuMP.unsafe_backend(model))
if !hasmethod(QUBOTools.backend, (JuMP.Model,))
# Other packages, such as ToQUBO.jl, also would like to apply
# this extesion to connect JuMP and QUBOTools.
# ToQUBO.jl and Anneal.jl share many use cases, but are inde-
# pendent in a conceptual sense.
function QUBOTools.backend(model::JuMP.Model)
return QUBOTools.backend(JuMP.unsafe_backend(model))
end
end

function QUBOTools.Sense(sense::MOI.OptimizationSense)
if sense === MOI.MIN_SENSE
return QUBOTools.Sense(:min)
elseif sense === MOI.MAX_SENSE
return QUBOTools.Sense(:max)
else
error("Invalid sense for QUBO: '$sense'")
end
end
12 changes: 4 additions & 8 deletions src/interface/automatic/interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,22 @@ abstract type AutomaticSampler{T} <: AbstractSampler{T} end
model_sense(sampler)::Union{Symbol,Nothing}
""" function model_sense end

function Anneal.model_sense(sampler::AutomaticSampler)
return MOI.get(sampler, MOI.ObjectiveSense())
end
Anneal.model_sense(sampler::AutomaticSampler) = QUBOTools.sense(sampler.source)::QUBOTools.Sense

@doc raw"""
model_domain(sampler)::Union{Symbol,Nothing}
""" function model_domain end

function Anneal.model_domain(sampler::AutomaticSampler)
return QUBOTools.domain(sampler)
end
Anneal.model_domain(sampler::AutomaticSampler) = QUBOTools.domain(sampler.source)::QUBOTools.VariableDomain

@doc raw"""
solver_sense(sampler)::Union{Symbol,Nothing}
""" function solver_sense end

Anneal.solver_sense(::AutomaticSampler) = nothing
Anneal.solver_sense(::S) where {S<:AutomaticSampler} = error("'solver_sense' not defined for '$S'")

@doc raw"""
solver_domain(sampler)::Union{Symbol,Nothing}
""" function solver_domain end

Anneal.solver_domain(::AutomaticSampler) = nothing
Anneal.solver_domain(::S) where {S<:AutomaticSampler} = error("'solver_domain' not defined for '$S'")
53 changes: 27 additions & 26 deletions src/interface/automatic/macros.jl
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,12 @@ function __anew_parse_params(block::Expr)
end
end

params[:sense] = if params[:sense] === :min
MOI.MIN_SENSE
else
MOI.MAX_SENSE
end

params[:domain] = if params[:domain] === :bool
QUBOTools.BoolDomain()
params[:sense] = QUBOTools.Sense(params[:sense])

if params[:domain] === :bool
params[:domain] = QUBOTools.BoolDomain()
elseif params[:domain] === :spin
QUBOTools.SpinDomain()
params[:domain] = QUBOTools.SpinDomain()
end

return params
Expand Down Expand Up @@ -216,23 +212,25 @@ function __anew_parse()
end

function __anew_parse(id, block)
id = if !(id isa Symbol)
params = Dict{Symbol,Any}()

if !(id isa Symbol)
__anew_error("first argument must be an identifier")
else
__anew_parse_id(id)
end

params[:id] = __anew_parse_id(id)

params = if !(block isa Expr && block.head === :block)
if !(block isa Expr && block.head === :block)
__anew_error("second argument must be a `begin...end` block")
else
__anew_parse_params(block)
end

return (id, params)

merge!(params, __anew_parse_params(block))

return params
end

function __anew_attr(attr)
type = attr[:type]
type = attr[:type]
default = attr[:default]
optattr = attr[:optattr]
rawattr = attr[:rawattr]
Expand Down Expand Up @@ -315,10 +313,10 @@ macro anew(raw_args...)
push!(Anneal.__ANEW_REGISTRY, __module__)
end

args = map(a -> macroexpand(__module__, a), raw_args)

id, params = __anew_parse(args...)
args = map(a -> macroexpand(__module__, a), raw_args)
params = __anew_parse(args...)

id = params[:id]
name = params[:name]
sense = params[:sense]
domain = params[:domain]
Expand All @@ -333,30 +331,33 @@ macro anew(raw_args...)

mutable struct $(esc(id)){T} <: Anneal.AutomaticSampler{T}
# ~*~ QUBOTools Backend model ~*~ #
model::Union{QUBOTools.StandardQUBOModel,Nothing}
source::Union{QUBOTools.Model,Nothing}
target::Union{QUBOTools.Model,Nothing}
# ~*~ Attributes ~*~ #
attrs::Anneal.SamplerAttributeData{T}

function $(esc(id)){T}(args...; kws...) where {T}
return new{T}(
nothing,
nothing,
Anneal.SamplerAttributeData{T}(copy.(__SAMPLER_ATTRIBUTES)),
)
end

function $(esc(id))(args...; kws...)
return $(esc(id)){Float64}(args...; kws...)
end
end

$(esc(id))(args...; kws...) = $(esc(id)){Float64}(args...; kws...)

$(attributes...)

# MOI interface
MOI.get(::$(esc(id)), ::MOI.SolverName) = $(esc(name))
MOI.get(::$(esc(id)), ::MOI.SolverVersion) = $(esc(version))

# domain/sense mapping
Anneal.solver_sense(::$(esc(id))) = $(esc(sense))
Anneal.solver_domain(::$(esc(id))) = $(esc(domain))

# test function
function $(esc(:test))(; examples::Bool = false)
Anneal.test($(esc(id)); examples = examples)

Expand Down
31 changes: 20 additions & 11 deletions src/interface/automatic/sample.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ function parse_results(
sampler::AutomaticSampler{T},
results::Anneal.SampleSet{T,U},
) where {T,U}
S = Anneal.solver_domain(sampler)
M = Anneal.model_domain(sampler)
results = QUBOTools.swap_domain(
Anneal.solver_domain(sampler),
Anneal.model_domain(sampler),
results
)

results = QUBOTools.swap_sense(
Anneal.solver_sense(sampler),
Anneal.model_sense(sampler),
results
)

return QUBOTools.swap_domain(S, M, results)
return results
end

function Anneal.sample!(sampler::AutomaticSampler)
Expand All @@ -18,20 +27,20 @@ function Anneal.sample!(sampler::AutomaticSampler)
sampleset = Anneal.parse_results(sampler, results.value)

# ~*~ Timing Information ~*~ #
time_data = Dict{String,Any}(
"total" => results.time
)
timedata = Dict{String,Any}("total" => results.time)
metadata = QUBOTools.metadata(sampleset)

# ~*~ Time metadata ~*~ #
if !haskey(sampleset.metadata, "time")
sampleset.metadata["time"] = time_data
if !haskey(metadata, "time")
metadata["time"] = timedata
elseif !haskey(sampleset.metadata["time"], "total")
sampleset.metadata["time"]["total"] = time_data["total"]
metadata["time"]["total"] = timedata["total"]
end

# ~*~ Update sampleset ~*~ #
model = Anneal.backend(sampler)::QUBOTools.StandardQUBOModel
model.sampleset = sampleset
model = frontend(sampler)::QUBOTools.Model

copy!(QUBOTools.sampleset(model), sampleset)

return nothing
end
Loading

2 comments on commit 1aa8f0c

@pedromxavier
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/74219

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.5.5 -m "<description of version>" 1aa8f0cf28e0dcb59fbff6a84f693817cda1c909
git push origin v0.5.5

Please sign in to comment.