forked from burakbayramli/books
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFlowEdge.java
188 lines (172 loc) · 7.41 KB
/
FlowEdge.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*************************************************************************
* Compilation: javac FlowEdge.java
* Execution: java FlowEdge
*
* Capacitated edge with a flow in a flow network.
*
*************************************************************************/
/**
* The <tt>FlowEdge</tt> class represents a capacitated edge with a
* flow in a {@link FlowNetwork}. Each edge consists of two integers
* (naming the two vertices), a real-valued capacity, and a real-valued
* flow. The data type provides methods for accessing the two endpoints
* of the directed edge and the weight. It also provides methods for
* changing the amount of flow on the edge and determining the residual
* capacity of the edge.
* <p>
* For additional documentation, see <a href="http://algs4.cs.princeton.edu/64maxflow">Section 6.4</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*/
public class FlowEdge {
private final int v; // from
private final int w; // to
private final double capacity; // capacity
private double flow; // flow
/**
* Initializes an edge from vertex <tt>v</tt> to vertex <tt>w</tt> with
* the given <tt>capacity</tt> and zero flow.
* @param v the tail vertex
* @param w the head vertex
* @param capacity the capacity of the edge
* @throws java.lang.IndexOutOfBoundsException if either <tt>v</tt> or <tt>w</tt>
* is a negative integer
* @throws java.lang.IllegalArgumentException if <tt>capacity</tt> is negative
*/
public FlowEdge(int v, int w, double capacity) {
if (v < 0) throw new IndexOutOfBoundsException("Vertex name must be a nonnegative integer");
if (w < 0) throw new IndexOutOfBoundsException("Vertex name must be a nonnegative integer");
if (!(capacity >= 0.0)) throw new IllegalArgumentException("Edge capacity must be nonnegaitve");
this.v = v;
this.w = w;
this.capacity = capacity;
this.flow = 0.0;
}
/**
* Initializes an edge from vertex <tt>v</tt> to vertex <tt>w</tt> with
* the given <tt>capacity</tt> and <tt>flow</tt>.
* @param v the tail vertex
* @param w the head vertex
* @param capacity the capacity of the edge
* @param flow the flow on the edge
* @throws java.lang.IndexOutOfBoundsException if either <tt>v</tt> or <tt>w</tt>
* is a negative integer
* @throws java.lang.IllegalArgumentException if <tt>capacity</tt> is negative
* @throws java.lang.IllegalArgumentException unless <tt>flow</tt> is between
* <tt>0.0</tt> and <tt>capacity</tt>.
*/
public FlowEdge(int v, int w, double capacity, double flow) {
if (v < 0) throw new IndexOutOfBoundsException("Vertex name must be a nonnegative integer");
if (w < 0) throw new IndexOutOfBoundsException("Vertex name must be a nonnegative integer");
if (!(capacity >= 0.0)) throw new IllegalArgumentException("Edge capacity must be nonnegaitve");
if (!(flow <= capacity)) throw new IllegalArgumentException("Flow exceeds capacity");
if (!(flow >= 0.0)) throw new IllegalArgumentException("Flow must be nonnnegative");
this.v = v;
this.w = w;
this.capacity = capacity;
this.flow = flow;
}
/**
* Initializes a flow edge from another flow edge.
* @param e the edge to copy
*/
public FlowEdge(FlowEdge e) {
this.v = e.v;
this.w = e.w;
this.capacity = e.capacity;
this.flow = e.flow;
}
/**
* Returns the tail vertex of the edge.
* @return the tail vertex of the edge
*/
public int from() {
return v;
}
/**
* Returns the head vertex of the edge.
* @return the head vertex of the edge
*/
public int to() {
return w;
}
/**
* Returns the capacity of the edge.
* @return the capacity of the edge
*/
public double capacity() {
return capacity;
}
/**
* Returns the flow on the edge.
* @return the flow on the edge
*/
public double flow() {
return flow;
}
/**
* Returns the endpoint of the edge that is different from the given vertex
* (unless the edge represents a self-loop in which case it returns the same vertex).
* @param vertex one endpoint of the edge
* @return the endpoint of the edge that is different from the given vertex
* (unless the edge represents a self-loop in which case it returns the same vertex)
* @throws java.lang.IllegalArgumentException if <tt>vertex</tt> is not one of the endpoints
* of the edge
*/
public int other(int vertex) {
if (vertex == v) return w;
else if (vertex == w) return v;
else throw new IllegalArgumentException("Illegal endpoint");
}
/**
* Returns the residual capacity of the edge in the direction
* to the given <tt>vertex</tt>.
* @param vertex one endpoint of the edge
* @return the residual capacity of the edge in the direction to the given vertex
* If <tt>vertex</tt> is the tail vertex, the residual capacity equals
* <tt>capacity() - flow()</tt>; if <tt>vertex</tt> is the head vertex, the
* residual capacity equals <tt>flow()</tt>.
* @throws java.lang.IllegalArgumentException if <tt>vertex</tt> is not one of the endpoints
* of the edge
*/
public double residualCapacityTo(int vertex) {
if (vertex == v) return flow; // backward edge
else if (vertex == w) return capacity - flow; // forward edge
else throw new IllegalArgumentException("Illegal endpoint");
}
/**
* Increases the flow on the edge in the direction to the given vertex.
* If <tt>vertex</tt> is the tail vertex, this increases the flow on the edge by <tt>delta</tt>;
* if <tt>vertex</tt> is the head vertex, this decreases the flow on the edge by <tt>delta</tt>.
* @param vertex one endpoint of the edge
* @throws java.lang.IllegalArgumentException if <tt>vertex</tt> is not one of the endpoints
* of the edge
* @throws java.lang.IllegalArgumentException if <tt>delta</tt> makes the flow on
* on the edge either negative or larger than its capacity
* @throws java.lang.IllegalArgumentException if <tt>delta</tt> is <tt>NaN</tt>
*/
public void addResidualFlowTo(int vertex, double delta) {
if (vertex == v) flow -= delta; // backward edge
else if (vertex == w) flow += delta; // forward edge
else throw new IllegalArgumentException("Illegal endpoint");
if (Double.isNaN(delta)) throw new IllegalArgumentException("Change in flow = NaN");
if (!(flow >= 0.0)) throw new IllegalArgumentException("Flow is negative");
if (!(flow <= capacity)) throw new IllegalArgumentException("Flow exceeds capacity");
}
/**
* Returns a string representation of the edge.
* @return a string representation of the edge
*/
public String toString() {
return v + "->" + w + " " + flow + "/" + capacity;
}
/**
* Unit tests the <tt>FlowEdge</tt> data type.
*/
public static void main(String[] args) {
FlowEdge e = new FlowEdge(12, 23, 3.14);
StdOut.println(e);
}
}