Skip to content

Commit 954ba5c

Browse files
committed
Redefine cast + add warm_start
1 parent 3898bf8 commit 954ba5c

File tree

11 files changed

+154
-206
lines changed

11 files changed

+154
-206
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ authors = [
77
"joaquimg <[email protected]>",
88
"bernalde <[email protected]>"
99
]
10-
version = "0.6.1"
10+
version = "0.7.0"
1111

1212
[deps]
1313
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

src/formats/bqpjson/parser.jl

+1-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ function read_model(io::IO, fmt::BQPJSON)
2525
target_domain = something(domain(fmt), data[:domain])
2626

2727
L, Q, α, β = cast(
28-
data[:domain],
29-
target_domain,
28+
data[:domain] => target_domain,
3029
data[:linear_terms],
3130
data[:quadratic_terms],
3231
data[:scale],

src/formats/minizinc/parser.jl

+1-2
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,7 @@ function read_model(io::IO, fmt::MiniZinc)
213213
target_domain = something(domain(fmt), data[:domain])
214214

215215
L, Q, α, β = cast(
216-
data[:domain],
217-
target_domain,
216+
data[:domain] => target_domain,
218217
data[:linear_terms],
219218
data[:quadratic_terms],
220219
data[:scale],

src/interface/fallback.jl

+4-11
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,11 @@ This file contains fallback implementations by calling the model's backend.
55
This allows for external models to define a QUBOTools-based backend and profit from these queries.
66
"""
77

8-
# ~*~ Frontend & Backend ~*~ #
9-
# The `frontend` implementation defaults to `backend`
10-
# because most of the time people will not be working
11-
# with two equivalent models as in `TwinModel`'s API.
12-
function frontend(model)
13-
return backend(model)
14-
end
15-
16-
function backend(::M) where {M<:AbstractModel}
8+
function backend(::M) where {M}
179
error(
1810
"""
19-
The '$M' QUBO Model Type has an incomplete inferface.
20-
It should either implement `backend(::$M)` or the complete `AbstractModel` API.
11+
'$M' has an incomplete inferface for 'QUBOTools'.
12+
It should either implement 'backend(::$M)' or the complete 'AbstractModel' API.
2113
Run `julia> ?QUBOTools.AbstractModel` for more information.
2214
"""
2315
)
@@ -42,6 +34,7 @@ variables(model) = variables(backend(model))
4234
variable_set(model) = variable_set(backend(model))
4335
variable_map(model, args...) = variable_map(backend(model), args...)
4436
variable_inv(model, args...) = variable_inv(backend(model), args...)
37+
warm_start(model, args...) = warm_start(backend(model), args...)
4538

4639
# ~*~ Model's Normal Forms ~*~ #
4740
qubo(model, args...) = qubo(backend(model), args...)

src/interface/generic/cast.jl

+18-31
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# -* Sense *- #
2-
function cast(::S, ::S, L̄::Dict{Int,T}) where {S<:Sense,T}
2+
function cast(::Pair{S,S}, L̄::Dict{Int,T}) where {T,S<:Sense}
33
return copy(L̄)
44
end
55

6-
function cast(::Sense, ::Sense, L̄::Dict{Int,T}) where {T}
6+
function cast(::Pair{A,B}, L̄::Dict{Int,T}) where {T,A<:Sense,B<:Sense}
77
L = sizehint!(Dict{Int,T}(), length(L̄))
88

99
for (i, c) in
@@ -13,11 +13,11 @@ function cast(::Sense, ::Sense, L̄::Dict{Int,T}) where {T}
1313
return L
1414
end
1515

16-
function cast(::S, ::S, Q̄::Dict{Tuple{Int,Int},T}) where {S<:Sense,T}
16+
function cast(::Pair{S,S}, Q̄::Dict{Tuple{Int,Int},T}) where {T,S<:Sense}
1717
return copy(Q̄)
1818
end
1919

20-
function cast(::Sense, ::Sense, Q̄::Dict{Tuple{Int,Int},T}) where {T}
20+
function cast(::Pair{A,B}, Q̄::Dict{Tuple{Int,Int},T}) where {T,A<:Sense,B<:Sense}
2121
Q = sizehint!(Dict{Tuple{Int,Int},T}(), length(Q̄))
2222

2323
for (ij, c) in
@@ -28,51 +28,47 @@ function cast(::Sense, ::Sense, Q̄::Dict{Tuple{Int,Int},T}) where {T}
2828
end
2929

3030
function cast(
31-
::S,
32-
::S,
31+
::Pair{S,S},
3332
::Dict{Int,T},
3433
::Dict{Tuple{Int,Int},T},
3534
α::T = one(T),
3635
β::T = zero(T),
37-
) where {S<:Sense,T}
36+
) where {T,S<:Sense}
3837
L = copy(L̄)
3938
Q = copy(Q̄)
4039

4140
return (L, Q, α, β)
4241
end
4342

4443
function cast(
45-
source::Sense,
46-
target::Sense,
44+
route::Pair{A,B},
4745
::Dict{Int,T},
4846
::Dict{Tuple{Int,Int},T},
4947
α::T = one(T),
5048
β::T = zero(T),
51-
) where {T}
52-
L = cast(source, target, L̄)
53-
Q = cast(source, target, Q̄)
49+
) where {T,A<:Sense,B<:Sense}
50+
L = cast(route, L̄)
51+
Q = cast(route, Q̄)
5452

5553
return (L, Q, α, -β)
5654
end
5755

5856
# -* Domain *- #
5957
function cast(
60-
::D,
61-
::D,
58+
::Pair{D,D},
6259
::Dict{Int,T},
6360
::Dict{Tuple{Int,Int},T},
6461
α::T = one(T),
6562
β::T = zero(T),
66-
) where {D<:Domain,T}
63+
) where {T,D<:Domain}
6764
L = copy(L̄)
6865
Q = copy(Q̄)
6966

7067
return (L, Q, α, β)
7168
end
7269

7370
function cast(
74-
::SpinDomain,
75-
::BoolDomain,
71+
::Pair{SpinDomain,BoolDomain},
7672
::Dict{Int,T},
7773
::Dict{Tuple{Int,Int},T},
7874
α::T = one(T),
@@ -97,8 +93,7 @@ function cast(
9793
end
9894

9995
function cast(
100-
::BoolDomain,
101-
::SpinDomain,
96+
::Pair{BoolDomain,SpinDomain},
10297
::Dict{Int,T},
10398
::Dict{Tuple{Int,Int},T},
10499
α::T = one(T),
@@ -122,19 +117,11 @@ function cast(
122117
return (L, Q, α, β)
123118
end
124119

125-
126-
# -* Model *- #
127-
function cast(source::AbstractModel, target::AbstractModel, data)
128-
return cast(sense(source), sense(target), domain(source), domain(target), data)
129-
end
130-
131120
# -* Chain *- #
132121
function cast(
133-
source_sense::Sense,
134-
target_sense::Sense,
135-
source_domain::Domain,
136-
target_domain::Domain,
122+
sense_route::Pair{A,B},
123+
domain_route::Pair{X,Y},
137124
data,
138-
)
139-
return cast(source_sense, target_sense, cast(source_domain, target_domain, data))
125+
) where {A<:Sense,B<:Sense,X<:Domain,Y<:Domain}
126+
return cast(sense_route, cast(domain_route, data))
140127
end

src/interface/interface.jl

+19-24
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,6 @@ Returns a list containing all available QUBO file formats.
4646
Given a file path, tries to infer the type associated to a QUBO model format.
4747
""" function infer_format end
4848

49-
@doc raw"""
50-
frontend(model)::AbstractModel
51-
frontend(model::AbstractModel)::AbstractModel
52-
53-
Retrieves the model's backend.
54-
Implementing this function allows one to profit from fallback implementations of the other methods.
55-
""" function frontend end
56-
5749
@doc raw"""
5850
backend(model)::AbstractModel
5951
backend(model::AbstractModel)::AbstractModel
@@ -101,7 +93,10 @@ Returns the list of available known variable domains.
10193
10294
""" function offset end
10395

104-
abstract type Sense end
96+
@doc raw"""
97+
Sense
98+
99+
""" abstract type Sense end
105100

106101
@doc raw"""
107102
sense(model)::Sense
@@ -121,7 +116,8 @@ abstract type Sense end
121116
""" function description end
122117

123118
@doc raw"""
124-
metadata(model)
119+
metadata(model::AbstractModel)
120+
metadata(sampleset::SampleSet)
125121
""" function metadata end
126122

127123
@doc raw"""
@@ -179,8 +175,8 @@ Returns the set of variables of a given model.
179175
""" function variable_map end
180176

181177
@doc raw"""
182-
variable_inv(model)::Dict{Int,V} where {V}
183-
variable_inv(model, i::Integer)::V where {V}
178+
variable_inv(model)::Dict{Int,V} where {V}
179+
variable_inv(model, i::Integer)::V where {V}
184180
185181
""" function variable_inv end
186182

@@ -369,15 +365,13 @@ If a second parameter, an integer, is present, then the set of neighbors of that
369365

370366
@doc raw"""
371367
cast(
372-
source_sense::Sense,
373-
source_domain::Domain,
374-
target_sense::Sense,
375-
target_domain::Domain,
376-
x::Any
377-
)
368+
sense_route::Pair{A,B},
369+
domain_route::Pair{X,Y},
370+
data,
371+
) where {A<:Sense,B<:Sense,X<:Domain,Y<:Domain}
378372
379373
cast(::S, ::S, model::AbstractModel) where {S<:Sense}
380-
cast(::S1, ::S2, model::AbstractModel) where {S1<:Sense,S2<:Sense}
374+
cast(::A, ::B, model::AbstractModel) where {A<:Sense,B<:Sense}
381375
382376
Recasting the sense of a model preserves its meaning:
383377
@@ -391,14 +385,14 @@ Recasting the sense of a model preserves its meaning:
391385
The linear terms, quadratic terms and constant offset of a model have its signs reversed.
392386
393387
cast(::S, ::S, s::Sample) where {S<:Sense}
394-
cast(::Sense, ::Sense, s::Sample) where {S1<:Sense,S2<:Sense}
388+
cast(::A, ::B, s::Sample) where {A<:Sense,B<:Sense}
395389
cast(::S, ::S, ω::SampleSet) where {S<:Sense}
396-
cast(::Sense, ::Sense, ω::SampleSet) where {S1<:Sense,S2<:Sense}
390+
cast(::A, ::B, ω::SampleSet) where {A<:Sense,B<:Sense}
397391
398392
cast(target, model::AbstractModel)
399-
cast(source, target, ψ::Vector{U})
400-
cast(source, target, Ψ::Vector{Vector{U}})
401-
cast(source, target, ω::SampleSet)
393+
cast(route, ψ::Vector{U})
394+
cast(route, Ψ::Vector{Vector{U}})
395+
cast(route, ω::SampleSet)
402396
403397
Returns a new object, switching its domain from `source` to `target`.
404398
@@ -427,4 +421,5 @@ Reverses the sign of the objective value.
427421

428422
@doc raw"""
429423
supports_read(::Type{F}) where {F<:AbstractFormat}
424+
430425
""" function supports_write end

src/library/sampleset.jl

+20-23
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
function cast(::D, ::D, ψ::Vector{U}) where {D<:Domain,U<:Integer}
1+
function cast(::Pair{D,D}, ψ::Vector{U}) where {U<:Integer,D<:Domain}
22
return copy(ψ)
33
end
44

5-
cast(::BoolDomain, ::SpinDomain, ψ::Vector{U}) where {U<:Integer} = (2 .* ψ) .- 1
6-
cast(::SpinDomain, ::BoolDomain, ψ::Vector{U}) where {U<:Integer} =.+ 1) 2
5+
cast(::Pair{BoolDomain,SpinDomain}, x::Integer) = (2 * x) - 1
6+
cast(::Pair{SpinDomain,BoolDomain}, s::Integer) = (s + 1) ÷ 2
7+
cast(::Pair{BoolDomain,SpinDomain}, ψ::Vector{U}) where {U<:Integer} = (2 .* ψ) .- 1
8+
cast(::Pair{SpinDomain,BoolDomain}, ψ::Vector{U}) where {U<:Integer} =.+ 1) 2
79

8-
function cast(source::Domain, target::Domain, Ψ::Vector{Vector{U}}) where {U<:Integer}
9-
return cast.(source, target, Ψ)
10+
function cast(route::Pair{X,Y}, Ψ::Vector{Vector{U}}) where {U<:Integer,X<:Domain,Y<:Domain}
11+
return cast.(route, Ψ)
1012
end
1113

1214
@doc raw"""
@@ -92,15 +94,15 @@ function format(data::Vector{Sample{T,U}}) where {T,U}
9294
return sort(collect(values(cache)))
9395
end
9496

95-
function cast(source::Domain, target::Domain, s::Sample{T,U}) where {T,U}
96-
return Sample{T,U}(cast(source, target, state(s)), value(s), reads(s))
97+
function cast(route::Pair{X,Y}, s::Sample{T,U}) where {T,U,X<:Domain,Y<:Domain}
98+
return Sample{T,U}(cast(route, state(s)), value(s), reads(s))
9799
end
98100

99-
function cast(::S, ::S, s::Sample{T,U}) where {S<:Sense,T,U}
101+
function cast(::Pair{S,S}, s::Sample{T,U}) where {S<:Sense,T,U}
100102
return Sample{T,U}(state(s), value(s), reads(s))
101103
end
102104

103-
function cast(::S1, ::S2, s::Sample{T,U}) where {S1<:Sense,S2<:Sense,T,U}
105+
function cast(::Pair{A,B}, s::Sample{T,U}) where {T,U,A<:Sense,B<:Sense}
104106
return Sample{T,U}(state(s), -value(s), reads(s))
105107
end
106108

@@ -189,18 +191,19 @@ reads(ω::AbstractSampleSet) = sum(reads.(ω))
189191
@doc raw"""
190192
SampleSet{T,U}(
191193
data::Vector{Sample{T,U}},
192-
metadata::Dict{String, Any},
194+
metadata::Dict{String,Any},
193195
) where {T,U}
194196
195197
It compresses repeated states by adding up the `reads` field.
196-
It was inspired by [1], with a few tweaks.
198+
It was inspired by [^dwave], with a few tweaks.
197199
198200
!!! info
199201
A `SampleSet{T,U}` was designed to be read-only.
200202
It is optimized to support queries over the solution set.
201203
202204
## References
203-
[1] [ocean docs](https://docs.ocean.dwavesys.com/en/stable/docs_dimod/reference/S.html#dimod.SampleSet)
205+
[^dwave]:
206+
[ocean docs](https://docs.ocean.dwavesys.com/en/stable/docs_dimod/reference/S.html#dimod.SampleSet)
204207
""" struct SampleSet{T,U} <: AbstractSampleSet{T,U}
205208
data::Vector{Sample{T,U}}
206209
metadata::Dict{String,Any}
@@ -265,16 +268,10 @@ Base.iterate(ω::SampleSet, i::Integer) = iterate(ω.data, i)
265268

266269
metadata::SampleSet) = ω.metadata
267270

268-
function cast(source::Domain, target::Domain, ω::SampleSet{T,U}) where {T,U}
269-
return SampleSet{T,U}(
270-
Vector{Sample{T,U}}(cast.(source, target, ω)),
271-
deepcopy(metadata(ω)),
272-
)
271+
function cast(route::Pair{A,B}, ω::SampleSet{T,U}) where {T,U,A<:Sense,B<:Sense}
272+
return SampleSet{T,U}(Vector{Sample{T,U}}(cast.(route, ω)), deepcopy(metadata(ω)))
273273
end
274274

275-
function cast(source::Sense, target::Sense, ω::SampleSet{T,U}) where {T,U}
276-
return SampleSet{T,U}(
277-
Vector{Sample{T,U}}(cast.(source, target, ω)),
278-
deepcopy(metadata(ω)),
279-
)
280-
end
275+
function cast(route::Pair{X,Y}, ω::SampleSet{T,U}) where {T,U,X<:Domain,Y<:Domain}
276+
return SampleSet{T,U}(Vector{Sample{T,U}}(cast.(route, ω)), deepcopy(metadata(ω)))
277+
end

0 commit comments

Comments
 (0)