| 25 name = "laser_and_mirrors_aux" |
25 name = "laser_and_mirrors_aux" |
| 26 |
26 |
| 27 # Fine-tune algorithms |
27 # Fine-tune algorithms |
| 28 alg_finetune = { |
28 alg_finetune = { |
| 29 "tau0": 0.99, |
29 "tau0": 0.99, |
| 30 "theta0": 0.01, |
30 "theta0": 100, |
| 31 "inner_method": "PP", |
31 "inner_method": "PP", |
| 32 "inner_pdps_τσ0": (19.8, 0.05), |
32 "inner_pdps_τσ0": (19.8, 0.05), |
| 33 "inner_pp_τ": [1000.0, 1000.0], |
33 "inner_pp_τ": [1000.0, 1000.0], |
| 34 "merge": True, |
34 "merge": True, |
| 35 "fitness_merging": True, |
35 "fitness_merging": True, |
| |
36 "merge_radius": 0.1, |
| |
37 "merge_interp": False, |
| 36 } |
38 } |
| 37 |
39 |
| 38 algorithm_overrides = { |
40 algorithm_overrides = { |
| 39 "RadonFB": alg_finetune, |
41 "RadonFB": alg_finetune, |
| 40 "RadonSlidingFB": alg_finetune, |
42 "RadonSlidingFB": alg_finetune, |
| 42 "RadonSlidingPDPS": alg_finetune, |
44 "RadonSlidingPDPS": alg_finetune, |
| 43 } |
45 } |
| 44 |
46 |
| 45 |
47 |
| 46 # Setup shared between experiment with known/unknown conductivity and diffusivity |
48 # Setup shared between experiment with known/unknown conductivity and diffusivity |
| 47 def generic_setup(prefix, simple=True): |
49 def generic_setup( |
| 48 |
50 prefix, |
| 49 # Create true source |
51 simple=True, |
| 50 μ_true = DiscreteMeasure_2_f64( |
52 rng=None, |
| |
53 μ_true=DiscreteMeasure_2_f64( |
| 51 [([0.1, 0.3], 0.08), ([0.4, 0.25], 0.05), ([0.25, 0.13], 0.06)] |
54 [([0.1, 0.3], 0.08), ([0.4, 0.25], 0.05), ([0.25, 0.13], 0.06)] |
| 52 ) |
55 ), |
| |
56 k=0.01, |
| |
57 r=0.5, |
| |
58 θ=30 * np.pi / 180, |
| |
59 ): |
| 53 |
60 |
| 54 # Create convection-diffusion PDE |
61 # Create convection-diffusion PDE |
| 55 pde = ConvectionDiffusion( |
62 pde = ConvectionDiffusion( |
| 56 u0=lambda x: 0.0 * x[1], |
63 u0=lambda x: 0.0 * x[1], |
| 57 g=lambda x: 0.0 * x[1], |
64 g=lambda x: 0.0 * x[1], |
| 58 domain_size=[0, 0.5, 0, 0.5], |
65 domain_size=[0, 0.5, 0, 0.5], |
| 59 num_steps=50, |
66 num_steps=50, |
| |
67 # override_lipschitz=4.0, |
| |
68 # override_lipschitz_pair=(4.0, 40.0), |
| 60 ) |
69 ) |
| 61 |
70 |
| 62 # Set up lasers and mirrors |
71 # Set up lasers and mirrors |
| 63 lasers = [ |
72 lasers = [ |
| 64 np.array([0.1, 0.1]), |
73 np.array([0.1, 0.1]), |
| 118 auxtrue = (k, (c1, c2)) |
125 auxtrue = (k, (c1, c2)) |
| 119 |
126 |
| 120 # Simulate measurements |
127 # Simulate measurements |
| 121 u_n_list = pde.apply((μ_true, (k, (c1, c2)))) |
128 u_n_list = pde.apply((μ_true, (k, (c1, c2)))) |
| 122 b_true = [L_i.apply(u) for u in u_n_list] |
129 b_true = [L_i.apply(u) for u in u_n_list] |
| 123 b = [b_i + L_i.noise(0.01 * norm(b_i) / np.sqrt(np.size(b_i))) for b_i in b_true] |
130 b = [ |
| |
131 b_i + L_i.noise(0.01 * norm(b_i) / np.sqrt(np.size(b_i)), rng) for b_i in b_true |
| |
132 ] |
| 124 |
133 |
| 125 # Estimate bounds on domains and values |
134 # Estimate bounds on domains and values |
| 126 dat_bound = 10 * max([norm(b_i) for b_i in b]) |
135 dat_bound = 2 * max([norm(b_i) for b_i in b]) |
| 127 μ_bound = 1.3 * sum([alpha for _point, alpha in μ_true.iter_padded()]) |
136 μ_bound = 1.3 * sum([alpha for _point, alpha in μ_true.iter_padded()]) |
| 128 xbound = XBound(mu_dual=μ_bound, k_min=k, k_max=k, c_Linf=r) |
137 pde.xbound = XBound(mu_dual=μ_bound, k_min=k * 0.9, k_max=k * 1.1, c_Linf=r * 0.9) |
| 129 |
138 |
| 130 # Create data term |
139 # Create data term |
| 131 dat = ComposeFnWithOperator( |
140 dat = ComposeFnWithOperator( |
| 132 SumOfSeparableFunctions( |
141 SumOfSeparableFunctions( |
| 133 [ |
142 [ |
| 137 xbound=dat_bound, |
146 xbound=dat_bound, |
| 138 b_norm=norm(b), |
147 b_norm=norm(b), |
| 139 λ=pde.dt / len(beams), |
148 λ=pde.dt / len(beams), |
| 140 ) |
149 ) |
| 141 for data in b |
150 for data in b |
| 142 ] |
151 ], |
| 143 ), |
152 ), |
| 144 pde, |
153 pde, |
| 145 xbound=[xbound], |
154 ) |
| 146 xbound_pair=[xbound], |
155 |
| 147 ) |
156 # Save true and initial data |
| 148 |
|
| 149 # Plot true and initial data |
|
| 150 plot_factory = PlotFactory(pde) |
157 plot_factory = PlotFactory(pde) |
| 151 plotter = plot_factory.produce(prefix) |
158 plotter = plot_factory.produce(prefix) |
| 152 ω, _ = dat.diff((DiscreteMeasure_2_f64([]), auxtrue)) |
159 ω, _ = dat.diff((DiscreteMeasure_2_f64([]), auxtrue)) |
| 153 ω_true, _ = dat.diff((μ_true, auxtrue)) |
160 ω_true, _ = dat.diff((μ_true, auxtrue)) |
| 154 np.savez_compressed( |
161 np.savez_compressed( |
| 155 "%s/omega_0.npz" % prefix, |
162 "%s/omega_0.npz" % prefix, |
| 156 true_mu=[[point[0], point[1], alpha] for point, alpha in μ_true.iter_padded()], |
163 true_mu=[[point[0], point[1], alpha] for point, alpha in μ_true.iter_padded()], |
| 157 omega0=ω.x.array, |
164 omega0=ω.x.array, |
| 158 true_omega=ω_true.x.array, |
165 true_omega=ω_true.x.array, |
| |
166 k=k, |
| |
167 c1=c1, |
| |
168 c2=c2, |
| 159 true_u_n_list_array=[u_n_list[i].x.array for i in plotter.plot_frames], |
169 true_u_n_list_array=[u_n_list[i].x.array for i in plotter.plot_frames], |
| 160 ) |
170 ) |
| 161 |
171 |
| 162 return dat, auxtrue, μ_bound, μ_true, plot_factory |
172 return dat, auxtrue, μ_bound, μ_true, plot_factory, pde |
| 163 |
173 |
| 164 |
174 |
| |
175 def relnoise(v, σ, rng, level=None): |
| |
176 if level is None: |
| |
177 level = abs(v) |
| |
178 return float(rng.normal(v, σ * level)) |
| |
179 |
| |
180 |
| |
181 # Setup the problem |
| 165 def setup(prefix): |
182 def setup(prefix): |
| 166 dat, auxtrue, _μ_bound, μ_true, plot_factory = generic_setup(prefix) |
183 rng = np.random.default_rng(seed=31337) |
| 167 |
184 |
| 168 reg = RegTerm.NonnegRadon(10e-7) |
185 dat, auxtrue, _μ_bound, μ_true, plot_factory, pde = generic_setup(prefix, rng=rng) |
| |
186 |
| |
187 # Override Lipschitz parameter |
| |
188 pde.override_lipschitz = (4.0,) |
| |
189 pde.override_lipschitz_pair = (4.0, 4.0) |
| |
190 # print("diff_chain_lipschitz_factor (modified)", pde.diff_chain_lipschitz_factor()) |
| |
191 # l1, l2 = pde.diff_chain_lipschitz_factor_pair() |
| |
192 # print("diff_chain_lipschitz_factor_pair (modified) ", l1, ", ", l2) |
| |
193 |
| |
194 reg = RegTerm.NonnegRadon(1.5e-6) |
| 169 |
195 |
| 170 μ0 = DiscreteMeasure_2_f64([]) |
196 μ0 = DiscreteMeasure_2_f64([]) |
| 171 aux0 = auxtrue |
197 (k, (c1, c2)) = auxtrue |
| 172 aux = QuadraticRegularisation(0.001, aux0) |
198 aux0 = ( |
| |
199 max(0.001, relnoise(k, 0.02, rng)), |
| |
200 ( |
| |
201 relnoise(c1, 0.2, rng), |
| |
202 relnoise(c2, 0.2, rng), |
| |
203 ), |
| |
204 ) |
| |
205 print("aux init ", aux0) |
| |
206 aux = BoxedQuadraticRegularisation((0.001, -1.0), (1.0, 1.0), (3.0, 0.0005), aux0) |
| 173 ax = aux.apply(aux0) |
207 ax = aux.apply(aux0) |
| 174 inival = dat.apply((μ0, aux0)) |
208 inival = dat.apply((μ0, aux0)) |
| 175 print("Initial value:", inival + ax, ax) |
209 print("Initial data term value:", inival + ax) |
| 176 print("Value at true μ:", dat.apply((μ_true, auxtrue)) + ax) |
210 print("Data term value at true μ:", dat.apply((μ_true, auxtrue)) + ax) |
| 177 |
211 |
| 178 # auxinit = np.c_[ |
212 # No curvature bound given: θ is aboslute. |
| 179 # np.zeros_like(k), |
213 dat.curvature_bound_components = lambda: (None, None) |
| 180 # np.zeros_like(c1), |
|
| 181 # np.zeros_like(c2), |
|
| 182 # ] |
|
| 183 # print(np.shape(auxinit)) |
|
| 184 |
|
| 185 # We need Θ² such that ⟨F'(μ+Δ, aux-F'(μ, aux)|Δ⟩ ≤ Θ²|γ|(c_2), where Δ=(π_♯^1-π_♯^0)γ. |
|
| 186 # We have |
|
| 187 # |
|
| 188 # ⟨F'(μ+Δ, aux)-F'(μ, aux)|Δ⟩ ≤ ‖⟨F'(μ+Δ, aux)-F'(μ, aux)‖ ‖Δ‖ |
|
| 189 # ≤ L_{F'(·, aux)} ‖Δ‖², |
|
| 190 # |
|
| 191 # so Θ² ≥ L_{F'(·, aux)} ‖Δ‖² / |γ|(c_2). Thsi doesn't give anything useful if the |
|
| 192 # transport is very small in distance. |
|
| 193 |
|
| 194 dat.curvature_bound_components = lambda: (None, None) # 1.0 |
|
| 195 |
214 |
| 196 return Problem(dat, reg, aux, aux0, μ0, plot_factory=plot_factory) |
215 return Problem(dat, reg, aux, aux0, μ0, plot_factory=plot_factory) |