Skip to content

Inconsistent MWIS results between Integer Programming and GenericTensorNetwork #54

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions