@@ -109,10 +109,10 @@ GraphPolynomial(; method::Symbol = :finitefield, kwargs...) = GraphPolynomial{me
109
109
graph_polynomial_method (:: GraphPolynomial{METHOD} ) where METHOD = METHOD
110
110
111
111
"""
112
- SingleConfigMax{BOUNDED} <: AbstractProperty
113
- SingleConfigMax(; bounded=false)
112
+ SingleConfigMax{K, BOUNDED} <: AbstractProperty
113
+ SingleConfigMax(k::Int ; bounded=false)
114
114
115
- Finding single best solution, e.g. for [`IndependentSet`](@ref) problem, it is one of the maximum independent sets.
115
+ Finding single solution for largest-K sizes , e.g. for [`IndependentSet`](@ref) problem, it is one of the maximum independent sets.
116
116
117
117
* The corresponding data type is [`CountingTropical{Float64,<:ConfigSampler}`](@ref) if `BOUNDED` is `false`, [`Tropical`](@ref) otherwise.
118
118
* Weighted graph problems is supported.
@@ -122,14 +122,15 @@ Keyword Arguments
122
122
----------------------------
123
123
* `bounded`, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
124
124
"""
125
- struct SingleConfigMax{BOUNDED} <: AbstractProperty end
126
- SingleConfigMax (; bounded:: Bool = false ) = SingleConfigMax {bounded} ()
125
+ struct SingleConfigMax{K,BOUNDED} <: AbstractProperty end
126
+ SingleConfigMax (k:: Int = 1 ; bounded:: Bool = false ) = SingleConfigMax {k, bounded} ()
127
+ max_k (:: SingleConfigMax{K} ) where K = K
127
128
128
129
"""
129
- SingleConfigMin{BOUNDED} <: AbstractProperty
130
- SingleConfigMin(; bounded=false)
130
+ SingleConfigMin{K, BOUNDED} <: AbstractProperty
131
+ SingleConfigMin(k::Int ; bounded=false)
131
132
132
- Finding single "worst" solution.
133
+ Finding single solution with smallest-K size .
133
134
134
135
* The corresponding data type is inverted [`CountingTropical{Float64,<:ConfigSampler}`](@ref) if `BOUNDED` is `false`, inverted [`Tropical`](@ref) otherwise.
135
136
* Weighted graph problems is supported.
@@ -139,8 +140,9 @@ Keyword Arguments
139
140
----------------------------
140
141
* `bounded`, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
141
142
"""
142
- struct SingleConfigMin{BOUNDED} <: AbstractProperty end
143
- SingleConfigMin (; bounded:: Bool = false ) = SingleConfigMin {bounded} ()
143
+ struct SingleConfigMin{K,BOUNDED} <: AbstractProperty end
144
+ SingleConfigMin (k:: Int = 1 ; bounded:: Bool = false ) = SingleConfigMin {k,bounded} ()
145
+ min_k (:: SingleConfigMin{K} ) where K = K
144
146
145
147
"""
146
148
ConfigsAll{TREESTORAGE} <:AbstractProperty
@@ -216,7 +218,7 @@ Positional Arguments
216
218
* [`CountingAll`](@ref) for counting all configurations,
217
219
* [`GraphPolynomial`](@ref) for evaluating the graph polynomial,
218
220
219
- * [`SingleConfigMax`](@ref) for finding one maximum configuration,
221
+ * [`SingleConfigMax`](@ref) for finding one maximum configuration for each size ,
220
222
* [`ConfigsMax`](@ref) for enumerating configurations with largest-K sizes,
221
223
* [`ConfigsMin`](@ref) for enumerating configurations with smallest-K sizes,
222
224
* [`ConfigsAll`](@ref) for enumerating all configurations,
@@ -236,9 +238,9 @@ function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=
236
238
elseif property isa SizeMin{1 }
237
239
return post_invert_exponent .(contractx (gp, _x (Tropical{T}; invert= true ); usecuda= usecuda))
238
240
elseif property isa SizeMax
239
- return contractx (gp, _x (ExtendedTropical{max_k (property), T }; invert= false ); usecuda= usecuda)
241
+ return contractx (gp, _x (ExtendedTropical{max_k (property), Tropical{T} }; invert= false ); usecuda= usecuda)
240
242
elseif property isa SizeMin
241
- return post_invert_exponent .(contractx (gp, _x (ExtendedTropical{max_k (property), T }; invert= true ); usecuda= usecuda))
243
+ return post_invert_exponent .(contractx (gp, _x (ExtendedTropical{max_k (property), Tropical{T} }; invert= true ); usecuda= usecuda))
242
244
elseif property isa CountingAll
243
245
return contractx (gp, one (T); usecuda= usecuda)
244
246
elseif property isa CountingMax{1 }
@@ -251,10 +253,14 @@ function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=
251
253
return post_invert_exponent .(contractx (gp, pre_invert_exponent (TruncatedPoly (ntuple (i-> i == min_k (property) ? one (T) : zero (T), min_k (property)), one (T))); usecuda= usecuda))
252
254
elseif property isa GraphPolynomial
253
255
return graph_polynomial (gp, Val (graph_polynomial_method (property)); usecuda= usecuda, T= T, property. kwargs... )
254
- elseif property isa SingleConfigMax{false }
255
- return solutions (gp, CountingTropical{T,T}; all= false , usecuda= usecuda, )
256
- elseif property isa SingleConfigMin{false }
256
+ elseif property isa SingleConfigMax{1 ,false }
257
+ return solutions (gp, CountingTropical{T,T}; all= false , usecuda= usecuda)
258
+ elseif property isa (SingleConfigMax{K,false } where K)
259
+ return solutions (gp, ExtendedTropical{max_k (property),CountingTropical{T,T}}; all= false , usecuda= usecuda)
260
+ elseif property isa SingleConfigMin{1 ,false }
257
261
return solutions (gp, CountingTropical{T,T}; all= false , usecuda= usecuda, invert= true )
262
+ elseif property isa (SingleConfigMin{K,false } where K)
263
+ return solutions (gp, ExtendedTropical{min_k (property),CountingTropical{T,T}}; all= false , usecuda= usecuda, invert= true )
258
264
elseif property isa ConfigsMax{1 ,false }
259
265
return solutions (gp, CountingTropical{T,T}; all= true , usecuda= usecuda, tree_storage= tree_storage (property))
260
266
elseif property isa ConfigsMin{1 ,false }
@@ -265,10 +271,16 @@ function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=
265
271
return solutions (gp, TruncatedPoly{min_k (property),T,T}; all= true , usecuda= usecuda, invert= true )
266
272
elseif property isa ConfigsAll
267
273
return solutions (gp, Real; all= true , usecuda= usecuda, tree_storage= tree_storage (property))
268
- elseif property isa SingleConfigMax{true }
274
+ elseif property isa SingleConfigMax{1 , true }
269
275
return best_solutions (gp; all= false , usecuda= usecuda, T= T)
270
- elseif property isa SingleConfigMin{true }
276
+ elseif property isa (SingleConfigMax{K,true } where K)
277
+ @warn " bounded `SingleConfigMax` property for `K != 1` is not implemented. Switching to the unbounded version."
278
+ return solve (gp, SingleConfigMax {max_k(property),false} (); T, usecuda)
279
+ elseif property isa SingleConfigMin{1 ,true }
271
280
return best_solutions (gp; all= false , usecuda= usecuda, invert= true , T= T)
281
+ elseif property isa (SingleConfigMin{K,true } where K)
282
+ @warn " bounded `SingleConfigMin` property for `K != 1` is not implemented. Switching to the unbounded version."
283
+ return solve (gp, SingleConfigMin {min_k(property),false} (); T, usecuda)
272
284
elseif property isa ConfigsMax{1 ,true }
273
285
return best_solutions (gp; all= true , usecuda= usecuda, tree_storage= tree_storage (property), T= T)
274
286
elseif property isa ConfigsMin{1 ,true }
@@ -396,10 +408,20 @@ Memory estimation in number of bytes to compute certain `property` of a `problem
396
408
function estimate_memory (problem:: GraphProblem , property:: AbstractProperty ; T= Float64)
397
409
_estimate_memory (tensor_element_type (T, length (labels (problem)), nflavor (problem), property), problem)
398
410
end
399
- function estimate_memory (problem:: GraphProblem , :: Union{SingleConfigMax{true },SingleConfigMin{true }} ; T= Float64)
411
+ function estimate_memory (problem:: GraphProblem , property :: Union{SingleConfigMax{K,BOUNDED },SingleConfigMin{K,BOUNDED }} ; T= Float64) where {K, BOUNDED}
400
412
tc, sc, rw = timespacereadwrite_complexity (problem. code, _size_dict (problem))
401
413
# caching all tensors is equivalent to counting the total number of writes
402
- return ceil (Int, exp2 (rw - 1 )) * sizeof (Tropical{T})
414
+ if K == 1 && BOUNDED
415
+ return ceil (Int, exp2 (rw - 1 )) * sizeof (Tropical{T})
416
+ elseif K == 1 & ! BOUNDED
417
+ n, nf = length (labels (problem)), nflavor (problem)
418
+ return peak_memory (problem. code, _size_dict (problem)) * (sizeof (tensor_element_type (T, n, nf, property)) * K)
419
+ else
420
+ # NOTE: the `K > 1` case does not respect bounding
421
+ n, nf = length (labels (problem)), nflavor (problem)
422
+ TT = tensor_element_type (T, n, nf, property)
423
+ return peak_memory (problem. code, _size_dict (problem)) * (sizeof (tensor_element_type (T, n, nf, SingleConfigMax {1,BOUNDED} ())) * K + sizeof (TT))
424
+ end
403
425
end
404
426
function estimate_memory (problem:: GraphProblem , :: GraphPolynomial{:polynomial} ; T= Float64)
405
427
# this is the upper bound
424
446
425
447
for (PROP, ET) in [
426
448
(:(SizeMax{1 }), :(Tropical{T})), (:(SizeMin{1 }), :(Tropical{T})),
427
- (:(SizeMax{K}), :(ExtendedTropical{K,T})), (:(SizeMin{K}), :(ExtendedTropical{K,T})),
428
- (:(SingleConfigMax{true }), :(Tropical{T})), (:(SingleConfigMin{true }), :(Tropical{T})),
449
+ (:(SizeMax{K}), :(ExtendedTropical{K,Tropical{T}})), (:(SizeMin{K}), :(ExtendedTropical{K,Tropical{T}})),
429
450
(:(CountingAll), :T ), (:(CountingMax{1 }), :(CountingTropical{T,T})), (:(CountingMin{1 }), :(CountingTropical{T,T})),
430
451
(:(CountingMax{K}), :(TruncatedPoly{K,T,T})), (:(CountingMin{K}), :(TruncatedPoly{K,T,T})),
431
452
(:(GraphPolynomial{:finitefield }), :(Mod{N,Int32} where N)), (:(GraphPolynomial{:fft }), :(Complex{T})),
@@ -434,11 +455,17 @@ for (PROP, ET) in [
434
455
@eval tensor_element_type (:: Type{T} , n:: Int , nflavor:: Int , :: $PROP ) where {T,K} = $ ET
435
456
end
436
457
437
- for (PROP, ET) in [(:(SingleConfigMax{false }), :(CountingTropical{T,T})), (:(SingleConfigMin{false }), :(CountingTropical{T,T}))]
438
- @eval function tensor_element_type (:: Type{T} , n:: Int , nflavor:: Int , :: $PROP ) where {T}
439
- sampler_type ($ ET, n, nflavor)
458
+ function tensor_element_type (:: Type{T} , n:: Int , nflavor:: Int , :: PROP ) where {T, K, BOUNDED, PROP<: Union{SingleConfigMax{K,BOUNDED},SingleConfigMin{K,BOUNDED}} }
459
+ if K == 1 && BOUNDED
460
+ return Tropical{T}
461
+ elseif K == 1 && ! BOUNDED
462
+ return sampler_type (CountingTropical{T,T}, n, nflavor)
463
+ else
464
+ # NOTE: the `K > 1` case does not respect bounding
465
+ return sampler_type (ExtendedTropical{K,CountingTropical{T,T}}, n, nflavor)
440
466
end
441
467
end
468
+
442
469
for (PROP, ET) in [
443
470
(:(ConfigsMax{1 }), :(CountingTropical{T,T})), (:(ConfigsMin{1 }), :(CountingTropical{T,T})),
444
471
(:(ConfigsMax{K}), :(TruncatedPoly{K,T,T})), (:(ConfigsMin{K}), :(TruncatedPoly{K,T,T})),
0 commit comments