| |
1 ######################### |
| |
2 # Some utility functions |
| |
3 ######################### |
| |
4 |
| |
5 module Util |
| |
6 |
| |
7 ############## |
| |
8 # Our exports |
| |
9 ############## |
| |
10 |
| |
11 export map_first_slice!, |
| |
12 reduce_first_slice, |
| |
13 norm₂, |
| |
14 γnorm₂, |
| |
15 norm₂w, |
| |
16 norm₂², |
| |
17 norm₂w², |
| |
18 norm₂₁, |
| |
19 γnorm₂₁, |
| |
20 dot, |
| |
21 mean, |
| |
22 proj_norm₂₁ball!, |
| |
23 curry, |
| |
24 ⬿ |
| |
25 |
| |
26 ######################## |
| |
27 # Functional programming |
| |
28 ######################### |
| |
29 |
| |
30 curry = (f::Function,y...)->(z...)->f(y...,z...) |
| |
31 |
| |
32 ############################### |
| |
33 # For working with NamedTuples |
| |
34 ############################### |
| |
35 |
| |
36 ⬿ = merge |
| |
37 |
| |
38 ###### |
| |
39 # map |
| |
40 ###### |
| |
41 |
| |
42 @inline function map_first_slice!(f!, y) |
| |
43 for i in CartesianIndices(size(y)[2:end]) |
| |
44 @inbounds f!(@view(y[:, i])) |
| |
45 end |
| |
46 end |
| |
47 |
| |
48 @inline function map_first_slice!(x, f!, y) |
| |
49 for i in CartesianIndices(size(y)[2:end]) |
| |
50 @inbounds f!(@view(x[:, i]), @view(y[:, i])) |
| |
51 end |
| |
52 end |
| |
53 |
| |
54 @inline function reduce_first_slice(f, y; init=0.0) |
| |
55 accum=init |
| |
56 for i in CartesianIndices(size(y)[2:end]) |
| |
57 @inbounds accum=f(accum, @view(y[:, i])) |
| |
58 end |
| |
59 return accum |
| |
60 end |
| |
61 |
| |
62 ########################### |
| |
63 # Norms and inner products |
| |
64 ########################### |
| |
65 |
| |
66 @inline function dot(x, y) |
| |
67 @assert(length(x)==length(y)) |
| |
68 |
| |
69 accum=0 |
| |
70 for i=1:length(y) |
| |
71 @inbounds accum += x[i]*y[i] |
| |
72 end |
| |
73 return accum |
| |
74 end |
| |
75 |
| |
76 @inline function norm₂w²(y, w) |
| |
77 #Insane memory allocs |
| |
78 #return @inbounds sum(i -> y[i]*y[i]*w[i], 1:length(y)) |
| |
79 accum=0 |
| |
80 for i=1:length(y) |
| |
81 @inbounds accum=accum+y[i]*y[i]*w[i] |
| |
82 end |
| |
83 return accum |
| |
84 end |
| |
85 |
| |
86 @inline function norm₂w(y, w) |
| |
87 return √(norm₂w²(y, w)) |
| |
88 end |
| |
89 |
| |
90 @inline function norm₂²(y) |
| |
91 #Insane memory allocs |
| |
92 #return @inbounds sum(i -> y[i]*y[i], 1:length(y)) |
| |
93 accum=0 |
| |
94 for i=1:length(y) |
| |
95 @inbounds accum=accum+y[i]*y[i] |
| |
96 end |
| |
97 return accum |
| |
98 end |
| |
99 |
| |
100 @inline function norm₂(y) |
| |
101 return √(norm₂²(y)) |
| |
102 end |
| |
103 |
| |
104 @inline function γnorm₂(y, γ) |
| |
105 hubersq = xsq -> begin |
| |
106 x=√xsq |
| |
107 return if x > γ |
| |
108 x-γ/2 |
| |
109 elseif x<-γ |
| |
110 -x-γ/2 |
| |
111 else |
| |
112 xsq/(2γ) |
| |
113 end |
| |
114 end |
| |
115 |
| |
116 if γ==0 |
| |
117 return norm₂(y) |
| |
118 else |
| |
119 return hubersq(norm₂²(y)) |
| |
120 end |
| |
121 end |
| |
122 |
| |
123 function norm₂₁(y) |
| |
124 return reduce_first_slice((s, x) -> s+norm₂(x), y) |
| |
125 end |
| |
126 |
| |
127 function γnorm₂₁(y,γ) |
| |
128 return reduce_first_slice((s, x) -> s+γnorm₂(x, γ), y) |
| |
129 end |
| |
130 |
| |
131 function mean(v) |
| |
132 return sum(v)/prod(size(v)) |
| |
133 end |
| |
134 |
| |
135 @inline function proj_norm₂₁ball!(y, α) |
| |
136 α²=α*α |
| |
137 y′=reshape(y, (size(y, 1), prod(size(y)[2:end]))) |
| |
138 |
| |
139 @inbounds @simd for i=1:size(y′, 2)# in CartesianIndices(size(y)[2:end]) |
| |
140 n² = norm₂²(@view(y′[:, i])) |
| |
141 if n²>α² |
| |
142 y′[:, i] .*= (α/√n²) |
| |
143 end |
| |
144 end |
| |
145 end |
| |
146 |
| |
147 end # Module |
| |
148 |