def test_orbital_id(self): # Test in 1D with spin. grid = Grid(dimensions=1, length=5, scale=1.0) input_coords = [0, 1, 2, 3, 4] tensor_factors_up = [1, 3, 5, 7, 9] tensor_factors_down = [0, 2, 4, 6, 8] test_output_up = [grid.orbital_id(i, 1) for i in input_coords] test_output_down = [grid.orbital_id(i, 0) for i in input_coords] self.assertEqual(test_output_up, tensor_factors_up) self.assertEqual(test_output_down, tensor_factors_down) with self.assertRaises(OrbitalSpecificationError): grid.orbital_id(6, 1) # Test in 2D without spin. grid = Grid(dimensions=2, length=3, scale=1.0) input_coords = [(0, 0), (0, 1), (1, 2)] tensor_factors = [0, 3, 7] test_output = [grid.orbital_id(i) for i in input_coords] self.assertEqual(test_output, tensor_factors)
def test_coefficients(self): # Test that the coefficients post-JW transform are as claimed in paper. grid = Grid(dimensions=2, length=3, scale=2.) spinless = 1 n_orbitals = grid.num_points n_qubits = (2**(1 - spinless)) * n_orbitals volume = grid.volume_scale() # Kinetic operator. kinetic = dual_basis_kinetic(grid, spinless) qubit_kinetic = jordan_wigner(kinetic) # Potential operator. potential = dual_basis_potential(grid, spinless) qubit_potential = jordan_wigner(potential) # Check identity. identity = tuple() kinetic_coefficient = qubit_kinetic.terms[identity] potential_coefficient = qubit_potential.terms[identity] paper_kinetic_coefficient = 0. paper_potential_coefficient = 0. for indices in grid.all_points_indices(): momenta = grid.momentum_vector(indices) paper_kinetic_coefficient += float(n_qubits) * momenta.dot( momenta) / float(4. * n_orbitals) if momenta.any(): potential_contribution = -numpy.pi * float(n_qubits) / float( 2. * momenta.dot(momenta) * volume) paper_potential_coefficient += potential_contribution self.assertAlmostEqual(kinetic_coefficient, paper_kinetic_coefficient) self.assertAlmostEqual(potential_coefficient, paper_potential_coefficient) # Check Zp. for p in range(n_qubits): zp = ((p, 'Z'), ) kinetic_coefficient = qubit_kinetic.terms[zp] potential_coefficient = qubit_potential.terms[zp] paper_kinetic_coefficient = 0. paper_potential_coefficient = 0. for indices in grid.all_points_indices(): momenta = grid.momentum_vector(indices) paper_kinetic_coefficient -= momenta.dot(momenta) / float( 4. * n_orbitals) if momenta.any(): potential_contribution = numpy.pi / float( momenta.dot(momenta) * volume) paper_potential_coefficient += potential_contribution self.assertAlmostEqual(kinetic_coefficient, paper_kinetic_coefficient) self.assertAlmostEqual(potential_coefficient, paper_potential_coefficient) # Check Zp Zq. if spinless: spins = [None] for indices_a in grid.all_points_indices(): for indices_b in grid.all_points_indices(): potential_coefficient = 0. paper_kinetic_coefficient = 0. paper_potential_coefficient = 0. position_a = grid.position_vector(indices_a) position_b = grid.position_vector(indices_b) differences = position_b - position_a for spin_a in spins: for spin_b in spins: p = grid.orbital_id(indices_a, spin_a) q = grid.orbital_id(indices_b, spin_b) if p == q: continue zpzq = ((min(p, q), 'Z'), (max(p, q), 'Z')) if zpzq in qubit_potential.terms: potential_coefficient = qubit_potential.terms[zpzq] for indices_c in grid.all_points_indices(): momenta = grid.momentum_vector(indices_c) if momenta.any(): potential_contribution = numpy.pi * numpy.cos( differences.dot(momenta)) / float( momenta.dot(momenta) * volume) paper_potential_coefficient += ( potential_contribution) self.assertAlmostEqual(potential_coefficient, paper_potential_coefficient)
def test_coefficients(self): # Test that the coefficients post-JW transform are as claimed in paper. spinless = True non_periodics = [False, True] # [[spatial dimension, fieldline dimension]]. dims = [[2, 2], [2, 3], [3, 3]] # Reference length scale where the 2D Coulomb potential is zero. R0 = 1e8 for dim in dims: # If dim[0] == 2, get range(2, 4). # If dim[0] == 3, get range(2, 3). for length in range(2, 6 - dim[0]): for non_periodic in non_periodics: grid = Grid(dimensions=dim[0], length=length, scale=2.) n_orbitals = grid.num_points n_qubits = (2**(1 - spinless)) * n_orbitals volume = grid.volume_scale() period_cutoff = None if non_periodic: period_cutoff = volume**(1. / grid.dimensions) fieldlines = dim[1] # Kinetic operator. kinetic = dual_basis_kinetic(grid, spinless) qubit_kinetic = jordan_wigner(kinetic) # Potential operator. potential = dual_basis_potential( grid, spinless, non_periodic=non_periodic, period_cutoff=period_cutoff, fieldlines=fieldlines) qubit_potential = jordan_wigner(potential) # Check identity. identity = tuple() kinetic_coefficient = qubit_kinetic.terms[identity] potential_coefficient = qubit_potential.terms[identity] paper_kinetic_coefficient = 0. paper_potential_coefficient = 0. for indices in grid.all_points_indices(): momenta = grid.momentum_vector(indices) momenta_squared = momenta.dot(momenta) paper_kinetic_coefficient += (float(n_qubits) * momenta_squared / float(4. * n_orbitals)) if momenta.any(): potential_contribution = 0. # 3D case. if grid.dimensions == 3: potential_contribution = -( numpy.pi * float(n_qubits) / float(2. * momenta_squared * volume)) # If non-periodic. if non_periodic: correction = 1.0 - numpy.cos( period_cutoff * numpy.sqrt(momenta_squared)) potential_contribution *= correction # 2D case. elif grid.dimensions == 2: V_nu = 0. # 2D Coulomb potential. if fieldlines == 2: # If non-periodic. if non_periodic: Dkv = period_cutoff * numpy.sqrt( momenta_squared) V_nu = ( 2. * numpy.pi / momenta_squared * (Dkv * numpy.log(R0 / period_cutoff) * scipy.special.jv(1, Dkv) - scipy.special.jv(0, Dkv))) # If periodic. else: var1 = 4. / momenta_squared var2 = 0.25 * momenta_squared V_nu = 0.5 * numpy.complex128( mpmath.meijerg([[1., 1.5, 2.], []], [[1.5], []], var1) - mpmath.meijerg( [[-0.5, 0., 0.], []], [[-0.5, 0.], [-1.]], var2)) # 3D Coulomb potential. elif fieldlines == 3: # If non-periodic. if non_periodic: var = (-0.25 * period_cutoff**2 * momenta_squared) V_nu = numpy.complex128( 2 * numpy.pi * period_cutoff * mpmath.hyp1f2(0.5, 1., 1.5, var)) # If periodic. else: V_nu = (2 * numpy.pi / numpy.sqrt(momenta_squared)) potential_contribution = (-float(n_qubits) / (8. * volume) * V_nu) paper_potential_coefficient += potential_contribution # Check if coefficients are equal. self.assertAlmostEqual(kinetic_coefficient, paper_kinetic_coefficient) self.assertAlmostEqual(potential_coefficient, paper_potential_coefficient) # Check Zp. for p in range(n_qubits): zp = ((p, 'Z'), ) kinetic_coefficient = qubit_kinetic.terms[zp] potential_coefficient = qubit_potential.terms[zp] paper_kinetic_coefficient = 0. paper_potential_coefficient = 0. for indices in grid.all_points_indices(): momenta = grid.momentum_vector(indices) momenta_squared = momenta.dot(momenta) paper_kinetic_coefficient -= ( momenta_squared / float(4. * n_orbitals)) if momenta.any(): potential_contribution = 0. # 3D case. if grid.dimensions == 3: potential_contribution = ( numpy.pi / float(momenta_squared * volume)) # If non-periodic. if non_periodic: correction = 1.0 - numpy.cos( period_cutoff * numpy.sqrt(momenta_squared)) potential_contribution *= correction # 2D case. elif grid.dimensions == 2: V_nu = 0. # 2D Coulomb potential. if fieldlines == 2: # If non-periodic. if non_periodic: Dkv = period_cutoff * numpy.sqrt( momenta_squared) V_nu = (2. * numpy.pi / momenta_squared * (Dkv * numpy.log( R0 / period_cutoff) * scipy.special.jv(1, Dkv) - scipy.special.jv(0, Dkv))) # If periodic. else: var1 = 4. / momenta_squared var2 = 0.25 * momenta_squared V_nu = 0.5 * numpy.complex128( mpmath.meijerg( [[1., 1.5, 2.], []], [[1.5], []], var1) - mpmath.meijerg( [[-0.5, 0., 0.], []], [[-0.5, 0.], [-1.]], var2)) # 3D Coulomb potential. elif fieldlines == 3: # If non-periodic. if non_periodic: var = (-0.25 * period_cutoff**2 * momenta_squared) V_nu = numpy.complex128( 2 * numpy.pi * period_cutoff * mpmath.hyp1f2( 0.5, 1., 1.5, var)) # If periodic. else: V_nu = ( 2 * numpy.pi / numpy.sqrt(momenta_squared)) potential_contribution = (1. / (4. * volume) * V_nu) paper_potential_coefficient += potential_contribution # Check if coefficients are equal. self.assertAlmostEqual(kinetic_coefficient, paper_kinetic_coefficient) self.assertAlmostEqual(potential_coefficient, paper_potential_coefficient) # Check Zp Zq. if spinless: spins = [None] for indices_a in grid.all_points_indices(): for indices_b in grid.all_points_indices(): potential_coefficient = 0. paper_kinetic_coefficient = 0. paper_potential_coefficient = 0. position_a = grid.position_vector(indices_a) position_b = grid.position_vector(indices_b) differences = position_b - position_a for spin_a in spins: for spin_b in spins: p = grid.orbital_id(indices_a, spin_a) q = grid.orbital_id(indices_b, spin_b) if p == q: continue zpzq = ((min(p, q), 'Z'), (max(p, q), 'Z')) if zpzq in qubit_potential.terms: potential_coefficient = qubit_potential.terms[ zpzq] for indices_c in grid.all_points_indices(): momenta = grid.momentum_vector( indices_c) momenta_squared = momenta.dot(momenta) if momenta.any(): potential_contribution = 0. # 3D case. if grid.dimensions == 3: potential_contribution = ( numpy.pi * numpy.cos( differences.dot( momenta)) / float(momenta_squared * volume)) # If non-periodic. if non_periodic: correction = 1.0 - numpy.cos( period_cutoff * numpy. sqrt(momenta_squared)) potential_contribution *= correction # 2D case. elif grid.dimensions == 2: V_nu = 0. # 2D Coulomb potential. if fieldlines == 2: # If non-periodic. if non_periodic: Dkv = ( period_cutoff * numpy.sqrt( momenta_squared )) V_nu = ( 2. * numpy.pi / momenta_squared * (Dkv * numpy.log( R0 / period_cutoff) * scipy.special. jv(1, Dkv) - scipy.special.jv( 0, Dkv))) # If periodic. else: var1 = 4. / momenta_squared var2 = 0.25 * momenta_squared V_nu = 0.5 * numpy.complex128( mpmath.meijerg([[ 1., 1.5, 2. ], []], [[1.5], [] ], var1) - mpmath.meijerg([[ -0.5, 0., 0. ], []], [[ -0.5, 0. ], [-1.]], var2)) # 3D Coulomb potential. elif fieldlines == 3: # If non-periodic. if non_periodic: var = -0.25 * period_cutoff**2 * momenta_squared V_nu = numpy.complex128( 2 * numpy.pi * period_cutoff * mpmath.hyp1f2( 0.5, 1., 1.5, var)) # If periodic. else: V_nu = 2 * numpy.pi / numpy.sqrt( momenta_squared) potential_contribution = ( numpy.cos( differences.dot( momenta)) / (4. * volume) * V_nu) paper_potential_coefficient += potential_contribution # Check if coefficients are equal. self.assertAlmostEqual( potential_coefficient, paper_potential_coefficient)