From 67dbf163f19a56e795d6315edced209ad8ceecc2 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Sun, 5 Jan 2025 12:18:27 +0100 Subject: [PATCH 1/9] use `broadcastable()` as the broadcasting interface for Values and Bounds --- src/bound.jl | 13 ++++++++++--- src/value.jl | 6 +++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/bound.jl b/src/bound.jl index 500432e..8a4989f 100644 --- a/src/bound.jl +++ b/src/bound.jl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, University of Luxembourg +# Copyright (c) 2023-2025, University of Luxembourg # Copyright (c) 2023, Heinrich-Heine University Duesseldorf # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,11 +20,18 @@ $(TYPEDEF) Abstract type of all bounds usable in constraints, including [`Between`](@ref) and [`EqualTo`](@ref). -`length` of any `Bound` defaults to 1 in order to make broadcasting easier (in -turn, one can write e.g. `Constraint.(some_values, EqualTo(0.0))`). +All [`Bound`](@ref)s are broadcastable as scalars by default. """ abstract type Bound end +Base.Broadcast.broadcastable(x::Bound) = return Ref(x) + +""" +$(TYPEDSIGNATURES) + +**Deprecation warning:** This is kept for backwards compatibility only, and +will be removed in a future release. +""" Base.length(x::Bound) = return 1 """ diff --git a/src/value.jl b/src/value.jl index 12b2eb1..64a2fb6 100644 --- a/src/value.jl +++ b/src/value.jl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, University of Luxembourg +# Copyright (c) 2023-2025, University of Luxembourg # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,9 +18,13 @@ $(TYPEDEF) Abstract type of all values usable in constraints, including [`LinearValue`](@ref) and [`QuadraticValue`](@ref). + +All [`Value`](@ref)s are broadcastable as scalars by default. """ abstract type Value end +Base.Broadcast.broadcastable(x::Value) = return Ref(x) + """ $(TYPEDSIGNATURES) From 37c69fce67b348d08dc6e02eb29a210644ac1d3a Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Sun, 5 Jan 2025 12:39:09 +0100 Subject: [PATCH 2/9] use the broadcasting to make variables() nicer --- src/constraint_tree.jl | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/constraint_tree.jl b/src/constraint_tree.jl index 1493864..189b615 100644 --- a/src/constraint_tree.jl +++ b/src/constraint_tree.jl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, University of Luxembourg +# Copyright (c) 2023-2025, University of Luxembourg # Copyright (c) 2023, Heinrich-Heine University Duesseldorf # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -291,25 +291,14 @@ $(TYPEDSIGNATURES) Make a trivial constraint system that creates variables with indexes in range `1:length(keys)` named in order as given by `keys`. -Parameter `bounds` is either `nothing` for creating variables without bounds -assigned to them, a single bound for creating variables with the same constraint -assigned to them all, or an iterable object of same length as `keys` with -individual bounds for each variable in the same order as `keys`. - -The individual bounds should be subtypes of [`Bound`](@ref), or nothing. To pass -a single bound for all variables, use e.g. `bounds = EqualTo(0)`. -""" -function variables(weight = 1.0; keys::AbstractVector{Symbol}, bounds = nothing) - bs = - isnothing(bounds) ? Base.Iterators.cycle(tuple(nothing)) : - length(bounds) == 1 ? Base.Iterators.cycle(tuple(bounds)) : - length(bounds) == length(keys) ? bounds : - error("lengths of bounds and keys differ for allocated variables") - ConstraintTree( - k => variable(weight; idx = i, bound = b) for - ((i, k), b) in Base.zip(enumerate(keys), bs) - ) -end +The individual bounds should be subtypes of [`Bound`](@ref), or nothing (which +is the default). The bounds are broadcasted; to pass a single bound for all +variables, one can use e.g. `bounds = EqualTo(0)`. +""" +variables(weight = 1.0; keys::AbstractVector{Symbol}, bounds = Ref(nothing)) = + let go((i, k), b) = k => variable(weight, idx = i, bound = b) + ConstraintTree(go.(enumerate(keys), bounds)...) + end """ $(TYPEDSIGNATURES) From 7b56717cfa4efb649cc23a345dc587c43f1ca677 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 7 Jan 2025 10:12:45 +0100 Subject: [PATCH 3/9] use `depwarn` to properly warn about deprecation Co-authored-by: Frames White --- src/bound.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bound.jl b/src/bound.jl index 8a4989f..953d836 100644 --- a/src/bound.jl +++ b/src/bound.jl @@ -32,7 +32,10 @@ $(TYPEDSIGNATURES) **Deprecation warning:** This is kept for backwards compatibility only, and will be removed in a future release. """ -Base.length(x::Bound) = return 1 +function Base.length(x::Bound) + Base.depwarn("length(::Bound) will be removed in future release. Just use 1", :length) + return 1 +end """ $(TYPEDEF) From 7ac95ea3cd9c15af1c56926bcb2e8dc6b2c5feee Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Tue, 7 Jan 2025 10:14:46 +0100 Subject: [PATCH 4/9] simplify the message --- src/bound.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bound.jl b/src/bound.jl index 953d836..1e6de50 100644 --- a/src/bound.jl +++ b/src/bound.jl @@ -33,7 +33,7 @@ $(TYPEDSIGNATURES) will be removed in a future release. """ function Base.length(x::Bound) - Base.depwarn("length(::Bound) will be removed in future release. Just use 1", :length) + Base.depwarn("length(::Bound) will be removed in future release.", :length) return 1 end From e6c12603a9be99406c1d0b407c219ddfd6cde2b3 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Wed, 8 Jan 2025 09:38:23 +0100 Subject: [PATCH 5/9] typo --- docs/src/1-metabolic-modeling.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/1-metabolic-modeling.jl b/docs/src/1-metabolic-modeling.jl index 3c21f6f..74e96b2 100644 --- a/docs/src/1-metabolic-modeling.jl +++ b/docs/src/1-metabolic-modeling.jl @@ -394,7 +394,7 @@ result.exchanges # ### Alternative: Using Accessors.jl # # Accessors.jl implement a "lensy" way to update immutable data structures. -# That comes with a nice outcome of doing the right amount of shallow copyies +# That comes with a nice outcome of doing the right amount of shallow copies # for you automatically, thus avoiding much of the technical danger of in-place # modifications. (You still lose the equational reasoning on your code, but that # may not be an issue at all in usual codebases.) From 14abc803a8325abb7391ab90c0a6633a4b47e7d8 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Wed, 8 Jan 2025 09:56:59 +0100 Subject: [PATCH 6/9] use/test broadcast of values --- docs/src/2-quadratic-optimization.jl | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/src/2-quadratic-optimization.jl b/docs/src/2-quadratic-optimization.jl index c7ac568..c46d659 100644 --- a/docs/src/2-quadratic-optimization.jl +++ b/docs/src/2-quadratic-optimization.jl @@ -84,10 +84,7 @@ ellipse_system = C.ConstraintTree( # single-variable-parametrized line equation. line_param = C.variable().value line_system = - :point^C.ConstraintTree( - :x => C.Constraint(0 + 2 * line_param), - :y => C.Constraint(0 + 1 * line_param), - ) + :point^C.ConstraintTree([:x, :y] .=> C.Constraint.([0, 0] .+ [2, 1] .* line_param)) # Finally, let's connect the systems using `+` operator and add the objective # that would minimize the distance of the points: From 5253159facbd8c4860891b96eb4ca225e5aa43fb Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Wed, 8 Jan 2025 10:11:15 +0100 Subject: [PATCH 7/9] cover, test and depretest the length of bounds --- src/bound.jl | 5 ++++- test/misc.jl | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bound.jl b/src/bound.jl index 1e6de50..049269d 100644 --- a/src/bound.jl +++ b/src/bound.jl @@ -33,7 +33,10 @@ $(TYPEDSIGNATURES) will be removed in a future release. """ function Base.length(x::Bound) - Base.depwarn("length(::Bound) will be removed in future release.", :length) + Base.depwarn( + "length(::Bound) is deprecated and will be removed in future release.", + :length, + ) return 1 end diff --git a/test/misc.jl b/test/misc.jl index 690acd5..8fd468d 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -16,6 +16,12 @@ import ConstraintTrees as C import SparseArrays as SP +@testset "Bounds" begin + b = C.EqualTo(0) + @test_deprecated length(b) + @test length(b) == 1 +end + @testset "Values" begin x = C.LinearValue(SP.sparse([5.0, 0, 6.0, 0])) + From 1928e21cb78d5cf6fd43bc6ccac8efb5f0f94447 Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Wed, 8 Jan 2025 10:20:03 +0100 Subject: [PATCH 8/9] upd copyrights --- docs/src/1-metabolic-modeling.jl | 2 +- docs/src/2-quadratic-optimization.jl | 2 +- test/misc.jl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/1-metabolic-modeling.jl b/docs/src/1-metabolic-modeling.jl index 74e96b2..0462fe3 100644 --- a/docs/src/1-metabolic-modeling.jl +++ b/docs/src/1-metabolic-modeling.jl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, University of Luxembourg #src +# Copyright (c) 2023-2025, University of Luxembourg #src # #src # Licensed under the Apache License, Version 2.0 (the "License"); #src # you may not use this file except in compliance with the License. #src diff --git a/docs/src/2-quadratic-optimization.jl b/docs/src/2-quadratic-optimization.jl index c46d659..256587d 100644 --- a/docs/src/2-quadratic-optimization.jl +++ b/docs/src/2-quadratic-optimization.jl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, University of Luxembourg #src +# Copyright (c) 2023-2025, University of Luxembourg #src # #src # Licensed under the Apache License, Version 2.0 (the "License"); #src # you may not use this file except in compliance with the License. #src diff --git a/test/misc.jl b/test/misc.jl index 8fd468d..1745b88 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -1,5 +1,5 @@ -# Copyright (c) 2023-2024, University of Luxembourg +# Copyright (c) 2023-2025, University of Luxembourg # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From 5c1ae3e473833a9995cac6fe1da74e5f906484ff Mon Sep 17 00:00:00 2001 From: Mirek Kratochvil Date: Wed, 8 Jan 2025 10:34:39 +0100 Subject: [PATCH 9/9] use the shorter&less noisy deprecation test Co-authored-by: Frames White --- test/misc.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/misc.jl b/test/misc.jl index 1745b88..d3f4085 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -18,8 +18,7 @@ import SparseArrays as SP @testset "Bounds" begin b = C.EqualTo(0) - @test_deprecated length(b) - @test length(b) == 1 + @test (@test_deprecated length(b)) == 1 end @testset "Values" begin