Skip to content

Commit c0d23c4

Browse files
authored
Merge pull request #80 from SECQUOIA/79-deprecated-filter-callback-signature-block-value
Deprecated `filter =` callback signature `(block, *value)`
2 parents 9694230 + caa3cff commit c0d23c4

File tree

2 files changed

+136
-19
lines changed

2 files changed

+136
-19
lines changed

gdplib/mod_hens/modular_discrete.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def build_modular_option(cafaro_approx, num_stages):
8181
"""
8282
m = build_model(cafaro_approx, num_stages)
8383

84-
# Optimize for the least cost configuration across all stages and matche
84+
# Optimize for the least cost configuration across all stages and matches
8585
for hot, cold in m.valid_matches:
8686
lowest_price = float('inf')
8787
for size in sorted(m.possible_sizes, reverse=True):

gdplib/water_network/wnd.py

Lines changed: 135 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
The user can create each instance like this:
1717
1818
build_model(approximation='none')
19-
build_model(approximation='quadratic')
19+
build_model(approximation='quadratic_nonzero_origin')
20+
build_model(approximation='quadratic_zero_origin')
2021
build_model(approximation='piecewise')
2122
2223
The general model description can be summarized as follows:
@@ -83,7 +84,7 @@
8384
# TU mass balances in the disjunct.
8485

8586

86-
def build_model(approximation='quadratic'):
87+
def build_model(approximation='none'):
8788
"""
8889
Builds a Pyomo ConcreteModel for Water Network Design.
8990
Generates a Pyomo model for the water network design problem with the specified approximation for the capital cost term of the active treatment units.
@@ -135,16 +136,38 @@ def build_model(approximation='quadratic'):
135136

136137
m.mixers = pyo.Set(doc="Set of mixers", within=m.units, initialize=['dm'] | m.inTU)
137138

139+
def _streams_filter(m, val):
140+
"""
141+
This function filters the streams based on one-to-one port pairing.
142+
The expression re.findall(r'\d+', x) returns a list of all the digits in the string x.
143+
The expression re.findall(r'\d+', y) returns a list of all the digits in the string y.
144+
The function returns True if the ports digits are the same, False otherwise.
145+
146+
Parameters
147+
----------
148+
m : Pyomo concrete model
149+
GDP model for water network design
150+
val : tuple
151+
Tuple of inlet and outlet ports, x are the source ports and y are the sink ports
152+
153+
Returns
154+
-------
155+
Boolean
156+
True if the ports digits are the same, False otherwise
157+
"""
158+
x, y = val
159+
return re.findall(r'\d+', x) == re.findall(r'\d+', y)
160+
138161
m.MU_TU_streams = pyo.Set(
139162
doc="MU to TU 1-1 port pairing",
140163
initialize=m.inTU * m.TU,
141-
filter=lambda _, x, y: re.findall(r'\d+', x) == re.findall(r'\d+', y),
164+
filter=_streams_filter,
142165
)
143166

144167
m.TU_SU_streams = pyo.Set(
145168
doc="TU to SU 1-1 port pairing",
146169
initialize=m.TU * m.outTU,
147-
filter=lambda _, x, y: re.findall(r'\d+', x) == re.findall(r'\d+', y),
170+
filter=_streams_filter,
148171
)
149172

