Skip to content

Inconsistent MWIS results between Integer Programming and GenericTensorNetwork #54

@isPANN

Description

@isPANN

@GiggleLiu I observed inconsistent maximum weighted independent set (MWIS) solutions between two methods applied to the same graph and weight vector:

  • Method 1: Integer Programming (JuMP + GLPK)
  • Method 2: GenericTensorNetwork(IndependentSet(...))

The two methods produce different sets of optimal configurations, even though both should theoretically enumerate all ground states with maximum weight.


🧪 Example (Requires code that has not yet been merged)

House Graph Setup

using UnitDiskMapping, Graphs, GenericTensorNetworks, LinearAlgebra

graph = smallgraph(:house)
triangular_weighted_res = map_graph(TriangularWeighted(), graph; vertex_order=MinhThiTrick())
g, _ = graph_and_weights(triangular_weighted_res.grid_graph)

source_weights = fill(0.1, nv(graph))
mapped_weights10 = map_weights(triangular_weighted_res, source_weights)
pins = [82, 63, 28, 5, 1]  # original node locations

✅ Method 1: Integer Programming

using JuMP, GLPK

function all_maximum_weighted_independent_sets(g::SimpleGraph, weights::Vector{Float64})
    n = nv(g)
    @assert length(weights) == n

    model = Model(GLPK.Optimizer)
    set_silent(model)
    @variable(model, x[1:n], Bin)

    for e in edges(g)
        @constraint(model, x[src(e)] + x[dst(e)] <= 1)
    end

    @objective(model, Max, sum(weights[i] * x[i] for i in 1:n))
    optimize!(model)

    if termination_status(model) != MOI.OPTIMAL
        error("No optimal solution found")
    end

    max_weight = objective_value(model)
    solutions = Set{Vector{Int}}()

    while true
        if termination_status(model) != MOI.OPTIMAL || abs(objective_value(model) - max_weight) > 1e-6
            break
        end
        current = [i for i in 1:n if value(x[i])  0.5]
        push!(solutions, sort(current))
        @constraint(model, sum(x[i] for i in current) <= length(current) - 1)
        optimize!(model)
    end

    return collect(solutions), max_weight
end

res_ip, _ = all_maximum_weighted_independent_sets(g, mapped_weights10)

bit_vectors_ip = []
for c in res_ip
    bit_vector = zeros(Int, nv(graph))
    for (j, pin) in enumerate(pins)
        if pin in c
            bit_vector[j] = 1
        end
    end
    push!(bit_vectors_ip, bit_vector)
end

❓ Method 2: GenericTensorNetwork

res_gtn = solve(GenericTensorNetwork(IndependentSet(g, mapped_weights10)), ConfigsMax())[].c.data

bit_vectors_gtn = []
for c in res_gtn
    bit_vector = map_config_back(triangular_weighted_res, c)
    push!(bit_vectors_gtn, bit_vector)
end

🧮 Observed Result

  • bit_vectors_ip and bit_vectors_gtn contain different configurations.
bit_vector_ip =  
 [0, 1, 1, 0, 0]
 [1, 0, 0, 0, 1]
 [1, 0, 0, 1, 0]
 [0, 1, 0, 0, 1]

bit_vector_gtn = 
 [1, 0, 0, 1, 0]
 [0, 1, 1, 0, 0]

Some MWIS solutions returned by the Integer Programming method are missing from the GTN result.

  • Both of the two methods return right result on the source graph.
res, max_weight = all_maximum_weighted_independent_sets(graph, source_weights)
solve(GenericTensorNetwork(IndependentSet(graph, source_weights)), ConfigsMax())[]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions