@@ -109,10 +109,10 @@ GraphPolynomial(; method::Symbol = :finitefield, kwargs...) = GraphPolynomial{me
109109graph_polynomial_method (:: GraphPolynomial{METHOD} ) where METHOD = METHOD
110110
111111"""
112- SingleConfigMax{BOUNDED} <: AbstractProperty
113- SingleConfigMax(; bounded=false)
112+ SingleConfigMax{K, BOUNDED} <: AbstractProperty
113+ SingleConfigMax(k::Int ; bounded=false)
114114
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.
116116
117117* The corresponding data type is [`CountingTropical{Float64,<:ConfigSampler}`](@ref) if `BOUNDED` is `false`, [`Tropical`](@ref) otherwise.
118118* Weighted graph problems is supported.
@@ -122,14 +122,15 @@ Keyword Arguments
122122----------------------------
123123* `bounded`, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
124124"""
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
127128
128129"""
129- SingleConfigMin{BOUNDED} <: AbstractProperty
130- SingleConfigMin(; bounded=false)
130+ SingleConfigMin{K, BOUNDED} <: AbstractProperty
131+ SingleConfigMin(k::Int ; bounded=false)
131132
132- Finding single "worst" solution.
133+ Finding single solution with smallest-K size .
133134
134135* The corresponding data type is inverted [`CountingTropical{Float64,<:ConfigSampler}`](@ref) if `BOUNDED` is `false`, inverted [`Tropical`](@ref) otherwise.
135136* Weighted graph problems is supported.
@@ -139,8 +140,9 @@ Keyword Arguments
139140----------------------------
140141* `bounded`, if it is true, use bounding trick (or boolean gradients) to reduce the working memory to store intermediate configurations.
141142"""
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
144146
145147"""
146148 ConfigsAll{TREESTORAGE} <:AbstractProperty
@@ -216,7 +218,7 @@ Positional Arguments
216218 * [`CountingAll`](@ref) for counting all configurations,
217219 * [`GraphPolynomial`](@ref) for evaluating the graph polynomial,
218220
219- * [`SingleConfigMax`](@ref) for finding one maximum configuration,
221+ * [`SingleConfigMax`](@ref) for finding one maximum configuration for each size ,
220222 * [`ConfigsMax`](@ref) for enumerating configurations with largest-K sizes,
221223 * [`ConfigsMin`](@ref) for enumerating configurations with smallest-K sizes,
222224 * [`ConfigsAll`](@ref) for enumerating all configurations,
@@ -236,9 +238,9 @@ function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=
236238 elseif property isa SizeMin{1 }
237239 return post_invert_exponent .(contractx (gp, _x (Tropical{T}; invert= true ); usecuda= usecuda))
238240 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)
240242 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))
242244 elseif property isa CountingAll
243245 return contractx (gp, one (T); usecuda= usecuda)
244246 elseif property isa CountingMax{1 }
@@ -251,10 +253,14 @@ function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=
251253 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))
252254 elseif property isa GraphPolynomial
253255 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 }
257261 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 )
258264 elseif property isa ConfigsMax{1 ,false }
259265 return solutions (gp, CountingTropical{T,T}; all= true , usecuda= usecuda, tree_storage= tree_storage (property))
260266 elseif property isa ConfigsMin{1 ,false }
@@ -265,10 +271,16 @@ function solve(gp::GraphProblem, property::AbstractProperty; T=Float64, usecuda=
265271 return solutions (gp, TruncatedPoly{min_k (property),T,T}; all= true , usecuda= usecuda, invert= true )
266272 elseif property isa ConfigsAll
267273 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 }
269275 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 }
271280 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)
272284 elseif property isa ConfigsMax{1 ,true }
273285 return best_solutions (gp; all= true , usecuda= usecuda, tree_storage= tree_storage (property), T= T)
274286 elseif property isa ConfigsMin{1 ,true }
@@ -396,10 +408,20 @@ Memory estimation in number of bytes to compute certain `property` of a `problem
396408function estimate_memory (problem:: GraphProblem , property:: AbstractProperty ; T= Float64)
397409 _estimate_memory (tensor_element_type (T, length (labels (problem)), nflavor (problem), property), problem)
398410end
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}
400412 tc, sc, rw = timespacereadwrite_complexity (problem. code, _size_dict (problem))
401413 # 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
403425end
404426function estimate_memory (problem:: GraphProblem , :: GraphPolynomial{:polynomial} ; T= Float64)
405427 # this is the upper bound
424446
425447for (PROP, ET) in [
426448 (:(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}})),
429450 (:(CountingAll), :T ), (:(CountingMax{1 }), :(CountingTropical{T,T})), (:(CountingMin{1 }), :(CountingTropical{T,T})),
430451 (:(CountingMax{K}), :(TruncatedPoly{K,T,T})), (:(CountingMin{K}), :(TruncatedPoly{K,T,T})),
431452 (:(GraphPolynomial{:finitefield }), :(Mod{N,Int32} where N)), (:(GraphPolynomial{:fft }), :(Complex{T})),
@@ -434,11 +455,17 @@ for (PROP, ET) in [
434455 @eval tensor_element_type (:: Type{T} , n:: Int , nflavor:: Int , :: $PROP ) where {T,K} = $ ET
435456end
436457
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)
440466 end
441467end
468+
442469for (PROP, ET) in [
443470 (:(ConfigsMax{1 }), :(CountingTropical{T,T})), (:(ConfigsMin{1 }), :(CountingTropical{T,T})),
444471 (:(ConfigsMax{K}), :(TruncatedPoly{K,T,T})), (:(ConfigsMin{K}), :(TruncatedPoly{K,T,T})),
0 commit comments