Skip to content

Commit 9f0084a

Browse files
Strilancbabbush
authored andcommitted
Switch position_vector/momentum_vector to Grid (#50)
* Switch position_kinetic_operator to Grid * Switch momentum_potential_operator to Grid * Switch jordan_wigner_position_jellium to Grid * Switch position_potential_operator to Grid * Switch position_vector to Grid * Switch momentum_vector to Grid
1 parent 4bd6740 commit 9f0084a

File tree

3 files changed

+58
-87
lines changed

3 files changed

+58
-87
lines changed

src/fermilib/utils/_jellium.py

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -92,42 +92,37 @@ def grid_indices(qubit_id, n_dimensions, grid_length, spinless):
9292
return grid_indices
9393

9494

95-
def position_vector(position_indices, grid_length, length_scale):
95+
def position_vector(position_indices, grid):
9696
"""Given grid point coordinate, return position vector with dimensions.
9797
9898
Args:
9999
position_indices: List or tuple of integers giving grid point
100100
coordinate. Allowed values are ints in [0, grid_length).
101-
grid_length (int): The number of points in one dimension of the grid.
102-
length_scale (float): The real space length of a box dimension.
101+
grid (Grid): The discretization to use.
103102
104103
Returns:
105-
position_vector: A numpy array giving the position vector with
106-
dimensions.
104+
position_vector (numpy.ndarray[float])
107105
"""
108106
# Raise exceptions.
109107
if isinstance(position_indices, int):
110108
position_indices = [position_indices]
111-
if (not isinstance(grid_length, int) or
112-
max(position_indices) >= grid_length or
113-
min(position_indices) < 0.):
109+
if not all(0 <= e < grid.length for e in position_indices):
114110
raise OrbitalSpecificationError(
115111
'Position indices must be integers in [0, grid_length).')
116112

117113
# Compute position vector.
118-
adjusted_vector = numpy.array(position_indices, float) - grid_length // 2
119-
position_vector = length_scale * adjusted_vector / float(grid_length)
114+
adjusted_vector = numpy.array(position_indices, float) - grid.length // 2
115+
position_vector = grid.scale * adjusted_vector / float(grid.length)
120116
return position_vector
121117

122118

123-
def momentum_vector(momentum_indices, grid_length, length_scale):
119+
def momentum_vector(momentum_indices, grid):
124120
"""Given grid point coordinate, return momentum vector with dimensions.
125121
126122
Args:
127123
momentum_indices: List or tuple of integers giving momentum indices.
128124
Allowed values are ints in [0, grid_length).
129-
grid_length: Int, the number of points in one dimension of the grid.
130-
length_scale: Float, the real space length of a box dimension.
125+
grid (Grid): The discretization to use.
131126
132127
Returns:
133128
momentum_vector: A numpy array giving the momentum vector with
@@ -136,15 +131,13 @@ def momentum_vector(momentum_indices, grid_length, length_scale):
136131
# Raise exceptions.
137132
if isinstance(momentum_indices, int):
138133
momentum_indices = [momentum_indices]
139-
if (not isinstance(grid_length, int) or
140-
max(momentum_indices) >= grid_length or
141-
min(momentum_indices) < 0.):
134+
if not all(0 <= e < grid.length for e in momentum_indices):
142135
raise OrbitalSpecificationError(
143136
'Momentum indices must be integers in [0, grid_length).')
144137

145138
# Compute momentum vector.
146-
adjusted_vector = numpy.array(momentum_indices, float) - grid_length // 2
147-
momentum_vector = 2. * numpy.pi * adjusted_vector / length_scale
139+
adjusted_vector = numpy.array(momentum_indices, float) - grid.length // 2
140+
momentum_vector = 2. * numpy.pi * adjusted_vector / grid.scale
148141
return momentum_vector
149142

150143

@@ -167,7 +160,7 @@ def momentum_kinetic_operator(grid, spinless=False):
167160

168161
# Loop once through all plane waves.
169162
for momenta_indices in grid.all_points_indices():
170-
momenta = momentum_vector(momenta_indices, grid.length, grid.scale)
163+
momenta = momentum_vector(momenta_indices, grid)
171164
coefficient = momenta.dot(momenta) / 2.
172165

173166
# Loop over spins.
@@ -206,8 +199,7 @@ def momentum_potential_operator(grid, spinless=False):
206199
index in omega_indices]
207200

208201
# Get the momenta vectors.
209-
omega_momenta = momentum_vector(
210-
omega_indices, grid.length, grid.scale)
202+
omega_momenta = momentum_vector(omega_indices, grid)
211203

212204
# Skip if omega momentum is zero.
213205
if not omega_momenta.any():
@@ -270,18 +262,15 @@ def position_kinetic_operator(grid, spinless=False):
270262

271263
# Loop once through all lattice sites.
272264
for grid_indices_a in grid.all_points_indices():
273-
coordinates_a = position_vector(
274-
grid_indices_a, grid.length, grid.scale)
265+
coordinates_a = position_vector(grid_indices_a, grid)
275266
for grid_indices_b in grid.all_points_indices():
276-
coordinates_b = position_vector(
277-
grid_indices_b, grid.length, grid.scale)
267+
coordinates_b = position_vector(grid_indices_b, grid)
278268
differences = coordinates_b - coordinates_a
279269

280270
# Compute coefficient.
281271
coefficient = 0.
282272
for momenta_indices in grid.all_points_indices():
283-
momenta = momentum_vector(
284-
momenta_indices, grid.length, grid.scale)
273+
momenta = momentum_vector(momenta_indices, grid)
285274
if momenta.any():
286275
coefficient += (
287276
numpy.cos(momenta.dot(differences)) *
@@ -321,18 +310,15 @@ def position_potential_operator(grid, spinless=False):
321310

322311
# Loop once through all lattice sites.
323312
for grid_indices_a in grid.all_points_indices():
324-
coordinates_a = position_vector(
325-
grid_indices_a, grid.length, grid.scale)
313+
coordinates_a = position_vector(grid_indices_a, grid)
326314
for grid_indices_b in grid.all_points_indices():
327-
coordinates_b = position_vector(
328-
grid_indices_b, grid.length, grid.scale)
315+
coordinates_b = position_vector(grid_indices_b, grid)
329316
differences = coordinates_b - coordinates_a
330317

331318
# Compute coefficient.
332319
coefficient = 0.
333320
for momenta_indices in grid.all_points_indices():
334-
momenta = momentum_vector(
335-
momenta_indices, grid.length, grid.scale)
321+
momenta = momentum_vector(momenta_indices, grid)
336322
if momenta.any():
337323
coefficient += (
338324
prefactor * numpy.cos(momenta.dot(differences)) /
@@ -400,7 +386,7 @@ def jordan_wigner_position_jellium(grid, spinless=False):
400386
# Compute the identity coefficient.
401387
identity_coefficient = 0.
402388
for k_indices in grid.all_points_indices():
403-
momenta = momentum_vector(k_indices, grid.length, grid.scale)
389+
momenta = momentum_vector(k_indices, grid)
404390
if momenta.any():
405391
identity_coefficient += momenta.dot(momenta) / 2.
406392
identity_coefficient -= (numpy.pi * float(n_orbitals) /
@@ -415,7 +401,7 @@ def jordan_wigner_position_jellium(grid, spinless=False):
415401
# Compute coefficient of local Z terms.
416402
z_coefficient = 0.
417403
for k_indices in grid.all_points_indices():
418-
momenta = momentum_vector(k_indices, grid.length, grid.scale)
404+
momenta = momentum_vector(k_indices, grid)
419405
if momenta.any():
420406
z_coefficient += numpy.pi / (momenta.dot(momenta) * volume)
421407
z_coefficient -= momenta.dot(momenta) / (4. * float(n_orbitals))
@@ -429,17 +415,17 @@ def jordan_wigner_position_jellium(grid, spinless=False):
429415
prefactor = numpy.pi / volume
430416
for p in range(n_qubits):
431417
index_p = grid_indices(p, grid.dimensions, grid.length, spinless)
432-
position_p = position_vector(index_p, grid.length, grid.scale)
418+
position_p = position_vector(index_p, grid)
433419
for q in range(p + 1, n_qubits):
434420
index_q = grid_indices(q, grid.dimensions, grid.length, spinless)
435-
position_q = position_vector(index_q, grid.length, grid.scale)
421+
position_q = position_vector(index_q, grid)
436422

437423
differences = position_p - position_q
438424

439425
# Loop through momenta.
440426
zpzq_coefficient = 0.
441427
for k_indices in grid.all_points_indices():
442-
momenta = momentum_vector(k_indices, grid.length, grid.scale)
428+
momenta = momentum_vector(k_indices, grid)
443429
if momenta.any():
444430
zpzq_coefficient += prefactor * numpy.cos(
445431
momenta.dot(differences)) / momenta.dot(momenta)
@@ -452,20 +438,20 @@ def jordan_wigner_position_jellium(grid, spinless=False):
452438
prefactor = .25 / float(n_orbitals)
453439
for p in range(n_qubits):
454440
index_p = grid_indices(p, grid.dimensions, grid.length, spinless)
455-
position_p = position_vector(index_p, grid.length, grid.scale)
441+
position_p = position_vector(index_p, grid)
456442
for q in range(p + 1, n_qubits):
457443
if not spinless and (p + q) % 2:
458444
continue
459445

460446
index_q = grid_indices(q, grid.dimensions, grid.length, spinless)
461-
position_q = position_vector(index_q, grid.length, grid.scale)
447+
position_q = position_vector(index_q, grid)
462448

463449
differences = position_p - position_q
464450

465451
# Loop through momenta.
466452
term_coefficient = 0.
467453
for k_indices in grid.all_points_indices():
468-
momenta = momentum_vector(k_indices, grid.length, grid.scale)
454+
momenta = momentum_vector(k_indices, grid)
469455
if momenta.any():
470456
term_coefficient += prefactor * momenta.dot(momenta) * \
471457
numpy.cos(momenta.dot(differences))

src/fermilib/utils/_jellium_test.py

Lines changed: 23 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -64,62 +64,52 @@ def test_orbital_id(self):
6464
def test_position_vector(self):
6565

6666
# Test in 1D.
67-
grid_length = 4
68-
length_scale = 4.
69-
test_output = [position_vector(i, grid_length, length_scale)
70-
for i in range(grid_length)]
67+
grid = Grid(dimensions=1, length=4, scale=4.)
68+
test_output = [position_vector(i, grid)
69+
for i in range(grid.length)]
7170
correct_output = [-2, -1, 0, 1]
7271
self.assertEqual(correct_output, test_output)
7372

74-
grid_length = 11
75-
length_scale = 2. * numpy.pi
76-
for i in range(grid_length):
73+
grid = Grid(dimensions=1, length=11, scale=2. * numpy.pi)
74+
for i in range(grid.length):
7775
self.assertAlmostEqual(
78-
-position_vector(i, grid_length, length_scale),
79-
position_vector(
80-
grid_length - i - 1, grid_length, length_scale))
76+
-position_vector(i, grid),
77+
position_vector(grid.length - i - 1, grid))
8178

8279
# Test in 2D.
83-
grid_length = 3
84-
length_scale = 3.
80+
grid = Grid(dimensions=2, length=3, scale=3.)
8581
test_input = []
8682
test_output = []
8783
for i in range(3):
8884
for j in range(3):
8985
test_input += [(i, j)]
90-
test_output += [position_vector(
91-
(i, j), grid_length, length_scale)]
86+
test_output += [position_vector((i, j), grid)]
9287
correct_output = numpy.array([[-1., -1.], [-1., 0.], [-1., 1.],
9388
[0., -1.], [0., 0.], [0., 1.],
9489
[1., -1.], [1., 0.], [1., 1.]])
9590
self.assertAlmostEqual(0., numpy.amax(test_output - correct_output))
9691

9792
def test_momentum_vector(self):
98-
grid_length = 3
99-
length_scale = 2. * numpy.pi
100-
test_output = [momentum_vector(i, grid_length, length_scale)
101-
for i in range(grid_length)]
93+
grid = Grid(dimensions=1, length=3, scale=2. * numpy.pi)
94+
test_output = [momentum_vector(i, grid)
95+
for i in range(grid.length)]
10296
correct_output = [-1., 0, 1.]
10397
self.assertEqual(correct_output, test_output)
10498

105-
grid_length = 11
106-
length_scale = 2. * numpy.pi
107-
for i in range(grid_length):
99+
grid = Grid(dimensions=1, length=11, scale=2. * numpy.pi)
100+
for i in range(grid.length):
108101
self.assertAlmostEqual(
109-
-momentum_vector(i, grid_length, length_scale),
110-
momentum_vector(
111-
grid_length - i - 1, grid_length, length_scale))
102+
-momentum_vector(i, grid),
103+
momentum_vector(grid.length - i - 1, grid))
112104

113105
# Test in 2D.
114-
grid_length = 3
115-
length_scale = 2. * numpy.pi
106+
grid = Grid(dimensions=2, length=3, scale=2. * numpy.pi)
116107
test_input = []
117108
test_output = []
118109
for i in range(3):
119110
for j in range(3):
120111
test_input += [(i, j)]
121-
test_output += [momentum_vector(
122-
(i, j), grid_length, length_scale)]
112+
test_output += [momentum_vector((i, j), grid)]
123113
correct_output = numpy.array([[-1, -1], [-1, 0], [-1, 1],
124114
[0, -1], [0, 0], [0, 1],
125115
[1, -1], [1, 0], [1, 1]])
@@ -208,7 +198,7 @@ def test_coefficients(self):
208198
paper_kinetic_coefficient = 0.
209199
paper_potential_coefficient = 0.
210200
for indices in grid.all_points_indices():
211-
momenta = momentum_vector(indices, grid.length, grid.scale)
201+
momenta = momentum_vector(indices, grid)
212202
paper_kinetic_coefficient += float(
213203
n_qubits) * momenta.dot(momenta) / float(4. * n_orbitals)
214204

@@ -231,7 +221,7 @@ def test_coefficients(self):
231221
paper_kinetic_coefficient = 0.
232222
paper_potential_coefficient = 0.
233223
for indices in grid.all_points_indices():
234-
momenta = momentum_vector(indices, grid.length, grid.scale)
224+
momenta = momentum_vector(indices, grid)
235225
paper_kinetic_coefficient -= momenta.dot(
236226
momenta) / float(4. * n_orbitals)
237227

@@ -257,10 +247,8 @@ def test_coefficients(self):
257247
paper_kinetic_coefficient = 0.
258248
paper_potential_coefficient = 0.
259249

260-
position_a = position_vector(
261-
indices_a, grid.length, grid.scale)
262-
position_b = position_vector(
263-
indices_b, grid.length, grid.scale)
250+
position_a = position_vector(indices_a, grid)
251+
position_b = position_vector(indices_b, grid)
264252
differences = position_b - position_a
265253

266254
for spin_a in spins:
@@ -281,8 +269,7 @@ def test_coefficients(self):
281269
potential_coefficient = 0.
282270

283271
for indices_c in grid.all_points_indices():
284-
momenta = momentum_vector(
285-
indices_c, grid.length, grid.scale)
272+
momenta = momentum_vector(indices_c, grid)
286273

287274
if momenta.any():
288275
potential_contribution = numpy.pi * numpy.cos(

src/fermilib/utils/_plane_wave_hamiltonian.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@
2323
from fermilib.utils._jellium import (orbital_id, grid_indices, position_vector,
2424
momentum_vector, jellium_model)
2525
from fermilib.utils._molecular_data import periodic_hash_table
26-
from fermilib.utils._grid import Grid
27-
28-
from projectq.ops import QubitOperator
2926

3027

3128
def dual_basis_u_operator(grid, geometry, spinless):
@@ -49,12 +46,11 @@ def dual_basis_u_operator(grid, geometry, spinless):
4946
spins = [0, 1]
5047

5148
for pos_indices in grid.all_points_indices():
52-
coordinate_p = position_vector(pos_indices, grid.length, grid.scale)
49+
coordinate_p = position_vector(pos_indices, grid)
5350
for nuclear_term in geometry:
5451
coordinate_j = numpy.array(nuclear_term[1], float)
5552
for momenta_indices in grid.all_points_indices():
56-
momenta = momentum_vector(momenta_indices, grid.length,
57-
grid.scale)
53+
momenta = momentum_vector(momenta_indices, grid)
5854
momenta_squared = momenta.dot(momenta)
5955
if momenta_squared < EQ_TOLERANCE:
6056
continue
@@ -100,8 +96,7 @@ def plane_wave_u_operator(grid, geometry, spinless):
10096
grid_indices_p_q = [
10197
(indices_p[i] - indices_q[i] + shift) % grid.length
10298
for i in range(grid.dimensions)]
103-
momenta_p_q = momentum_vector(grid_indices_p_q, grid.length,
104-
grid.scale)
99+
momenta_p_q = momentum_vector(grid_indices_p_q, grid)
105100
momenta_p_q_squared = momenta_p_q.dot(momenta_p_q)
106101
if momenta_p_q_squared < EQ_TOLERANCE:
107102
continue
@@ -218,17 +213,20 @@ def _fourier_transform_helper(hamiltonian, n_dimensions, grid_length,
218213
length_scale, spinless, factor,
219214
vec_func_1, vec_func_2):
220215
hamiltonian_t = None
216+
grid = Grid(dimensions=n_dimensions,
217+
length=grid_length,
218+
scale=length_scale)
221219

222220
for term in hamiltonian.terms:
223221
transformed_term = None
224222
for ladder_operator in term:
225223
indices_1 = grid_indices(ladder_operator[0], n_dimensions,
226224
grid_length, spinless)
227-
vec_1 = vec_func_1(indices_1, grid_length, length_scale)
225+
vec_1 = vec_func_1(indices_1, grid)
228226
new_basis = None
229227
for indices_2 in itertools.product(range(grid_length),
230228
repeat=n_dimensions):
231-
vec_2 = vec_func_2(indices_2, grid_length, length_scale)
229+
vec_2 = vec_func_2(indices_2, grid)
232230
if spinless:
233231
spin = None
234232
else:

0 commit comments

Comments
 (0)