def test_flip_state_fock_infinite(): hi = Fock(N=2) rng = nk.jax.PRNGSeq(1) N_batches = 20 states = hi.random_state(rng.next(), N_batches, dtype=jnp.int64) ids = jnp.asarray( jnp.floor(hi.size * jax.random.uniform(rng.next(), shape=(N_batches, ))), dtype=int, ) new_states, old_vals = nk.hilbert.random.flip_state( hi, rng.next(), states, ids) assert new_states.shape == states.shape assert np.all(states >= 0) states_np = np.asarray(states) states_new_np = np.array(new_states) for (row, col) in enumerate(ids): states_new_np[row, col] = states_np[row, col] np.testing.assert_allclose(states_np, states_new_np)
def test_inhomogeneous_fock(): hi1 = Fock(n_max=7, N=40) hi2 = Fock(n_max=2, N=40) hi = hi1 * hi2 assert hi.size == hi1.size + hi2.size for i in range(0, 40): assert hi.size_at_index(i) == 8 assert hi.states_at_index(i) == list(range(8)) for i in range(40, 80): assert hi.size_at_index(i) == 3 assert hi.states_at_index(i) == list(range(3))
def _reorder_kronecker_product(hi, mat, acting_on) -> Tuple[Array, Tuple]: """ Reorders the matrix resulting from a kronecker product of several operators in such a way to sort acting_on. A conceptual example is the following: if `mat = Â ⊗ B̂ ⊗ Ĉ` and `acting_on = [[2],[1],[3]` you will get `result = B̂ ⊗ Â ⊗ Ĉ, [[1], [2], [3]]. However, essentially, A,B,C represent some operators acting on thei sub-space acting_on[1], [2] and [3] of the hilbert space. This function also handles any possible set of values in acting_on. The inner logic uses the Fock.all_states(), number_to_state and state_to_number to perform the re-ordering. """ acting_on_sorted = np.sort(acting_on) if np.array_equal(acting_on_sorted, acting_on): return mat, acting_on # could write custom binary <-> int logic instead of using Fock... # Since i need to work with bit-strings (where instead of bits i # have integers, in order to support arbitrary size spaces) this # is exactly what hilbert.to_number() and viceversa do. # target ordering binary representation hi_subspace = Fock(hi.shape[acting_on_sorted[0]] - 1) for site in acting_on_sorted[1:]: hi_subspace = hi_subspace * Fock(hi.shape[site] - 1) hi_unsorted_subspace = Fock(hi.shape[acting_on[0]] - 1) for site in acting_on[1:]: hi_unsorted_subspace = hi_unsorted_subspace * Fock(hi.shape[site] - 1) # find how to map target ordering back to unordered acting_on_unsorted_ids = np.zeros(len(acting_on), dtype=np.intp) for (i, site) in enumerate(acting_on): acting_on_unsorted_ids[i] = np.argmax(site == acting_on_sorted) # now it is valid that # acting_on_sorted == acting_on[acting_on_unsorted_ids] # generate n-bit strings in the target ordering v = hi_subspace.all_states() # convert them to origin (unordered) ordering v_unsorted = v[:, acting_on_unsorted_ids] # convert the unordered bit-strings to numbers in the target space. n_unsorted = hi_unsorted_subspace.states_to_numbers(v_unsorted) # reorder the matrix mat_sorted = mat[n_unsorted, :][:, n_unsorted] return mat_sorted, tuple(acting_on_sorted)
def _reorder_matrix(hi, mat, acting_on): acting_on_sorted = np.sort(acting_on) if np.all(acting_on_sorted == acting_on): return mat, acting_on acting_on_sorted_ids = np.argsort(acting_on) # could write custom binary <-> int logic instead of using Fock... # Since i need to work with bit-strings (where instead of bits i # have integers, in order to support arbitrary size spaces) this # is exactly what hilbert.to_number() and viceversa do. # target ordering binary representation hi_subspace = Fock(hi.shape[acting_on_sorted[0]] - 1) for site in acting_on_sorted[1:]: hi_subspace = Fock(hi.shape[site] - 1) * hi_subspace # find how to map target ordering back to unordered acting_on_unsorted_ids = np.zeros(len(acting_on), dtype=np.intp) for (i, site) in enumerate(acting_on): acting_on_unsorted_ids[i] = np.argmax(site == acting_on_sorted) # now it is valid that # acting_on_sorted == acting_on[acting_on_unsorted_ids] # generate n-bit strings in the target ordering v = hi_subspace.all_states() # convert them to origin (unordered) ordering v_unsorted = v[:, acting_on_unsorted_ids] # convert the unordered bit-strings to numbers in the target space. n_unsorted = hi_subspace.states_to_numbers(v_unsorted) # reorder the matrix mat_sorted = mat[n_unsorted, :][:, n_unsorted] return mat_sorted, acting_on_sorted
def test_random_states_fock_infinite(): hi = Fock(N=2) rstate = hi.random_state(jax.random.PRNGKey(14), 20) assert np.all(rstate >= 0) assert rstate.shape == (20, 2)
# Spin 1/2 with total Sz hilberts["Spin[0.5, N=20, total_sz=1"] = Spin(s=0.5, total_sz=1.0, N=20) hilberts["Spin[0.5, N=5, total_sz=-1.5"] = Spin(s=0.5, total_sz=-1.5, N=5) # Spin 1/2 with total Sz hilberts["Spin 1 with total Sz, even sites"] = Spin(s=1.0, total_sz=5.0, N=6) # Spin 1/2 with total Sz hilberts["Spin 1 with total Sz, odd sites"] = Spin(s=1.0, total_sz=2.0, N=7) # Spin 3 hilberts["Spin 3"] = Spin(s=3, N=25) # Boson hilberts["Fock"] = Fock(n_max=5, N=41) # Boson with total number hilberts["Fock with total number"] = Fock(n_max=3, n_particles=110, N=120) # Composite Fock hilberts["Fock * Fock (indexable)"] = Fock(n_max=5, N=4) * Fock(n_max=7, N=4) hilberts["Fock * Fock (non-indexable)"] = Fock(n_max=4, N=40) * Fock(n_max=7, N=40) # Qubit hilberts["Qubit"] = nk.hilbert.Qubit(100) # Custom Hilbert hilberts["Custom Hilbert"] = CustomHilbert(local_states=[-1232, 132, 0], N=70)
# Spin 1/2 with total Sz hilberts["Spin[0.5, N=20, total_sz=1"] = Spin(s=0.5, total_sz=1.0, N=20) hilberts["Spin[0.5, N=5, total_sz=-1.5"] = Spin(s=0.5, total_sz=-1.5, N=5) # Spin 1/2 with total Sz hilberts["Spin 1 with total Sz, even sites"] = Spin(s=1.0, total_sz=5.0, N=6) # Spin 1/2 with total Sz hilberts["Spin 1 with total Sz, odd sites"] = Spin(s=1.0, total_sz=2.0, N=7) # Spin 3 hilberts["Spin 3"] = Spin(s=3, N=25) # Boson hilberts["Fock"] = Fock(n_max=5, N=41) # Boson with total number hilberts["Fock with total number"] = Fock(n_max=3, n_particles=110, N=120) # Qubit hilberts["Qubit"] = nk.hilbert.Qubit(100) # Custom Hilbert hilberts["Custom Hilbert"] = CustomHilbert(local_states=[-1232, 132, 0], N=70) # Heisenberg 1d hilberts["Heisenberg 1d"] = Spin(s=0.5, total_sz=0.0, N=20) # Bose Hubbard hilberts["Bose Hubbard"] = Fock(n_max=4, n_particles=20, N=20)