35
35
ConstantValue ,
36
36
Divider ,
37
37
FormulaStep ,
38
+ Maximizer ,
38
39
MetricFetcher ,
40
+ Minimizer ,
39
41
Multiplier ,
40
42
OpenParen ,
41
43
Subtractor ,
45
47
_logger = logging .Logger (__name__ )
46
48
47
49
_operator_precedence = {
48
- "(" : 0 ,
49
- "/" : 1 ,
50
- "*" : 2 ,
51
- "-" : 3 ,
52
- "+" : 4 ,
53
- ")" : 5 ,
50
+ "max" : 0 ,
51
+ "min" : 1 ,
52
+ "(" : 2 ,
53
+ "/" : 3 ,
54
+ "*" : 4 ,
55
+ "-" : 5 ,
56
+ "+" : 6 ,
57
+ ")" : 7 ,
54
58
}
55
59
56
60
@@ -168,6 +172,36 @@ def __truediv__(
168
172
"""
169
173
return self ._higher_order_builder (self , self ._create_method ) / other # type: ignore
170
174
175
+ def _max (
176
+ self , other : _GenericEngine | _GenericHigherOrderBuilder | QuantityT
177
+ ) -> _GenericHigherOrderBuilder :
178
+ """Return a formula engine that outputs the maximum of `self` and `other`.
179
+
180
+ Args:
181
+ other: A formula receiver, a formula builder or a QuantityT instance
182
+ corresponding to a sub-expression.
183
+
184
+ Returns:
185
+ A formula builder that can take further expressions, or can be built
186
+ into a formula engine.
187
+ """
188
+ return self ._higher_order_builder (self , self ._create_method ).max (other ) # type: ignore
189
+
190
+ def _min (
191
+ self , other : _GenericEngine | _GenericHigherOrderBuilder | QuantityT
192
+ ) -> _GenericHigherOrderBuilder :
193
+ """Return a formula engine that outputs the minimum of `self` and `other`.
194
+
195
+ Args:
196
+ other: A formula receiver, a formula builder or a QuantityT instance
197
+ corresponding to a sub-expression.
198
+
199
+ Returns:
200
+ A formula builder that can take further expressions, or can be built
201
+ into a formula engine.
202
+ """
203
+ return self ._higher_order_builder (self , self ._create_method ).min (other ) # type: ignore
204
+
171
205
172
206
class FormulaEngine (
173
207
Generic [QuantityT ],
@@ -467,6 +501,10 @@ def push_oper(self, oper: str) -> None:
467
501
self ._build_stack .append (Divider ())
468
502
elif oper == "(" :
469
503
self ._build_stack .append (OpenParen ())
504
+ elif oper == "max" :
505
+ self ._build_stack .append (Maximizer ())
506
+ elif oper == "min" :
507
+ self ._build_stack .append (Minimizer ())
470
508
471
509
def push_metric (
472
510
self ,
@@ -653,15 +691,15 @@ def _push(
653
691
self ._steps .append ((TokenType .OPER , ")" ))
654
692
self ._steps .append ((TokenType .OPER , oper ))
655
693
656
- # pylint: disable=protected-access
657
694
if isinstance (other , (FormulaEngine , FormulaEngine3Phase )):
658
695
self ._steps .append ((TokenType .COMPONENT_METRIC , other ))
659
- elif isinstance (other , (Quantity , float )):
696
+ elif isinstance (other , (Quantity , float , int )):
660
697
match oper :
661
- case "+" | "-" :
698
+ case "+" | "-" | "max" | "min" :
662
699
if not isinstance (other , Quantity ):
663
700
raise RuntimeError (
664
- f"A Quantity must be provided for addition or subtraction to { other } "
701
+ "A Quantity must be provided for addition,"
702
+ f" subtraction, min or max to { other } "
665
703
)
666
704
case "*" | "/" :
667
705
if not isinstance (other , (float , int )):
@@ -671,9 +709,8 @@ def _push(
671
709
self ._steps .append ((TokenType .CONSTANT , other ))
672
710
elif isinstance (other , _BaseHOFormulaBuilder ):
673
711
self ._steps .append ((TokenType .OPER , "(" ))
674
- self ._steps .extend (other ._steps )
712
+ self ._steps .extend (other ._steps ) # pylint: disable=protected-access
675
713
self ._steps .append ((TokenType .OPER , ")" ))
676
- # pylint: enable=protected-access
677
714
else :
678
715
raise RuntimeError (f"Can't build a formula from: { other } " )
679
716
assert isinstance (
@@ -804,6 +841,66 @@ def __truediv__(
804
841
"""
805
842
return self ._push ("/" , other )
806
843
844
+ @overload
845
+ def max (
846
+ self , other : _CompositionType1Phase
847
+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
848
+ ...
849
+
850
+ @overload
851
+ def max (
852
+ self , other : _CompositionType3Phase | QuantityT
853
+ ) -> HigherOrderFormulaBuilder3Phase [QuantityT ]:
854
+ ...
855
+
856
+ def max (
857
+ self , other : _CompositionType | QuantityT
858
+ ) -> (
859
+ HigherOrderFormulaBuilder [QuantityT ]
860
+ | HigherOrderFormulaBuilder3Phase [QuantityT ]
861
+ ):
862
+ """Return a formula builder that calculates the maximum of `self` and `other`.
863
+
864
+ Args:
865
+ other: A formula receiver, or a formula builder instance corresponding to a
866
+ sub-expression.
867
+
868
+ Returns:
869
+ A formula builder that can take further expressions, or can be built
870
+ into a formula engine.
871
+ """
872
+ return self ._push ("max" , other )
873
+
874
+ @overload
875
+ def min (
876
+ self , other : _CompositionType1Phase
877
+ ) -> HigherOrderFormulaBuilder [QuantityT ]:
878
+ ...
879
+
880
+ @overload
881
+ def min (
882
+ self , other : _CompositionType3Phase | QuantityT
883
+ ) -> HigherOrderFormulaBuilder3Phase [QuantityT ]:
884
+ ...
885
+
886
+ def min (
887
+ self , other : _CompositionType | QuantityT
888
+ ) -> (
889
+ HigherOrderFormulaBuilder [QuantityT ]
890
+ | HigherOrderFormulaBuilder3Phase [QuantityT ]
891
+ ):
892
+ """Return a formula builder that calculates the minimum of `self` and `other`.
893
+
894
+ Args:
895
+ other: A formula receiver, or a formula builder instance corresponding to a
896
+ sub-expression.
897
+
898
+ Returns:
899
+ A formula builder that can take further expressions, or can be built
900
+ into a formula engine.
901
+ """
902
+ return self ._push ("min" , other )
903
+
807
904
808
905
class HigherOrderFormulaBuilder (Generic [QuantityT ], _BaseHOFormulaBuilder [QuantityT ]):
809
906
"""A specialization of the _BaseHOFormulaBuilder for `FormulaReceiver`."""
0 commit comments