@@ -148,150 +148,152 @@ dependencies(row) = sort(rowvals(row) .=> nonzeros(row), by = first)
148148 @test_throws " absence of state dependence for time" Incidence (Const (0.0 ), IncidenceValue[linear, linear_time_dependent])
149149 end
150150
151- incidence = @infer_incidence t
152- @test incidence. typ === Const (0.0 )
153- @test dependencies (incidence. row) == [1 => 1 ]
154- @test incidence == incidence " t"
155-
156- incidence = @infer_incidence 5. + ᵢ u₁
157- @test incidence. typ === Const (5.0 )
158- @test dependencies (incidence. row) == [2 => 1 ]
159- @test incidence == incidence " 5.0 + u₁"
160-
161- incidence = @infer_incidence 5.0 + ᵢ t + ᵢ u₁
162- @test incidence. typ === Const (5.0 )
163- @test dependencies (incidence. row) == [1 => 1 , 2 => 1 ]
164- @test incidence == incidence " 5.0 + t + u₁"
165-
166- incidence = @infer_incidence t * ᵢ u₁
167- @test incidence. typ === Const (0.0 )
168- @test dependencies (incidence. row) == [1 => linear_state_dependent, 2 => linear_time_dependent]
169- @test incidence == incidence " f(∝ₛt, ∝ₜu₁)"
170-
171- incidence = @infer_incidence u₁
172- @test incidence. typ === Const (0.0 )
173- @test dependencies (incidence. row) == [2 => 1 ]
174- @test incidence == incidence " u₁"
175-
176- incidence = @infer_incidence u₁ + ᵢ u₂
177- @test incidence. typ === Const (0.0 )
178- @test dependencies (incidence. row) == [2 => 1 , 3 => 1 ]
179- @test incidence == incidence " u₁ + u₂"
180-
181- incidence = @infer_incidence u₁ * ᵢ u₂
182- @test incidence. typ === Const (0.0 )
183- @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => linear_state_dependent]
184- @test incidence == incidence " f(∝ₛu₁, ∝ₛu₂)"
185-
186- incidence = @infer_incidence (2.0 + ᵢ u₁) * ᵢ (3.0 + ᵢ u₂)
187- @test incidence. typ === Const (6.0 )
188- @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => linear_state_dependent]
189- @test incidence == incidence " 6.0 + f(∝ₛu₁, ∝ₛu₂)"
190-
191- incidence = @infer_incidence (2.0 + ᵢ u₁) * ᵢ (3.0 + ᵢ u₁ * ᵢ u₂)
192- @test incidence. typ === Const (6.0 )
193- @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent]
194- @test incidence == incidence " 6.0 + f(u₁, ∝ₛu₂)"
195-
196- incidence = @infer_incidence (2.0 + ᵢ u₁) * ᵢ (3.0 + ᵢ u₁ * ᵢ u₂) + ᵢ u₃
197- @test incidence. typ === Const (6.0 )
198- @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent, 4 => 1.0 ]
199- @test incidence == incidence " 6.0 + u₃ + f(u₁, ∝ₛu₂)"
200-
201- incidence = @infer_incidence (u₁ + ᵢ u₂) * ᵢ t
202- @test incidence. typ === Const (0.0 )
203- @test dependencies (incidence. row) == [1 => linear_state_dependent, (2 : 3 .=> linear_time_dependent). .. ]
204- @test incidence == incidence " f(∝ₛt, ∝ₜu₁, ∝ₜu₂)"
205-
206- incidence = @infer_incidence u₁ * ᵢ u₂ + ᵢ (u₁ + ᵢ t) * ᵢ u₃
207- @test dependencies (incidence. row) == [(1 : 3 .=> linear_state_dependent). .. , 4 => linear_time_and_state_dependent]
208- @test incidence == incidence " f(∝ₛt, ∝ₛu₁, ∝ₛu₂, ∝ₜₛu₃)"
209-
210- # IPO
211-
212- # NOTE: Most of additive terms (`.typ`) can't be precise given the current IPO representation.
213- # We expect `Const(0.0)` in most cases, but widen to `Float64`.
214-
215- incidence = @infer_incidence 1.0 t * 3.0
216- @test dependencies (incidence. row) == [1 => linear]
217- @test incidence == incidence " a + ∝t"
218-
219- incidence = @infer_incidence (1.0 + u₁ + ᵢ u₂) * 1.0
220- @test incidence. typ === Float64
221- @test dependencies (incidence. row) == (2 : 3 .=> linear_state_dependent)
222- @test incidence == incidence " a + f(∝ₛu₁, ∝ₛu₂)"
223-
224- incidence = @infer_incidence (2.0 + u₁) * (3.0 + u₂)
225- @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => linear_state_dependent]
226- @test incidence == incidence " a + f(∝ₛu₁, ∝ₛu₂)"
227-
228- incidence = @infer_incidence 5.0 + u₁
229- @test incidence. typ === Const (5.0 )
230- @test dependencies (incidence. row) == [2 => 1 ]
231- @test incidence == incidence " 5.0 + u₁"
232-
233- incidence = @infer_incidence u₁ * u₁
234- @test dependencies (incidence. row) == [2 => nonlinear]
235- @test incidence == incidence " f(u₁)"
236-
237- incidence = @infer_incidence t * t
238- @test dependencies (incidence. row) == [1 => nonlinear]
239- @test incidence == incidence " f(t)"
240-
241- mul3 (a, b, c) = a * ᵢ (b * ᵢ c)
242- incidence = @infer_incidence mul3 (t, u₁, u₂)
243- @test dependencies (incidence. row) == [1 => linear_state_dependent, (2 : 3 .=> linear_time_and_state_dependent). .. ]
244- @test incidence == incidence " f(∝ₛt, ∝ₜₛu₁, ∝ₜₛu₂)"
245-
246- incidence = @infer_incidence mul3 (t, u₁, u₁)
247- @test dependencies (incidence. row) == [1 => linear_state_dependent, 2 => nonlinear]
248- @test incidence == incidence " f(∝ₛt, u₁)"
249-
250- incidence = @infer_incidence mul3 (t, u₁, t)
251- # If we knew which state is used for state dependence,
252- # state should be inferred as linear_time_dependent.
253- @test dependencies (incidence. row) == [1 => nonlinear, 2 => linear_time_and_state_dependent]
254- @test incidence == incidence " f(t, ∝ₜₛu₁)"
255-
256- incidence = @infer_incidence mul3 (u₂, u₁, u₂)
257- @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => nonlinear]
258- @test incidence == incidence " f(∝ₛu₁, u₂)"
259-
260- _muladd (a, b, c) = a + ᵢ b * ᵢ c
261- incidence = @infer_incidence _muladd (u₁, u₁, u₂)
262- # We widen to `nonlinear` because we can't yet infer that `b := u₁` is
263- # not multiplied by `a := u₁`. The solution would be to see that `a`
264- # is linear but state-independent and therefore can't be a factor of `b`.
265- @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent]
266- @test incidence == incidence " f(u₁, ∝ₛu₂)"
267-
268- # Here we still wouldn't be able to use the above solution because `a := u₁` is state-dependent.
269- # So `c := u₁` having a state-dependent coefficient might be multiplied by `a` a.k.a itself
270- # which would make it nonlinear, so IPO can only infer `u₁` as nonlinear.
271- _muladd2 (a, b, c, d) = d * ᵢ a + ᵢ b * ᵢ c
272- incidence = @infer_incidence _muladd2 (u₁, u₂, u₁, u₃)
273- @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent, 4 => linear_state_dependent]
274- @test incidence == incidence " f(u₁, ∝ₛu₂, ∝ₛu₃)"
275-
276- incidence = @infer_incidence exp (u₁)
277- @test dependencies (incidence. row) == [2 => nonlinear]
278- @test incidence == incidence " a + f(u₁)"
279-
280- incidence = @infer_incidence t * exp (u₁)
281- @test dependencies (incidence. row) == [1 => linear_state_dependent, 2 => nonlinear]
282- @test incidence == incidence " a + f(∝ₛt, u₁)"
283-
284- incidence = @infer_incidence u₁ * exp (t)
285- @test dependencies (incidence. row) == [1 => nonlinear, 2 => linear_time_dependent]
286- @test incidence == incidence " a + f(t, ∝ₜu₁)"
287-
288- incidence = @infer_incidence u₁ * exp (t + u₂)
289- @test dependencies (incidence. row) == [1 => nonlinear, 2 => linear_time_and_state_dependent, 3 => nonlinear]
290- @test incidence == incidence " a + f(t, ∝ₜₛu₁, u₂)"
291-
292- incidence = @infer_incidence atan (u₁, u₂)
293- @test dependencies (incidence. row) == [2 => nonlinear, 3 => nonlinear]
294- @test incidence == incidence " a + f(u₁, u₂)"
151+ @testset " Basic lattice operations with intrinsic tfuncs" begin
152+ incidence = @infer_incidence t
153+ @test incidence. typ === Const (0.0 )
154+ @test dependencies (incidence. row) == [1 => 1 ]
155+ @test incidence == incidence " t"
156+
157+ incidence = @infer_incidence 5. + ᵢ u₁
158+ @test incidence. typ === Const (5.0 )
159+ @test dependencies (incidence. row) == [2 => 1 ]
160+ @test incidence == incidence " 5.0 + u₁"
161+
162+ incidence = @infer_incidence 5.0 + ᵢ t + ᵢ u₁
163+ @test incidence. typ === Const (5.0 )
164+ @test dependencies (incidence. row) == [1 => 1 , 2 => 1 ]
165+ @test incidence == incidence " 5.0 + t + u₁"
166+
167+ incidence = @infer_incidence t * ᵢ u₁
168+ @test incidence. typ === Const (0.0 )
169+ @test dependencies (incidence. row) == [1 => linear_state_dependent, 2 => linear_time_dependent]
170+ @test incidence == incidence " f(∝ₛt, ∝ₜu₁)"
171+
172+ incidence = @infer_incidence u₁
173+ @test incidence. typ === Const (0.0 )
174+ @test dependencies (incidence. row) == [2 => 1 ]
175+ @test incidence == incidence " u₁"
176+
177+ incidence = @infer_incidence u₁ + ᵢ u₂
178+ @test incidence. typ === Const (0.0 )
179+ @test dependencies (incidence. row) == [2 => 1 , 3 => 1 ]
180+ @test incidence == incidence " u₁ + u₂"
181+
182+ incidence = @infer_incidence u₁ * ᵢ u₂
183+ @test incidence. typ === Const (0.0 )
184+ @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => linear_state_dependent]
185+ @test incidence == incidence " f(∝ₛu₁, ∝ₛu₂)"
186+
187+ incidence = @infer_incidence (2.0 + ᵢ u₁) * ᵢ (3.0 + ᵢ u₂)
188+ @test incidence. typ === Const (6.0 )
189+ @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => linear_state_dependent]
190+ @test incidence == incidence " 6.0 + f(∝ₛu₁, ∝ₛu₂)"
191+
192+ incidence = @infer_incidence (2.0 + ᵢ u₁) * ᵢ (3.0 + ᵢ u₁ * ᵢ u₂)
193+ @test incidence. typ === Const (6.0 )
194+ @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent]
195+ @test incidence == incidence " 6.0 + f(u₁, ∝ₛu₂)"
196+
197+ incidence = @infer_incidence (2.0 + ᵢ u₁) * ᵢ (3.0 + ᵢ u₁ * ᵢ u₂) + ᵢ u₃
198+ @test incidence. typ === Const (6.0 )
199+ @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent, 4 => 1.0 ]
200+ @test incidence == incidence " 6.0 + u₃ + f(u₁, ∝ₛu₂)"
201+
202+ incidence = @infer_incidence (u₁ + ᵢ u₂) * ᵢ t
203+ @test incidence. typ === Const (0.0 )
204+ @test dependencies (incidence. row) == [1 => linear_state_dependent, (2 : 3 .=> linear_time_dependent). .. ]
205+ @test incidence == incidence " f(∝ₛt, ∝ₜu₁, ∝ₜu₂)"
206+
207+ incidence = @infer_incidence u₁ * ᵢ u₂ + ᵢ (u₁ + ᵢ t) * ᵢ u₃
208+ @test dependencies (incidence. row) == [(1 : 3 .=> linear_state_dependent). .. , 4 => linear_time_and_state_dependent]
209+ @test incidence == incidence " f(∝ₛt, ∝ₛu₁, ∝ₛu₂, ∝ₜₛu₃)"
210+ end
211+
212+ @testset " IPO" begin
213+ # NOTE: Most of additive terms (`.typ`) can't be precise given the current IPO representation.
214+ # We expect `Const(0.0)` in most cases, but widen to `Float64`.
215+
216+ incidence = @infer_incidence 1.0 t * 3.0
217+ @test dependencies (incidence. row) == [1 => linear]
218+ @test incidence == incidence " a + ∝t"
219+
220+ incidence = @infer_incidence (1.0 + u₁ + ᵢ u₂) * 1.0
221+ @test incidence. typ === Float64
222+ @test dependencies (incidence. row) == (2 : 3 .=> linear_state_dependent)
223+ @test incidence == incidence " a + f(∝ₛu₁, ∝ₛu₂)"
224+
225+ incidence = @infer_incidence (2.0 + u₁) * (3.0 + u₂)
226+ @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => linear_state_dependent]
227+ @test incidence == incidence " a + f(∝ₛu₁, ∝ₛu₂)"
228+
229+ incidence = @infer_incidence 5.0 + u₁
230+ @test incidence. typ === Const (5.0 )
231+ @test dependencies (incidence. row) == [2 => 1 ]
232+ @test incidence == incidence " 5.0 + u₁"
233+
234+ incidence = @infer_incidence u₁ * u₁
235+ @test dependencies (incidence. row) == [2 => nonlinear]
236+ @test incidence == incidence " f(u₁)"
237+
238+ incidence = @infer_incidence t * t
239+ @test dependencies (incidence. row) == [1 => nonlinear]
240+ @test incidence == incidence " f(t)"
241+
242+ mul3 (a, b, c) = a * ᵢ (b * ᵢ c)
243+ incidence = @infer_incidence mul3 (t, u₁, u₂)
244+ @test dependencies (incidence. row) == [1 => linear_state_dependent, (2 : 3 .=> linear_time_and_state_dependent). .. ]
245+ @test incidence == incidence " f(∝ₛt, ∝ₜₛu₁, ∝ₜₛu₂)"
246+
247+ incidence = @infer_incidence mul3 (t, u₁, u₁)
248+ @test dependencies (incidence. row) == [1 => linear_state_dependent, 2 => nonlinear]
249+ @test incidence == incidence " f(∝ₛt, u₁)"
250+
251+ incidence = @infer_incidence mul3 (t, u₁, t)
252+ # If we knew which state is used for state dependence,
253+ # state should be inferred as linear_time_dependent.
254+ @test dependencies (incidence. row) == [1 => nonlinear, 2 => linear_time_and_state_dependent]
255+ @test incidence == incidence " f(t, ∝ₜₛu₁)"
256+
257+ incidence = @infer_incidence mul3 (u₂, u₁, u₂)
258+ @test dependencies (incidence. row) == [2 => linear_state_dependent, 3 => nonlinear]
259+ @test incidence == incidence " f(∝ₛu₁, u₂)"
260+
261+ _muladd (a, b, c) = a + ᵢ b * ᵢ c
262+ incidence = @infer_incidence _muladd (u₁, u₁, u₂)
263+ # We widen to `nonlinear` because we can't yet infer that `b := u₁` is
264+ # not multiplied by `a := u₁`. The solution would be to see that `a`
265+ # is linear but state-independent and therefore can't be a factor of `b`.
266+ @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent]
267+ @test incidence == incidence " f(u₁, ∝ₛu₂)"
268+
269+ # Here we still wouldn't be able to use the above solution because `a := u₁` is state-dependent.
270+ # So `c := u₁` having a state-dependent coefficient might be multiplied by `a` a.k.a itself
271+ # which would make it nonlinear, so IPO can only infer `u₁` as nonlinear.
272+ _muladd2 (a, b, c, d) = d * ᵢ a + ᵢ b * ᵢ c
273+ incidence = @infer_incidence _muladd2 (u₁, u₂, u₁, u₃)
274+ @test dependencies (incidence. row) == [2 => nonlinear, 3 => linear_state_dependent, 4 => linear_state_dependent]
275+ @test incidence == incidence " f(u₁, ∝ₛu₂, ∝ₛu₃)"
276+
277+ incidence = @infer_incidence exp (u₁)
278+ @test dependencies (incidence. row) == [2 => nonlinear]
279+ @test incidence == incidence " a + f(u₁)"
280+
281+ incidence = @infer_incidence t * exp (u₁)
282+ @test dependencies (incidence. row) == [1 => linear_state_dependent, 2 => nonlinear]
283+ @test incidence == incidence " a + f(∝ₛt, u₁)"
284+
285+ incidence = @infer_incidence u₁ * exp (t)
286+ @test dependencies (incidence. row) == [1 => nonlinear, 2 => linear_time_dependent]
287+ @test incidence == incidence " a + f(t, ∝ₜu₁)"
288+
289+ incidence = @infer_incidence u₁ * exp (t + u₂)
290+ @test dependencies (incidence. row) == [1 => nonlinear, 2 => linear_time_and_state_dependent, 3 => nonlinear]
291+ @test incidence == incidence " a + f(t, ∝ₜₛu₁, u₂)"
292+
293+ incidence = @infer_incidence atan (u₁, u₂)
294+ @test dependencies (incidence. row) == [2 => nonlinear, 3 => nonlinear]
295+ @test incidence == incidence " a + f(u₁, u₂)"
296+ end
295297end ;
296298
297299end
0 commit comments