150173
m.TU_streams = pyo.Set(
@@ -155,7 +178,7 @@ def build_model(approximation='quadratic'):
155178
m.feed_streams = pyo.Set(
156179
doc="Feed to FSU 1-1 port pairing",
157180
initialize=m.feed * m.FSU,
158-
filter=lambda _, x, y: re.findall(r'\d+', x) == re.findall(r'\d+', y),
181+
filter=_streams_filter,
159182
)
160183

161184
m.streams = pyo.Set(
@@ -168,17 +191,63 @@ def build_model(approximation='quadratic'):
168191
| [('dm', 'sink')],
169192
)
170193

194+
def _from_stream_filter(m, val):
195+
"""
196+
This function filters the streams based on the ports.
197+
The function returns True if the inlet port is a splitter or the inlet and outlet ports are the discharge mixer and the sink, respectively, False otherwise.
198+
199+
Parameters
200+
----------
201+
m : Pyomo concrete model
202+
GDP model for water network design
203+
x : str
204+
The source port
205+
y : str
206+
The sink port
207+
208+
Returns
209+
-------
210+
Boolean
211+
True if the inlet port is a splitter or the inlet and outlet ports are the discharge mixer and the sink, respectively, False otherwise
212+
"""
213+
x, y = val
214+
return x in m.splitters or (x, y) == ('dm', 'sink')
215+
171216
m.from_splitters = pyo.Set(
172217
doc='Streams from splitters',
173218
within=m.streams,
174219
initialize=m.streams,
175-
filter=lambda _, x, y: x in m.splitters or (x, y) == ('dm', 'sink'),
220+
filter=_from_stream_filter,
176221
)
222+
223+
def _to_stream_filter(m, val):
224+
"""
225+
This function filters the streams based on the ports.
226+
The function returns True if the outlet port is a splitter or the inlet and outlet ports are part of the feed streams, False otherwise.
227+
The feed streams are the streams from the feed splitters to the mixers.
228+
229+
Parameters
230+
----------
231+
m : Pyomo concrete model
232+
GDP model for water network design
233+
x : str
234+
The source port
235+
y : str
236+
The sink port
237+
238+
Returns
239+
-------
240+
Boolean
241+
True if the outlet port is a splitter or the inlet and outlet ports are part of the feed streams, False otherwise
242+
"""
243+
x, y = val
244+
return y in m.splitters or (x, y) in m.feed_streams
245+
177246
m.to_splitters = pyo.Set(
178247
doc='Streams to splitters',
179248
within=m.streams,
180249
initialize=m.streams,
181-
filter=lambda _, x, y: y in m.splitters or (x, y) in m.feed_streams,
250+
filter=_to_stream_filter,
182251
)
183252

184253
# =============================================================================
@@ -227,7 +296,6 @@ def build_model(approximation='quadratic'):
227296

228297
# Concentration of component j in feedstream i
229298
for j, i, k in m.contaminant * (m.FSU * ['dm'] | m.FSU * m.inTU | m.feed_streams):
230-
# print(j,i,k)
231299
if i in m.feed:
232300
m.conc[j, i, k].fix(feed.loc[k, j])
233301
else:
@@ -460,7 +528,7 @@ def _no_cost(disj):
460528
@m.Disjunction(m.TU)
461529
def unit_exists_or_not(m, unit):
462530
'''Disjunction: Unit exists or not.
463-
This disjunctiont specifies if the treatment unit exists or does not exist.
531+
This disjunction specifies if the treatment unit exists or does not exist.
464532
465533
Parameters
466534
----------
@@ -490,16 +558,61 @@ def unit_exists_or_not(m, unit):
490558

491559
for unit in m.TU:
492560
unit_exists = m.unit_exists[unit]
561+
562+
def _unit_exists_streams_filter(unit_exists, val):
563+
"""
564+
This function filters the streams based on the ports.
565+
The function returns True if the ports are the treatment unit, False otherwise.
566+
567+
Parameters
568+
----------
569+
unit_exists : Pyomo disjunct
570+
Disjunct for the active treatment unit
571+
x : str
572+
The source port
573+
y : str
574+
The sink port
575+
576+
Returns
577+
-------
578+
Boolean
579+
True if either the source or destination port is the treatment unit, False otherwise
580+
"""
581+
x, y = val
582+
return x == unit or y == unit
583+
493584
unit_exists.streams = pyo.Set(
494585
doc="Streams in active TU",
495586
initialize=m.TU_streams,
496-
filter=lambda _, x, y: x == unit or y == unit,
587+
filter=_unit_exists_streams_filter,
497588
)
589+
590+
def _unit_exists_onetoone_filter(unit_exists, val):
591+
"""
592+
This function filters the streams based on the ports.
593+
The function returns True if the ports are the same and the destination port is the treatment unit, False otherwise.
594+
595+
Parameters
596+
----------
597+
unit_exists : Pyomo disjunct
598+
Disjunct for the active treatment unit
599+
x : str
600+
The source port
601+
y : str
602+
The sink port
603+
604+
Returns
605+
-------
606+
Boolean
607+
True if the port if source and destination are the same and the destination is the treatment unit, False otherwise
608+
"""
609+
x, y = val
610+
return re.findall(r'\d+', x) == re.findall(r'\d+', y) and y == unit
611+
498612
unit_exists.MU_TU_streams = pyo.Set(
499613
doc="MU to TU 1-1 port pairing",
500614
initialize=m.inTU * m.TU,
501-
filter=lambda _, x, y: re.findall(r'\d+', x) == re.findall(r'\d+', y)
502-
and y == unit,
615+
filter=_unit_exists_onetoone_filter,
503616
)
504617

505618
unit_exists.flow = pyo.Var(
@@ -579,7 +692,7 @@ def unit_exists_or_not(m, unit):
579692
]
580693
# Setting inlet flowrate bounds for the active treatment units.
581694
unit_exists.flow_bound = pyo.ConstraintList(
582-
doc='Flowrate bounds to/from active RU'
695+
doc='Flowrate bounds to/from active TU'
583696
)
584697
[
585698
unit_exists.flow_bound.add(
@@ -786,10 +899,14 @@ def _func(model, i, j, xp):
786899
@unit_exists.Constraint(doc='Cost active TU')
787900
def costTU(unit_exists):
788901
"""Constraint: Cost of active treatment unit.
789-
The constraint ensures that the cost of the active treatment unit is equal to the sum of an investment cost which is proportional to the total flow to 0.7 exponent and an operating cost which is proportional to the flow.
790-
If approximation is quadratic, the investment cost is approximated by a quadratic function of the flow rate.
902+
The constraint defines the cost of the active treatment unit as the sum of an investment cost and an operating cost.
903+
The investment cost is proportional to the total flow raised to the power of 0.7 and the operating cost is proportional to the flow.
904+
905+
Based on the approximation given, the concave investment cost is calculated as follows:
906+
If approximation is quadratic zero origin, the investment cost is approximated by a quadratic function of the flow rate with the origin at zero.
907+
If approximation is quadratic nonzero origin, the investment cost is approximated by a quadratic function of the flow rate with origin different from zero. This approximation has a better fit than the quadratic zero origin.
791908
If approximation is piecewise, the investment cost is approximated by a piecewise linear function of the flow rate.
792-
If approximation is none, the investment cost is equal to the flow rate to the 0.7 exponent, the original concave function.
909+
If approximation is none, the investment cost is equal to the flow rate raised to 0.7, the original concave function.
793910
794911
Parameters
795912
----------
@@ -802,9 +919,9 @@ def costTU(unit_exists):
802919
The constraint that the cost of the active treatment unit is equal to the sum of an investment cost and an operating cost.
803920
"""
804921
for mt, t in unit_exists.streams:
805-
if approximation == 'quadratic':
922+
if approximation == 'quadratic_zero_origin':
806923
new_var = unit_exists.cost_var[unit]
807-
elif approximation == 'quadratic2':
924+
elif approximation == 'quadratic_nonzero_origin':
808925
new_var = _g(unit_exists.flow[mt, unit])
809926
elif approximation == 'piecewise':
810927
new_var = unit_exists.cost_var[mt, unit]

0 commit comments

Comments
 (0)