15
15
# Operator overloads in src/operators.jl
16
16
# ############################################################################
17
17
18
- # Utilities for OrderedDict
19
18
function _add_or_set! (dict:: OrderedDict{K,V} , k:: K , v:: V ) where {K,V}
20
19
# Adding zero terms to this dictionary leads to unacceptable performance
21
20
# degradations. See, e.g., https://github.com/jump-dev/JuMP.jl/issues/1946.
@@ -52,11 +51,13 @@ function _new_ordered_dict(
52
51
end
53
52
return dict
54
53
end
54
+
55
55
# Shortcut for one and two arguments to avoid creating an empty dict and add
56
56
# elements one by one with `JuMP._add_or_set!`
57
57
function _new_ordered_dict (:: Type{K} , :: Type{V} , kv:: Pair ) where {K,V}
58
58
return OrderedDict {K,V} (kv)
59
59
end
60
+
60
61
function _new_ordered_dict (
61
62
:: Type{K} ,
62
63
:: Type{V} ,
@@ -77,6 +78,7 @@ function _build_aff_expr(constant::V, coef::V, var::K) where {V,K}
77
78
terms[var] = coef
78
79
return GenericAffExpr {V,K} (constant, terms)
79
80
end
81
+
80
82
function _build_aff_expr (
81
83
constant:: V ,
82
84
coef1:: V ,
@@ -171,15 +173,21 @@ end
171
173
function Base. iszero (expr:: GenericAffExpr )
172
174
return iszero (expr. constant) && all (iszero, values (expr. terms))
173
175
end
176
+
174
177
function Base. zero (:: Type{GenericAffExpr{C,V}} ) where {C,V}
175
178
return GenericAffExpr {C,V} (zero (C), OrderedDict {V,C} ())
176
179
end
180
+
181
+ Base. zero (a:: GenericAffExpr ) = zero (typeof (a))
182
+
177
183
function Base. one (:: Type{GenericAffExpr{C,V}} ) where {C,V}
178
184
return GenericAffExpr {C,V} (one (C), OrderedDict {V,C} ())
179
185
end
180
- Base . zero (a :: GenericAffExpr ) = zero ( typeof (a))
186
+
181
187
Base. one (a:: GenericAffExpr ) = one (typeof (a))
188
+
182
189
Base. copy (a:: GenericAffExpr ) = GenericAffExpr (copy (a. constant), copy (a. terms))
190
+
183
191
Base. broadcastable (a:: GenericAffExpr ) = Ref (a)
184
192
185
193
# Needed for cases when Julia uses `x == 0` instead of `iszero(x)` (e.g., in the
@@ -192,7 +200,7 @@ Base.:(==)(x::GenericAffExpr, y::Number) = isempty(x.terms) && x.constant == y
192
200
Return the coefficient associated with variable `v` in the affine expression `a`.
193
201
"""
194
202
coefficient (a:: GenericAffExpr{C,V} , v:: V ) where {C,V} = get (a. terms, v, zero (C))
195
- coefficient (a :: GenericAffExpr{C,V} , v1 :: V , v2 :: V ) where {C,V} = zero (C)
203
+ coefficient (:: GenericAffExpr{C,V} , :: V , :: V ) where {C,V} = zero (C)
196
204
197
205
"""
198
206
drop_zeros!(expr::GenericAffExpr)
@@ -312,24 +320,27 @@ linear part of the affine expression.
312
320
linear_terms (aff:: GenericAffExpr ) = LinearTermIterator (aff)
313
321
314
322
_reverse_pair_to_tuple (p:: Pair ) = (p. second, p. first)
323
+
315
324
function Base. iterate (lti:: LinearTermIterator )
316
325
ret = iterate (lti. aff. terms)
317
326
if ret === nothing
318
- return nothing
327
+ return
319
328
else
320
329
return _reverse_pair_to_tuple (ret[1 ]), ret[2 ]
321
330
end
322
331
end
332
+
323
333
function Base. iterate (lti:: LinearTermIterator , state)
324
334
ret = iterate (lti. aff. terms, state)
325
335
if ret === nothing
326
- return nothing
336
+ return
327
337
else
328
338
return _reverse_pair_to_tuple (ret[1 ]), ret[2 ]
329
339
end
330
340
end
331
341
Base. length (lti:: LinearTermIterator ) = length (lti. aff. terms)
332
- function Base. eltype (lti:: LinearTermIterator{GenericAffExpr{C,V}} ) where {C,V}
342
+
343
+ function Base. eltype (:: LinearTermIterator{GenericAffExpr{C,V}} ) where {C,V}
333
344
return Tuple{C,V}
334
345
end
335
346
459
470
function Base. convert (:: Type{GenericAffExpr{T,V}} , v:: V ) where {T,V}
460
471
return GenericAffExpr (zero (T), v => one (T))
461
472
end
473
+
462
474
function Base. convert (:: Type{GenericAffExpr{T,V}} , v:: _Constant ) where {T,V}
463
475
return GenericAffExpr {T,V} (convert (T, _constant_to_number (v)))
464
476
end
@@ -474,14 +486,17 @@ const AffExpr = GenericAffExpr{Float64,VariableRef}
474
486
# Check all coefficients are finite, i.e. not NaN, not Inf, not -Inf
475
487
function _assert_isfinite (a:: AffExpr )
476
488
for (coef, var) in linear_terms (a)
477
- isfinite (coef) || error (" Invalid coefficient $coef on variable $var ." )
489
+ if ! isfinite (coef)
490
+ error (" Invalid coefficient $coef on variable $var ." )
491
+ end
478
492
end
479
493
if isnan (a. constant)
480
494
error (
481
495
" Expression contains an invalid NaN constant. This could be " *
482
496
" produced by `Inf - Inf`." ,
483
497
)
484
498
end
499
+ return
485
500
end
486
501
487
502
"""
490
505
Return the value of the `GenericAffExpr` `v` associated with result index
491
506
`result` of the most-recent solution returned by the solver.
492
507
493
- Replaces `getvalue` for most use cases.
494
-
495
508
See also: [`result_count`](@ref).
496
509
"""
497
510
function value (a:: GenericAffExpr ; result:: Int = 1 )
@@ -504,6 +517,7 @@ function check_belongs_to_model(a::GenericAffExpr, model::AbstractModel)
504
517
for variable in keys (a. terms)
505
518
check_belongs_to_model (variable, model)
506
519
end
520
+ return
507
521
end
508
522
509
523
# Note: No validation is performed that the variables in the AffExpr belong to
@@ -554,42 +568,50 @@ See also: [`moi_function_type`](@ref).
554
568
function jump_function_type end
555
569
556
570
moi_function (a:: GenericAffExpr ) = MOI. ScalarAffineFunction (a)
571
+
557
572
function moi_function_type (:: Type{<:GenericAffExpr{T}} ) where {T}
558
573
return MOI. ScalarAffineFunction{T}
559
574
end
560
575
561
576
function AffExpr (m:: Model , f:: MOI.ScalarAffineFunction )
562
- aff = AffExpr ()
577
+ aff = AffExpr (f . constant )
563
578
for t in f. terms
564
579
add_to_expression! (aff, t. coefficient, VariableRef (m, t. variable))
565
580
end
566
- aff. constant = f. constant
567
581
return aff
568
582
end
583
+
569
584
function jump_function_type (
570
585
:: Model ,
571
586
:: Type{MOI.ScalarAffineFunction{T}} ,
572
587
) where {T}
573
588
return GenericAffExpr{T,VariableRef}
574
589
end
590
+
575
591
function jump_function (model:: Model , f:: MOI.ScalarAffineFunction{T} ) where {T}
576
592
return GenericAffExpr {T,VariableRef} (model, f)
577
593
end
594
+
578
595
function jump_function_type (
579
596
:: Model ,
580
597
:: Type{MOI.VectorAffineFunction{T}} ,
581
598
) where {T}
582
599
return Vector{GenericAffExpr{T,VariableRef}}
583
600
end
601
+
584
602
function jump_function (model:: Model , f:: MOI.VectorAffineFunction{T} ) where {T}
585
603
return GenericAffExpr{T,VariableRef}[
586
604
GenericAffExpr {T,VariableRef} (model, f) for f in MOIU. eachscalar (f)
587
605
]
588
606
end
589
607
590
608
"""
591
- _fill_vaf!(terms::Vector{<:MOI.VectorAffineTerm}, offset::Int, oi::Int,
592
- aff::AbstractJuMPScalar)
609
+ _fill_vaf!(
610
+ terms::Vector{<:MOI.VectorAffineTerm},
611
+ offset::Int,
612
+ oi::Int,
613
+ aff::AbstractJuMPScalar,
614
+ )
593
615
594
616
Fills the vectors terms at indices starting at `offset+1` with the affine terms
595
617
of `aff`. The output index for all terms is `oi`. Return the index of the last
@@ -613,7 +635,10 @@ function _fill_vaf!(
613
635
end
614
636
615
637
function MOI. VectorAffineFunction (affs:: Vector{AffExpr} )
616
- len = sum (aff -> length (linear_terms (aff)), affs)
638
+ len = 0
639
+ for aff in affs
640
+ len += length (linear_terms (aff))
641
+ end
617
642
terms = Vector {MOI.VectorAffineTerm{Float64}} (undef, len)
618
643
constant = Vector {Float64} (undef, length (affs))
619
644
offset = 0
@@ -623,11 +648,9 @@ function MOI.VectorAffineFunction(affs::Vector{AffExpr})
623
648
end
624
649
return MOI. VectorAffineFunction (terms, constant)
625
650
end
651
+
626
652
moi_function (a:: Vector{<:GenericAffExpr} ) = MOI. VectorAffineFunction (a)
653
+
627
654
function moi_function_type (:: Type{<:Vector{<:GenericAffExpr{T}}} ) where {T}
628
655
return MOI. VectorAffineFunction{T}
629
656
end
630
-
631
- # TODO : Find somewhere to put this error message.
632
- # add_constraint(m::Model, c::Array{AffExprConstraint}) =
633
- # error("The operators <=, >=, and == can only be used to specify scalar constraints. If you are trying to add a vectorized constraint, use the element-wise dot comparison operators (.<=, .>=, or .==) instead")
0 commit comments