Search code examples
pythoniterationgraph-theorymathematical-optimizationcplex

Python CPLEX API: Conditional iteration on binary variables


I'm working on a graph-theoretical problem. Suppose we want to find a Graph G=(V,E), such that there exists a partition X of V containing at most k equivalence classes. A variable p_S takes value 1 exactly when S is a member of partition X, and zero otherwise. So we have a constraint that the sum over all variables p_S is at most k, for all subsets S of V.

So what I want to do is to iterate over all p_S that have value 1 and define more constraints based on the elements I draw out of S. These constraints would preserve that members of an equivalence class share some mutual property.

Is it possible to access the p_S variables that way and how could I do it?

ALternatively I know I can do without iterating on my binary variables if I'm allowed to use binary variables as coefficients in my constraints. Is that possible?

Thanks in advance!


Solution

  • The CPLEX Python API is index based. To iterate over all binary variables with a solution value set to 1 we need to query the variables types and the solution values and filter accordingly. Here is a simple example:

    import sys
    import cplex
    
    
    def main(modelfile):
        # Read in a model file.
        c = cplex.Cplex()
        c.read(modelfile)
    
        # Solve the model and print the solution and status.
        c.solve()
        print("Solution value:", c.solution.get_objective_value())
        print("Solution status: {0} ({1})".format(
            c.solution.get_status_string(),
            c.solution.get_status()))
    
        # Display all binary variables that have a solution value of 1.
        types = c.variables.get_types()
        nvars = c.variables.get_num()
        binvars = [idx for idx, typ
                   in zip(range(nvars), c.variables.get_types())
                   if typ == c.variables.type.binary]
        inttol = c.parameters.mip.tolerances.integrality.get()
        binvars_at_one = [idx for idx, val
                          in zip(binvars, c.solution.get_values(binvars))
                          if abs(val - 1.0) <= inttol]
        print("Binary variables with a solution value equal to one:")
        for varname in c.variables.get_names(binvars_at_one):
            print("  ", varname)
    
    
    if __name__ == "__main__":
        if len(sys.argv) != 2:
            raise ValueError("usage: {0} <model>".format(sys.argv[0]))
        main(sys.argv[1])
    

    For more, see the documentation for Cplex.variables and Cplex.solution.