@@ -8,12 +8,14 @@ using QuantumPropagators.Interfaces:
88using QuantumGradientGenerators: GradGenerator, GradVector, GradgenOperator
99using StaticArrays: SVector, SMatrix, MVector
1010using LinearAlgebra: norm, dot, mul!, I
11+ using StableRNGs: StableRNG
1112
1213
1314@testset " GradVector Interface" begin
1415
16+ rng = StableRNG (1179926107 )
1517 N = 10
16- Ψ = random_state_vector (N)
18+ Ψ = random_state_vector (N; rng )
1719 Ψ̃ = GradVector (Ψ, 2 )
1820 @test check_state (Ψ̃)
1921
2426
2527@testset " GradVector Interface (Static)" begin
2628
29+ rng = StableRNG (2188051723 )
2730 N = 10
28- Ψ = SVector {N,ComplexF64} (random_state_vector (N))
31+ Ψ = SVector {N,ComplexF64} (random_state_vector (N; rng ))
2932 Ψ̃ = GradVector (Ψ, 2 )
3033 @test check_state (Ψ̃)
3134
4851
4952@testset " GradGenerator Interface" begin
5053
54+ rng = StableRNG (3031820470 )
5155 N = 10
52- Ĥ₀ = random_matrix (N, hermitian = true )
53- Ĥ₁ = random_matrix (N, hermitian = true )
54- Ĥ₂ = random_matrix (N, hermitian = true )
56+ Ĥ₀ = random_matrix (N; hermitian = true , rng )
57+ Ĥ₁ = random_matrix (N; hermitian = true , rng )
58+ Ĥ₂ = random_matrix (N; hermitian = true , rng )
5559 ϵ₁ (t) = 1.0
5660 ϵ₂ (t) = 1.0
5761 Ĥ_of_t = hamiltonian (Ĥ₀, (Ĥ₁, ϵ₁), (Ĥ₂, ϵ₂))
6064
6165 G̃_of_t = GradGenerator (Ĥ_of_t)
6266
63- Ψ = random_state_vector (N)
67+ Ψ = random_state_vector (N; rng )
6468 Ψ̃ = GradVector (Ψ, length (get_controls (G̃_of_t)))
6569
6670 @test check_generator (G̃_of_t; state = Ψ̃, tlist, for_gradient_optimization = false )
7074
7175@testset " GradGenerator Interface (Static)" begin
7276
77+ rng = StableRNG (1911203795 )
7378 N = 10
74- Ĥ₀ = SMatrix {N,N,ComplexF64} (random_matrix (N, hermitian = true ))
75- Ĥ₁ = SMatrix {N,N,ComplexF64} (random_matrix (N, hermitian = true ))
76- Ĥ₂ = SMatrix {N,N,ComplexF64} (random_matrix (N, hermitian = true ))
79+ Ĥ₀ = SMatrix {N,N,ComplexF64} (random_matrix (N; hermitian = true , rng ))
80+ Ĥ₁ = SMatrix {N,N,ComplexF64} (random_matrix (N; hermitian = true , rng ))
81+ Ĥ₂ = SMatrix {N,N,ComplexF64} (random_matrix (N; hermitian = true , rng ))
7782 ϵ₁ (t) = 1.0
7883 ϵ₂ (t) = 1.0
7984 Ĥ_of_t = hamiltonian (Ĥ₀, (Ĥ₁, ϵ₁), (Ĥ₂, ϵ₂))
8287
8388 G̃_of_t = GradGenerator (Ĥ_of_t)
8489
85- Ψ = SVector {N,ComplexF64} (random_state_vector (N))
90+ Ψ = SVector {N,ComplexF64} (random_state_vector (N; rng ))
8691 Ψ̃ = GradVector (Ψ, length (get_controls (G̃_of_t)))
8792
8893 @test check_generator (G̃_of_t; state = Ψ̃, tlist, for_gradient_optimization = false )
9297
9398@testset " GradgenOperator Matrix Interface" begin
9499
100+ rng = StableRNG (3317751223 )
95101 N = 5
96102 L = 2
97103 G = Matrix {ComplexF64} (I, N, N)
98- mu = [rand (ComplexF64, N, N) for _ = 1 : L]
104+ mu = [rand (rng, ComplexF64, N, N) for _ = 1 : L]
99105 op = GradgenOperator {L,Matrix{ComplexF64},Matrix{ComplexF64}} (G, mu)
100- state = GradVector (rand (ComplexF64, N), L)
106+ state = GradVector (rand (rng, ComplexF64, N), L)
101107
102108 # supports_matrix_interface reports true for matrix-backed GradgenOperator
103109 @test supports_matrix_interface (typeof (op))
@@ -116,15 +122,15 @@ end
116122 @test all (collect (op) .≈ vec (dense))
117123
118124 # 3-arg mul! agrees with 5-arg mul!(Phi, G, Psi, true, false)
119- Psi = GradVector (rand (ComplexF64, N), L)
125+ Psi = GradVector (rand (rng, ComplexF64, N), L)
120126 Phi1 = GradVector (zeros (ComplexF64, N), L)
121127 Phi2 = GradVector (zeros (ComplexF64, N), L)
122128 mul! (Phi1, op, Psi)
123129 mul! (Phi2, op, Psi, true , false )
124130 @test norm (Phi1 - Phi2) < 1e-14
125131
126132 # 3-arg dot(Psi, op, Phi) matches dot(Psi, op * Phi)
127- Psi2 = GradVector (rand (ComplexF64, N), L)
133+ Psi2 = GradVector (rand (rng, ComplexF64, N), L)
128134 @test dot (state, op, Psi2) ≈ dot (state, op * Psi2)
129135
130136 # similar(op) returns a dense Array of the same eltype and size (matching Operator pattern)
@@ -147,11 +153,52 @@ end
147153end
148154
149155
156+ @testset " GradgenOperator flat-vector mul!" begin
157+
158+ rng = StableRNG (1602052280 )
159+ N = 5
160+ L = 2
161+ G = rand (rng, ComplexF64, N, N)
162+ mu = [rand (rng, ComplexF64, N, N) for _ = 1 : L]
163+ op = GradgenOperator {L,Matrix{ComplexF64},Matrix{ComplexF64}} (G, mu)
164+ dense = Array (op)
165+
166+ # Flat-vector layout: [grad_1 | grad_2 | ... | grad_L | state]
167+ Ψ_flat = rand (rng, ComplexF64, N * (L + 1 ))
168+ Φ_ref = dense * Ψ_flat
169+
170+ # 3-arg mul! agrees with the dense matrix-vector product
171+ Φ1 = zeros (ComplexF64, N * (L + 1 ))
172+ mul! (Φ1, op, Ψ_flat)
173+ @test norm (Φ1 - Φ_ref) < 1e-14
174+
175+ # 5-arg mul! with α=true, β=false matches the 3-arg result
176+ Φ2 = zeros (ComplexF64, N * (L + 1 ))
177+ mul! (Φ2, op, Ψ_flat, true , false )
178+ @test norm (Φ2 - Φ_ref) < 1e-14
179+
180+ # 5-arg mul! with non-trivial α, β: Φ ← α * G * Ψ + β * Φ
181+ α = 2.3 + 0.7im
182+ β = 1.5 - 0.3im
183+ Φ3 = rand (rng, ComplexF64, N * (L + 1 ))
184+ Φ3_init = copy (Φ3)
185+ mul! (Φ3, op, Ψ_flat, α, β)
186+ @test norm (Φ3 - (α * Φ_ref + β * Φ3_init)) < 1e-14
187+
188+ # works with views (the actual ExponentialUtilities use case)
189+ V = rand (rng, ComplexF64, N * (L + 1 ), 4 )
190+ mul! (view (V, :, 2 ), op, view (V, :, 1 ))
191+ @test norm (view (V, :, 2 ) - dense * view (V, :, 1 )) < 1e-14
192+
193+ end
194+
195+
150196@testset " GradVector Vector Interface" begin
151197
198+ rng = StableRNG (2618946253 )
152199 N = 5
153200 L = 2
154- Psi = rand (ComplexF64, N)
201+ Psi = rand (rng, ComplexF64, N)
155202 gradvec = GradVector (Psi, L)
156203
157204 # supports_vector_interface is true for Vector-backed GradVector
192239
193240@testset " GradVector Vector Interface (Static)" begin
194241
242+ rng = StableRNG (167987434 )
195243 N = 5
196244 L = 2
197- Psi = SVector {N,ComplexF64} (rand (ComplexF64, N))
245+ Psi = SVector {N,ComplexF64} (rand (rng, ComplexF64, N))
198246 gradvec = GradVector (Psi, L)
199247
200248 # SVector-backed GradVector: supports_vector_interface follows the component type
@@ -212,10 +260,11 @@ end
212260
213261@testset " GradVector without Vector Interface" begin
214262
263+ rng = StableRNG (4252840018 )
215264 N = 5
216265 L = 2
217266 # Matrix is not an AbstractVector, so supports_vector_interface returns false
218- Psi = rand (ComplexF64, N, N)
267+ Psi = rand (rng, ComplexF64, N, N)
219268 gradvec = GradVector (Psi, L)
220269
221270 @test ! supports_vector_interface (typeof (gradvec))
@@ -241,10 +290,11 @@ end
241290
242291@testset " GradgenOperator without Matrix Interface" begin
243292
293+ rng = StableRNG (1276996367 )
244294 N = 5
245295 L = 2
246- G = NonMatrixOp (rand (ComplexF64, N, N))
247- mu = [NonMatrixOp (rand (ComplexF64, N, N)) for _ = 1 : L]
296+ G = NonMatrixOp (rand (rng, ComplexF64, N, N))
297+ mu = [NonMatrixOp (rand (rng, ComplexF64, N, N)) for _ = 1 : L]
248298 op = GradgenOperator {L,NonMatrixOp,NonMatrixOp} (G, mu)
249299
250300 @test ! supports_matrix_interface (typeof (op))
0 commit comments