The first several PROC OPTMODEL statements declare index sets and read the input data:
proc optmodel;
set <num,num> EDGES {1..2};
read data edge_data1 into EDGES[1]=[i j];
read data edge_data2 into EDGES[2]=[i j];
The following statements declare and initialize the NODES[g] sets and then use the INTER operator to store their elements in increasing order:
set NODES {g in 1..2} init union {<i,j> in EDGES[g]} {i,j};
for {g in 1..2} NODES[g] = 1..card(NODES[g]) inter NODES[g];
The following statements declare the remaining sets:
set IJ = NODES[1] cross NODES[2];
set EDGE_PAIRS = {<i,j> in IJ, <k,l> in IJ: i < k and j ne l and
(<i,k> in EDGES[1]) and (<j,l> in EDGES[2])};
The following model declaration statements correspond directly to the mathematical programming formulation that is described earlier:
/* Assign[i,j] = 1 if node i in NODES[1] assigned to node j in NODES[2] */
var Assign {IJ} binary;
/* IsCorrespondingEdge[i,j,k,l] = 1 if edge <i,k> in EDGES[1]
corresponds to edge <j,l> in EDGES[2] */
var IsCorrespondingEdge {EDGE_PAIRS} binary;
/* maximize number of corresponding edges */
max NumCorrespondingEdges =
sum {<i,j,k,l> in EDGE_PAIRS} IsCorrespondingEdge[i,j,k,l];
/* assign each i to at most one j */
con Assign_i {i in NODES[1]}:
sum {<(i),j> in IJ} Assign[i,j] <= 1;
/* assign at most one i to each j */
con Assign_j {j in NODES[2]}:
sum {<i,(j)> in IJ} Assign[i,j] <= 1;
/* disallow crossing edges */
con NoCrossover {<i,j> in IJ, <k,l> in IJ: i < k and j > l}:
Assign[i,j] + Assign[k,l] <= 1;
/* if IsCorrespondingEdge[i,j,k,l] = 1 then Assign[i,j] = Assign[k,l] = 1 */
con Corresponding1 {<i,j,k,l> in EDGE_PAIRS}:
IsCorrespondingEdge[i,j,k,l] <= Assign[i,j];
con Corresponding2 {<i,j,k,l> in EDGE_PAIRS}:
IsCorrespondingEdge[i,j,k,l] <= Assign[k,l];
The following statements call the mixed integer linear programming solver and use the FILE and PUT statements to write log output to the listing:
solve;
file print;
for {<i,j> in IJ: Assign[i,j].sol > 0.5}
put ('Node '||i||' in graph 1 corresponds to node '||j||' in graph 2.');
for {<i,j,k,l> in EDGE_PAIRS: IsCorrespondingEdge[i,j,k,l].sol > 0.5} do;
put ('Edge ('||i||','||k||') in graph 1 corresponds to') @@;
put ('edge ('||j||','||l||') in graph 2.');
end;
quit;
Figure 29.5 shows the output from the mixed integer linear programming solver.
Figure 29.5: Output from Mixed Integer Linear Programming Solver
| Problem Summary | |
|---|---|
| Objective Sense | Maximization |
| Objective Function | NumCorrespondingEdges |
| Objective Type | Linear |
| Number of Variables | 179 |
| Bounded Above | 0 |
| Bounded Below | 0 |
| Bounded Below and Above | 179 |
| Free | 0 |
| Fixed | 0 |
| Binary | 179 |
| Integer | 0 |
| Number of Constraints | 2160 |
| Linear LE (<=) | 2160 |
| Linear EQ (=) | 0 |
| Linear GE (>=) | 0 |
| Linear Range | 0 |
| Constraint Coefficients | 4478 |
| Performance Information | |
|---|---|
| Execution Mode | Single-Machine |
| Number of Threads | 1 |
| Solution Summary | |
|---|---|
| Solver | MILP |
| Algorithm | Branch and Cut |
| Objective Function | NumCorrespondingEdges |
| Solution Status | Optimal |
| Objective Value | 5 |
| Relative Gap | 0 |
| Absolute Gap | 0 |
| Primal Infeasibility | 0 |
| Bound Infeasibility | 0 |
| Integer Infeasibility | 0 |
| Best Bound | 5 |
| Nodes | 1 |
| Iterations | 475 |
| Presolve Time | 0.08 |
| Solution Time | 0.19 |
Figure 29.6 shows the output from the PUT statements.
Figure 29.6: Output from PUT Statements
The OPTMODEL Procedure
Node 1 in graph 1 corresponds to node 2 in graph 2.
Node 2 in graph 1 corresponds to node 3 in graph 2.
Node 3 in graph 1 corresponds to node 4 in graph 2.
Node 4 in graph 1 corresponds to node 6 in graph 2.
Node 5 in graph 1 corresponds to node 7 in graph 2.
Node 6 in graph 1 corresponds to node 8 in graph 2.
Node 8 in graph 1 corresponds to node 10 in graph 2.
Node 9 in graph 1 corresponds to node 11 in graph 2.
Edge (1,2) in graph 1 corresponds to edge (2,3) in graph 2.
Edge (3,4) in graph 1 corresponds to edge (4,6) in graph 2.
Edge (3,5) in graph 1 corresponds to edge (4,7) in graph 2.
Edge (5,6) in graph 1 corresponds to edge (7,8) in graph 2.
Edge (8,9) in graph 1 corresponds to edge (10,11) in graph 2.
|
Figure 29.7 shows the optimal solution as a comparison between contact maps, with the matched nodes indicated by dashed lines and the edges of the isomorphic subgraphs highlighted.