/
minimum.jl
57 lines (49 loc) · 1.67 KB
/
minimum.jl
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
#############################################################################
# minimum.jl
# Compute the minimum value of an array.
# All expressions and atoms are subtpyes of AbstractExpr.
# Please read expressions.jl first.
#############################################################################
import Base.minimum
### Minimum Atom
struct MinimumAtom <: AbstractExpr
head::Symbol
id_hash::UInt64
children::Tuple{AbstractExpr}
size::Tuple{Int, Int}
function MinimumAtom(x::AbstractExpr)
if sign(x) == ComplexSign()
error("Argument should be real instead it is $(sign(x))")
else
children = (x,)
return new(:minimum, hash(children), children, (1, 1))
end
end
end
function sign(x::MinimumAtom)
return sign(x.children[1])
end
# The monotonicity
function monotonicity(x::MinimumAtom)
return (Nondecreasing(),)
end
# If we have h(x) = f o g(x), the chain rule says h''(x) = g'(x)^T f''(g(x))g'(x) + f'(g(x))g''(x);
# this represents the first term
function curvature(x::MinimumAtom)
return ConcaveVexity()
end
function evaluate(x::MinimumAtom)
return Base.minimum(evaluate(x.children[1]))
end
# x >= this if minimum(x) = this
# so, x - this will be in the :NonNeg cone
function conic_form!(x::MinimumAtom, unique_conic_forms::UniqueConicForms)
if !has_conic_form(unique_conic_forms, x)
this = Variable()
objective = conic_form!(this, unique_conic_forms)
conic_form!(this <= x.children[1], unique_conic_forms)
cache_conic_form!(unique_conic_forms, x, objective)
end
return get_conic_form(unique_conic_forms, x)
end
minimum(x::AbstractExpr) = MinimumAtom(x)