Search code examples
algorithmlinear-programmingpyomomixed-integer-programming

Ilp - count number of times variables received a value


In an ILP, is it possible to have a variable whose value will be the number of variables with value N?

N is a bounded integer, with lower bound 1.

Thank you


Solution

  • This achieves the goal. It is written in pyomo but should be fairly easy to translate to other frameworks.

    Code:

    # magic number counter
    
    import pyomo.environ as pyo
    
    M = 100
    magic_number=7
    
    m = pyo.ConcreteModel()
    
    m.I = pyo.Set(initialize=[1,2,3,4])
    
    m.x    = pyo.Var(m.I, domain=pyo.NonNegativeIntegers, bounds=(1, M))
    m.magic = pyo.Var(m.I, domain=pyo.Binary)
    
    # obj:  max sum of x, plus some sugar for magic numbers's
    
    m.obj = pyo.Objective(expr=sum(m.x[i] + 0.1*m.magic[i] for i in m.I), sense=pyo.maximize)
    
    # constraints
    
    m.sum_limit = pyo.Constraint(expr=pyo.sum_product(m.x) <= 19)
    
    @m.Constraint(m.I)
    def linking_1(m, i):
        return m.x[i] <= magic_number + (1 - m.magic[i]) * M
    
    @m.Constraint(m.I)
    def linking_2(m, i):
        return m.x[i] >= magic_number * m.magic[i]
    
    solver = pyo.SolverFactory('glpk')
    soln = solver.solve(m)
    print(soln)
    m.display()
    
    print(f"\nmagic numbers {magic_number}'s produced: {pyo.value(pyo.sum_product(m.magic))}")
    

    Output:

    Problem: 
    - Name: unknown
      Lower bound: 19.2
      Upper bound: 19.2
      Number of objectives: 1
      Number of constraints: 10
      Number of variables: 9
      Number of nonzeros: 21
      Sense: maximize
    Solver: 
    - Status: ok
      Termination condition: optimal
      Statistics: 
        Branch and bound: 
          Number of bounded subproblems: 5
          Number of created subproblems: 5
      Error rc: 0
      Time: 0.005478858947753906
    Solution: 
    - number of solutions: 0
      number of solutions displayed: 0
    
    Model unknown
    
      Variables:
        x : Size=4, Index=I
            Key : Lower : Value : Upper : Fixed : Stale : Domain
              1 :     1 :   7.0 :   100 : False : False : NonNegativeIntegers
              2 :     1 :   4.0 :   100 : False : False : NonNegativeIntegers
              3 :     1 :   7.0 :   100 : False : False : NonNegativeIntegers
              4 :     1 :   1.0 :   100 : False : False : NonNegativeIntegers
        magic : Size=4, Index=I
            Key : Lower : Value : Upper : Fixed : Stale : Domain
              1 :     0 :   1.0 :     1 : False : False : Binary
              2 :     0 :   0.0 :     1 : False : False : Binary
              3 :     0 :   1.0 :     1 : False : False : Binary
              4 :     0 :   0.0 :     1 : False : False : Binary
    
      Objectives:
        obj : Size=1, Index=None, Active=True
            Key  : Active : Value
            None :   True : 19.200000000000003
    
      Constraints:
        sum_limit : Size=1
            Key  : Lower : Body : Upper
            None :  None : 19.0 :  19.0
        linking_1 : Size=4
            Key : Lower : Body   : Upper
              1 :  None :    0.0 :   0.0
              2 :  None : -103.0 :   0.0
              3 :  None :    0.0 :   0.0
              4 :  None : -106.0 :   0.0
        linking_2 : Size=4
            Key : Lower : Body : Upper
              1 :  None :  0.0 :   0.0
              2 :  None : -4.0 :   0.0
              3 :  None :  0.0 :   0.0
              4 :  None : -1.0 :   0.0
    
    magic numbers 7's produced: 2.0