Weighted Problems
Overview
Many optimization problems involve weights associated with vertices or edges. This example demonstrates how to:
- Define weighted problem instances
- Solve for optimal configurations
- Analyze the energy spectrum of solutions
- Visualize weighted solutions
We'll use the Maximum Weighted Independent Set problem on the Petersen graph as our example.
using GenericTensorNetworks, GenericTensorNetworks.ProblemReductions, Graphs
Create a Petersen graph instance
graph = Graphs.smallgraph(:petersen)
{10, 15} undirected simple Int64 graph
Defining Weighted Problems
Create a weighted independent set problem where each vertex i has weight i
problem = GenericTensorNetwork(IndependentSet(graph, collect(1:10)))
GenericTensorNetwork{IndependentSet{SimpleGraph{Int64}, Int64, Vector{Int64}}, OMEinsum.DynamicNestedEinsum{Int64}, Int64}
- open vertices: Int64[]
- fixed vertices: Dict{Int64, Int64}()
- contraction time = 2^8.044, space = 2^4.0, read-write = 2^8.758
Examine the weights assigned to each vertex
GenericTensorNetworks.weights(problem)
10-element Vector{Int64}:
1
2
3
4
5
6
7
8
9
10
The tensor labels associated with these weights can be accessed via:
ProblemReductions.local_solution_spec(problem.problem)
10-element Vector{ProblemReductions.LocalSolutionSize{Int64}}:
LocalSolutionSize{Int64} on [1]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 1 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [2]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 2 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [3]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 3 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [4]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 4 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [5]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 5 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [6]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 6 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [7]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 7 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [8]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 8 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [9]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 9 │
└───────────────┴──────┘
LocalSolutionSize{Int64} on [10]
┌───────────────┬──────┐
│ Configuration │ Size │
├───────────────┼──────┤
│ [0] │ 0 │
│ [1] │ 10 │
└───────────────┴──────┘
Note: You can use a vector for custom weights or UnitWeight()
for unweighted problems. Most solution space properties that work for unweighted graphs also work for weighted graphs.
Finding Optimal Solutions
Find the maximum weighted independent set:
max_config_weighted = solve(problem, SingleConfigMax())[]
(24.0, ConfigSampler{10, 1, 1}(0100100110))ₜ
Visualizing Solutions
Define vertex layout for visualization
rot15(a, b, i::Int) = cos(2i*π/5)*a + sin(2i*π/5)*b, cos(2i*π/5)*b - sin(2i*π/5)*a
locations = [[rot15(0.0, 60.0, i) for i=0:4]..., [rot15(0.0, 30, i) for i=0:4]...]
10-element Vector{Tuple{Float64, Float64}}:
(0.0, 60.0)
(57.06339097770921, 18.541019662496847)
(35.267115137548394, -48.54101966249684)
(-35.26711513754838, -48.54101966249685)
(-57.06339097770922, 18.541019662496833)
(0.0, 30.0)
(28.531695488854606, 9.270509831248424)
(17.633557568774197, -24.27050983124842)
(-17.63355756877419, -24.270509831248425)
(-28.53169548885461, 9.270509831248416)
Visualize the maximum weighted independent set
show_graph(graph, locations; format=:svg, vertex_colors=
[iszero(max_config_weighted.c.data[i]) ? "white" : "red" for i=1:nv(graph)])
Note: The GraphPolynomial
property is the only solution space property that cannot be defined for general real-weighted graphs (though it works for integer-weighted graphs).
Analyzing the Energy Spectrum
For weighted problems, it's often useful to examine the "energy spectrum" - the distribution of weights across different configurations.
Compute the 10 largest weights and their configurations:
spectrum = solve(problem, SizeMax(10))[]
ExtendedTropical{10, Tropical{Float64}}(Tropical{Float64}[20.0ₜ, 20.0ₜ, 20.0ₜ, 21.0ₜ, 21.0ₜ, 22.0ₜ, 22.0ₜ, 22.0ₜ, 23.0ₜ, 24.0ₜ])
The result is an ExtendedTropical
object containing the ordered weights:
spectrum.orders
10-element Vector{Tropical{Float64}}:
20.0ₜ
20.0ₜ
20.0ₜ
21.0ₜ
21.0ₜ
22.0ₜ
22.0ₜ
22.0ₜ
23.0ₜ
24.0ₜ
Each element in orders
is a Tropical
number representing a solution weight.
Finding Multiple Top Solutions
Find the 5 independent sets with the highest weights:
max5_configs = read_config(solve(problem, SingleConfigMax(5))[])
5-element Vector{StaticBitVector{10, 1}}:
0000100110
0010000011
0101010001
1010000011
0100100110
The return value contains CountingTropical{Float64,ConfigSampler}
objects that store both the weights and configurations.
Visualize these top 5 configurations:
show_configs(graph, locations, [max5_configs[j] for i=1:1, j=1:5]; padding_left=20)
Each configuration represents an independent set with one of the 5 highest total weights.
This page was generated using Literate.jl.