13
13
import com .graphhopper .util .EdgeIterator ;
14
14
import gurobi .*;
15
15
16
- import java .util .Arrays ;
17
-
18
16
public class Main {
19
17
20
18
private static Params params ;
@@ -27,33 +25,14 @@ public class Main {
27
25
private static Weighting score ;
28
26
private static FlagEncoder flagEncoder ;
29
27
28
+ // Solver variables
30
29
private static GRBEnv env ;
31
30
private static GRBModel model ;
32
- private static GRBVar [] arcsFwd ;
33
- private static GRBVar [] arcsBwd ;
34
- private static int [] arcBaseIds ;
35
31
36
32
private static void setupSolver () throws GRBException {
37
33
env = new GRBEnv ("osm.log" );
38
34
model = new GRBModel (env );
39
-
40
- AllEdgesIterator edges = graph .getAllEdges ();
41
- int numEdges = edges .getMaxId ();
42
- int numNodes = graph .getNodes ();
43
-
44
- // Make a decision variable "x_i" for every arc in our graph
45
- // x_i: =1 if arc is travelled, 0 otherwise
46
- // Since every edge can be 2 arcs (forward + backward), we keep two lists
47
- arcsFwd = model .addVars (numEdges , GRB .BINARY );
48
- arcsBwd = model .addVars (numEdges , GRB .BINARY );
49
- arcBaseIds = new int [numEdges ];
50
-
51
- // Make a variable for every node in the graph
52
- // verts[i]: = the number of times vertex i is visited
53
- char [] types = new char [numNodes ];
54
- Arrays .fill (types , GRB .INTEGER );
55
- GRBVar [] verts = model .addVars (null , null , null , types ,
56
- null , 0 , numNodes );
35
+ Vars vars = new Vars (graph , model , flagEncoder );
57
36
58
37
// (1a)
59
38
// Objective maximizes total collected score of all roads
@@ -63,51 +42,43 @@ private static void setupSolver() throws GRBException {
63
42
// Limit length of path
64
43
GRBLinExpr maxCost = new GRBLinExpr ();
65
44
45
+ AllEdgesIterator edges = graph .getAllEdges ();
66
46
while (edges .next ()) {
67
- int edgeId = edges .getEdge ();
68
- arcBaseIds [edgeId ] = edges .getBaseNode (); // Record the original base ID to keep direction
69
- GRBVar fwd = arcsFwd [edgeId ];
70
- GRBVar bwd = arcsBwd [edgeId ];
71
- double edgeScore = score .calcWeight (edges , false , edgeId );
47
+ double edgeScore = score .calcWeight (edges , false , edges .getEdge ());
72
48
double edgeDist = edges .getDistance ();
73
49
74
- if (edges .isForward (flagEncoder )) {
75
- objective .addTerm (edgeScore , fwd );
76
- maxCost .addTerm (edgeDist , fwd );
77
- } else {
78
- fwd .set (GRB .DoubleAttr .UB , 0 );
79
- }
50
+ GRBVar forward = vars .getArc (edges );
51
+ GRBVar backward = vars .getComplementArc (edges );
80
52
81
- if (edges .isBackward (flagEncoder )) {
82
- objective .addTerm (edgeScore , bwd );
83
- maxCost .addTerm (edgeDist , bwd );
84
- } else {
85
- bwd .set (GRB .DoubleAttr .UB , 0 );
86
- }
53
+ objective .addTerm (edgeScore , forward );
54
+ objective .addTerm (edgeScore , backward );
55
+ maxCost .addTerm (edgeDist , forward );
56
+ maxCost .addTerm (edgeDist , backward );
87
57
88
58
// (1j)
89
59
GRBLinExpr arcConstraint = new GRBLinExpr ();
90
- arcConstraint .addTerm (1 , fwd );
91
- arcConstraint .addTerm (1 , bwd );
60
+ arcConstraint .addTerm (1 , forward );
61
+ arcConstraint .addTerm (1 , backward );
92
62
model .addConstr (arcConstraint , GRB .LESS_EQUAL , 1 , "arc_constraint" );
93
63
}
94
64
95
65
model .setObjective (objective , GRB .MAXIMIZE );
96
66
model .addConstr (maxCost , GRB .LESS_EQUAL , params .getMaxCost (), "max_cost" );
97
67
68
+ int numNodes = graph .getNodes ();
98
69
for (int i = 0 ; i < numNodes ; i ++) {
99
70
// (1d)
100
71
GRBLinExpr edgeCounts = new GRBLinExpr ();
101
72
IntHashSet incomingIds = new IntHashSet ();
102
73
EdgeIterator incoming = graphUtils .incomingEdges (i );
103
74
while (incoming .next ()) {
104
75
incomingIds .add (incoming .getEdge ());
105
- edgeCounts .addTerm (1 , getArc (incoming ));
76
+ edgeCounts .addTerm (1 , vars . getArc (incoming ));
106
77
}
107
78
108
79
EdgeIterator outgoing = graphUtils .outgoingEdges (i );
109
80
while (outgoing .next ()) {
110
- GRBVar arc = getArc (outgoing );
81
+ GRBVar arc = vars . getArc (outgoing );
111
82
// Check if we already recorded it as an incoming edge
112
83
if (incomingIds .contains (outgoing .getEdge ())) {
113
84
edgeCounts .remove (arc );
@@ -122,29 +93,19 @@ private static void setupSolver() throws GRBException {
122
93
GRBLinExpr vertexVisits = new GRBLinExpr ();
123
94
outgoing = graphUtils .outgoingEdges (i );
124
95
while (outgoing .next ()) {
125
- vertexVisits .addTerm (1 , getArc (outgoing ));
96
+ vertexVisits .addTerm (1 , vars . getArc (outgoing ));
126
97
}
127
- vertexVisits .addTerm (-1 , verts [ i ] );
98
+ vertexVisits .addTerm (-1 , vars . getVertex ( i ) );
128
99
model .addConstr (vertexVisits , GRB .EQUAL , 0 , "vertex_visits" );
129
100
}
130
101
131
102
// (1h)/(1i)
132
103
// Start vertex can only be visited once
133
- GRBVar startNode = verts [ START_NODE_ID ] ;
104
+ GRBVar startNode = vars . getVertex ( START_NODE_ID ) ;
134
105
startNode .set (GRB .DoubleAttr .LB , 1 );
135
106
startNode .set (GRB .DoubleAttr .UB , 1 );
136
107
}
137
108
138
- private static GRBVar getArc (EdgeIterator edge ) {
139
- int edgeId = edge .getEdge ();
140
- int baseNode = edge .getBaseNode ();
141
- if (baseNode == arcBaseIds [edgeId ]) {
142
- return arcsFwd [edgeId ];
143
- } else {
144
- return arcsBwd [edgeId ];
145
- }
146
- }
147
-
148
109
private static void runSolver () throws GRBException {
149
110
System .out .println ("Max cost: " + params .getMaxCost ());
150
111
System .out .println ("Start position: " + params .getStartLat () + ", " + params .getStartLon () +
0 commit comments