def J():
    I = jnp.array([[1, 0], [0, 1]])
    X = jnp.array([[0, 1], [1, 0]])
    I_f = jnp.kron(I, I)
    X_f = jnp.kron(X, X)
    J = jnp.array((1 / jnp.sqrt(2)) * (I_f + 1j * X_f))
    return J
Ejemplo n.º 2
0
def gate_expand_1toN(U, N, target):
    """
    Create a JAX array representing a 1-qubit gate acting on a system with N qubits.
    Parameters
    ----------
    U : 2 X 2 unitary matrix
        The one-qubit gate
    N : integer
        The number of qubits in the target space.
    target : integer
        The index of the target qubit.
    Returns
    -------
    gate : (2 ** N) X (2 ** N) unitary matrix
        Quantum object representation of N-qubit gate.
    """

    if N < 1:
        raise ValueError("integer N must be larger or equal to 1")

    if target >= N:
        raise ValueError("target must be integer < integer N")

    return jnp.kron(jnp.kron(jnp.eye(2**target), U),
                    jnp.eye(2**(N - target - 1)))
Ejemplo n.º 3
0
def circuit(params):
    thetax, thetay, thetaz = params
    layer0 = jnp.kron(basis(2, 0), basis(2, 0))
    layer1 = jnp.kron(ry(jnp.pi / 4), ry(jnp.pi / 4))
    layer2 = jnp.kron(rx(thetax), jnp.eye(2))
    layer3 = jnp.kron(ry(thetay), rz(thetaz))
    layers = [layer1, cnot(), layer2, cnot(), layer3]
    unitary = reduce(lambda x, y: jnp.dot(x, y), layers)
    return jnp.dot(unitary, layer0)
Ejemplo n.º 4
0
 def kernel_to_state_space(self, R=None):
     F_t, L_t, Qc_t, H_t, Pinf_t = self.temporal_kernel.kernel_to_state_space(
     )
     Kzz = self.spatial_kernel(self.z.value, self.z.value)
     F = np.kron(np.eye(self.M), F_t)
     Qc = None
     L = None
     H = self.measurement_model()
     Pinf = np.kron(Kzz, Pinf_t)
     return F, L, Qc, H, Pinf
Ejemplo n.º 5
0
def ising_hamiltonian(n_qubits, g, h):
    """ Construct the hamiltonian matrix of Ising model.

    Args:
        n_qubits: int, Number of qubits
        g: float, Transverse magnetic field
        h: float, Longitudinal magnetic field
    """
    ham_matrix = 0

    # Nearest-neighbor interaction
    spin_coupling = jnp.kron(PauliBasis[3], PauliBasis[3])

    for i in range(n_qubits - 1):
        ham_matrix -= jnp.kron(jnp.kron(jnp.eye(2**i), spin_coupling),
                               jnp.eye(2**(n_qubits - 2 - i)))
    ham_matrix -= jnp.kron(jnp.kron(PauliBasis[3], jnp.eye(2**(n_qubits - 2))),
                           PauliBasis[3])  # Periodic B.C

    # Transverse magnetic field
    for i in range(n_qubits):
        ham_matrix -= g * jnp.kron(jnp.kron(jnp.eye(2**i), PauliBasis[1]),
                                   jnp.eye(2**(n_qubits - 1 - i)))

    # Longitudinal magnetic field
    for i in range(n_qubits):
        ham_matrix -= h * jnp.kron(jnp.kron(jnp.eye(2**i), PauliBasis[3]),
                                   jnp.eye(2**(n_qubits - 1 - i)))
    return ham_matrix
def circuit(params):
    thetax, thetay, thetaz = params
    layer0 = jnp.array([[1], [0], [0], [0]])
    layer1 = J()
    layer2 = jnp.kron(rx(thetax), rx(thetax))
    layer3 = jnp.kron(ry(thetay), ry(thetay))
    layer4 = jnp.kron(rz(thetaz), rz(thetaz))
    layer5 = J_dag()
    layers = [layer5, layer4, layer3, layer2, layer1, layer0]
    q_state_out = reduce(lambda x, y: jnp.dot(x, y), layers)
    return q_state_out
Ejemplo n.º 7
0
def circuit(params):
    thetax, thetay, thetaz = params
    layer0 = jnp.kron(basis(2, 0), basis(2, 0))
    layer1 = J()
    layer2 = jnp.kron(rx(thetax), rx(thetax))
    layer3 = jnp.kron(ry(thetay), ry(thetay))
    layer4 = jnp.kron(rz(thetaz), rz(thetaz))
    layer5 = J_dag()
    layers = [layer5, layer4, layer3, layer2, layer1]
    unitary = reduce(lambda x, y: jnp.dot(x, y), layers)
    #unitary = np.dot(layer5,np.dot(layer4, np.dot(layer3, np.dot(layer2, layer1))))
    return jnp.dot(unitary, layer0)
Ejemplo n.º 8
0
def wavelet_tensors(request):
    """Returns the Hamiltonian and MERA tensors for the D=2 wavelet MERA.

  From Evenbly & White, Phys. Rev. Lett. 116, 140403 (2016).
  """
    D = 2
    h = simple_mera.ham_ising()

    E = np.array([[1, 0], [0, 1]])
    X = np.array([[0, 1], [1, 0]])
    Y = np.array([[0, -1j], [1j, 0]])
    Z = np.array([[1, 0], [0, -1]])

    wmat_un = np.real((np.sqrt(3) + np.sqrt(2)) / 4 * np.kron(E, E) +
                      (np.sqrt(3) - np.sqrt(2)) / 4 * np.kron(Z, Z) + 1.j *
                      (1 + np.sqrt(2)) / 4 * np.kron(X, Y) + 1.j *
                      (1 - np.sqrt(2)) / 4 * np.kron(Y, X))

    umat = np.real((np.sqrt(3) + 2) / 4 * np.kron(E, E) +
                   (np.sqrt(3) - 2) / 4 * np.kron(Z, Z) +
                   1.j / 4 * np.kron(X, Y) + 1.j / 4 * np.kron(Y, X))

    w = np.reshape(wmat_un, (D, D, D, D))[:, 0, :, :]
    u = np.reshape(umat, (D, D, D, D))

    w = np.transpose(w, [1, 2, 0])
    u = np.transpose(u, [2, 3, 0, 1])

    return tuple(x.astype(np.complex128) for x in (h, w, u))
Ejemplo n.º 9
0
    def initialize_Cinv(self, params):

        df = self.df
        Cinvs = [
            smoothness_kernel([
                params[i],
            ], df[i])[1] for i in range(len(df))
        ]

        if len(Cinvs) == 1:
            self.Cinv = Cinvs[0]
        elif len(Cinvs) == 2:
            self.Cinv = jnp.kron(*Cinvs)
        else:
            self.Cinv = jnp.kron(Cinvs[0], jnp.kron(Cinvs[1], Cinvs[2]))
Ejemplo n.º 10
0
    def __init__(self, tau_s=[3, 5, 100], NMDAratio=0.4, *args):
        """
        tau_s = [tau_AMPA, tau_GABA, tau_NMDA] or [tau_AMPA, tau_GABA]
          decay time-consants for synaptic currents of different receptor types.
        NMDAratio: scalar
          ratio of E synaptic weights that are NMDA-type
          (model assumes this fraction is constant in all weights)
        Good values:
         tau_AMPA = 4, tau_GABA= 5  #in ms
         NMDAratio = 0.3-0.4
        """
        if len(args) != 0:
            super(_SSN_AMPAGABA, self).__init__(*args)
        #super(_SSN_Base, _SSN_Base).__init__(*args)
        self.tau_s = np.squeeze(np.asarray(tau_s))
        self.tau_AMPA = tau_s[0]
        self.tau_GABA = tau_s[1]
        assert self.tau_s.size <= 3 and self.tau_s.ndim == 1
        if self.tau_s.size == 3 and NMDAratio > 0:
            self.tau_NMDA = tau_s[2]
            self.NMDAratio = NMDAratio
        else:
            self.tau_s = self.tau_s[:2]
            self.NMDAratio = 0
        self.num_rcpt = self.tau_s.size
        self.tau_s_vec = np.kron(self.tau_s, np.ones(self.N))

        W_AMPA = (1 - self.NMDAratio) * np.hstack(
            (self.W[:, :self.Ne], np.zeros((self.N, self.Ni))))
        W_GABA = np.hstack((np.zeros((self.N, self.Ne)), self.W[:, self.Ne:]))
        Wrcpt = [W_AMPA, W_GABA]
        if self.NMDAratio > 0:
            W_NMDA = self.NMDAratio / (1 - self.NMDAratio) * W_AMPA
            Wrcpt.append(W_NMDA)
        self.Wrcpt = np.vstack(Wrcpt)  # shape = (self.num_rcpt*self.N, self.N)
Ejemplo n.º 11
0
def make_oracle(n, f):
    """

    Form Quantum Oracle Matrix.
    Creates the unitary matrix representing an oracle from arbitrary function

        f : {0, 1} ^ n -> {0, 1} ^ n

    The matrix Uf, acts on (i.e. takes as input) two n-qbit registers. Its action
    on the first and second registers, when fully concentrated in the two computational
    basis states ∣x⟩∣y⟩ is given by

        Uf∣x⟩∣y⟩ = ∣x⟩∣y ⊕ f(x)⟩

    That is, the first register remain unchanged and the second register becomes
    the bitwise xor of its previous CBS (i.e. y) with the function, f, applied to the
    CBS of the first register, (i.e. x). The gate extends linearly to register states
    that are not fully concentrated in any CBS.

    As described by A Michael Loceff, Course in Quantum Computing (page 358)
    http://lapastillaroja.net/wp-content/uploads/2016/09/Intro_to_QC_Vol_1_Loceff.pdf

    We form this by letting the columns of the matrix Uf be the outputs for each
    computational basis state for the two registers.

    :param f: Callable function mapping {0, 1} ^ n -> {0, 1} ^ n
    :param n: Number of Qbits.
    :return: Unitary matrix that acts on two n-Qbit registers.
    """
    return np.array(
        [[np.kron(cbs(n, x), cbs(n, y | f(x))) for x in range(2**n)]
         for y in range(2**n)],
        dtype=dtype).T
Ejemplo n.º 12
0
    def V1_cost(self, W):
        # Weight factor, determining the weigth of the penalty
        weight = self.scheme[1]

        # Calculating the quadrupole matrix using the occupied orbitals.
        q_loc = jnp.einsum('ji,abjk,ki->iab',
                           W,
                           self.quadrupole_matrix_elem,
                           W,
                           optimize=True)

        # Calculating the trace of the quadrupole matrices.
        q_trace = jnp.einsum('iaa->i', q_loc, optimize=True) / 3.

        # Making the quadrupole traceless, we do this by constructing an
        # array of identity matrices and filling them with their corresponding
        # traces.
        q_loc_traceless = q_loc - jnp.kron(q_trace, jnp.eye(
            (3))).transpose().reshape(self.N_occ, 3, 3)

        # Calculating the matrix norm of the quadrupole matrix of
        # every occupied orbital.
        penalty = jnp.sum(q_loc_traceless**2)

        return self.FB_cost(W) - weight * penalty
Ejemplo n.º 13
0
def make_eE_noiseCov(ssn, noise_pars, LFPrange):
    # setting up e_E and e_I: the projection/measurement vectors for
    # representing the "LFP" measurement (e_E good for LFP interpretation, but e_I ?)
    # eE = np.zeros(ssn.N)
    # # eE[LFPrange] =1/len(LFPrange)
    # index_update(eE, LFPrange, 1/len(LFPrange))
    # eI = np.zeros(ssn.N)
    # eI[ssn.Ne + LFPrange] =1/len(LFPrange)

    eE = np.hstack((np.array([i in LFPrange for i in range(ssn.Ne)],
                             dtype=np.float32), np.zeros(ssn.Ni)))

    # the script assumes independent noise to E and I, and spatially uniform magnitude of noise
    noiseCov = np.hstack((noise_pars.stdevE**2 * np.ones(ssn.Ne),
                          noise_pars.stdevI**2 * np.ones(ssn.Ni)))

    OriVec = ssn.topos_vec
    if noise_pars.corr_length > 0 and OriVec.size > 1:  #assumes one E and one I at every topos
        dOri = np.abs(OriVec)
        L = OriVec.size * np.diff(OriVec[:2])
        dOri[dOri > L /
             2] = L - dOri[dOri > L / 2]  # distance on circle/periodic B.C.
        SpatialFilt = toeplitz(
            np.exp(-(dOri**2) / (2 * noise_pars.corr_length**2)) /
            np.sqrt(2 * pi) / noise_pars.corr_length * L / ssn.Ne)
        sigTau1Sprd1 = 0.394  # roughly the std of spatially and temporally filtered noise when the white seed is randn(ssn.Nthetas,Nt)/sqrt(dt) and corr_time=corr_length = 1 (ms or angle, respectively)
        SpatialFilt = SpatialFilt * np.sqrt(
            noise_pars.corr_length /
            2) / sigTau1Sprd1  # for the sake of output
        SpatialFilt = np.kron(np.eye(2), SpatialFilt)  # 2 for E/I
    else:
        SpatialFilt = np.array(1)

    return eE, noiseCov, SpatialFilt  # , eI
Ejemplo n.º 14
0
def concatenate_and_update(mu1, mu2, a, y, elo_functions, elo_params):
    """Combines mu1 and mu2 into a concatenated vector mu and uses this to
    calculate updated means mu1' and mu2'.

    Args:
        mu1: The winner's mean prior to the match.
        mu2: The loser's mean prior to the match.
        a: The vector such that a^T [mu1, mu2] = mu_delta.
        y: The observed outcomes.
        elo_functions: The functions required to compute the update
        elo_params: The parameters required for the update

    Returns:
    A Tuple with three elements: the first two contain the new means, the last
    the log likelihood of the result.
    """

    mu = jnp.concatenate([mu1, mu2])
    cov_full = jnp.kron(jnp.eye(2), elo_params.theta['cov_mat'])

    new_mu, lik = calculate_update(mu, cov_full, a, y, elo_functions,
                                   elo_params)

    new_mu1, new_mu2 = jnp.split(new_mu, 2)

    return new_mu1, new_mu2, lik
Ejemplo n.º 15
0
 def kernel_to_state_space(self, R=None):
     F_mat = np.array([[-1.0 / self.lengthscale]])
     L_mat = np.array([[1.0]])
     Qc_mat = np.array([[2.0 * self.variance / self.lengthscale]])
     H_mat = np.array([[1.0]])
     Pinf_mat = np.array([[self.variance]])
     F_cos = np.array([[0.0, -self.radial_frequency],
                       [self.radial_frequency, 0.0]])
     H_cos = np.array([[1.0, 0.0]])
     # F = (-1/l -ω
     #      ω    -1/l)
     F = np.kron(F_mat, np.eye(2)) + F_cos
     L = np.kron(L_mat, np.eye(2))
     Qc = np.kron(np.eye(2), Qc_mat)
     H = np.kron(H_mat, H_cos)
     Pinf = np.kron(Pinf_mat, np.eye(2))
     return F, L, Qc, H, Pinf
Ejemplo n.º 16
0
 def stationary_covariance(self):
     """
     Compute the covariance of the stationary state distribution. Since the latent components are independent
     under the prior, this is a block-diagonal matrix
     """
     Pinf_time = self.temporal_kernel.stationary_covariance()
     Pinf = np.kron(np.eye(self.M), Pinf_time)
     return Pinf
Ejemplo n.º 17
0
 def measurement_model(self):
     """
     Compute the spatial conditional, i.e. the measurement model projecting the state x(t) to function space
         f(t, R) = H x(t)
     """
     H_time = self.temporal_kernel.measurement_model()
     H = np.kron(np.eye(self.M), H_time)
     return H
Ejemplo n.º 18
0
 def kinetic(k, d_qtm_nk, nd_qtm):
     vly, = d_qtm_nk
     G = jnp.array(nd_qtm)
     K1, K2 = np.array([[1. / 3., 2. / 3.], [2. / 3., 1. / 3.]])
     K1, K2 = jnp.where(vly == 1, (K2, K1), (K1, K2))
     k1 = (k + G - K1) @ bvec
     k2 = (k + G - K2) @ bvec
     res = jnp.kron((sigma[0] + sigma[3]) / 2, -vF * k1[0] * vly * sigma[1] - vF * k1[1] * sigma[2]) + jnp.kron((sigma[0] - sigma[3]) / 2, -vF * k2[0] * vly * sigma[1] - vF * k2[1] * sigma[2])
     return res
Ejemplo n.º 19
0
 def state_transition(self, dt):
     """
     Calculation of the discrete-time state transition matrix A = expm(FΔt) for the spatio-temporal prior.
     :param dt: step size(s), Δtₙ = tₙ - tₙ₋₁ [scalar]
     :return: state transition matrix A
     """
     A_time = self.temporal_kernel.state_transition(dt)
     A = np.kron(np.eye(self.M), A_time)
     return A
Ejemplo n.º 20
0
def combine_matrices(a, b, Pia, Pib, check=True):
    # this combines INDEPENDENT transition matrices Pia and Pib
    grid = mat_combine(a, b)

    Pi = np.kron(Pia, Pib)

    if check:
        assert (all(abs(np.sum(Pi, axis=1) - 1) < 1e-5))

    return grid, Pi
Ejemplo n.º 21
0
def SYK_hamiltonian(rng, n_qubits):
    """ Construct the hamiltonian matrix of Ising model.

    Args:
        n_qubits: int, Number of qubits
        g: float, Transverse magnetic field
        h: float, Longitudinal magnetic field
    """
    # Construct the gamma matrices for SO(2 * n_qubits) Clifford algebra
    gamma_matrices, n_gamma = [], 2 * n_qubits

    for k in range(n_gamma):
        temp = jnp.eye(1)

        for j in range(k // 2):
            temp = jnp.kron(temp, PauliBasis[3])

        if k % 2 == 0:
            temp = jnp.kron(temp, PauliBasis[1])
        else:
            temp = jnp.kron(temp, PauliBasis[2])

        for i in range(int(n_gamma / 2) - (k // 2) - 1):
            temp = jnp.kron(temp, PauliBasis[0])

        gamma_matrices.append(temp)

    # Number of SYK4 interaction terms
    n_terms = int(factorial(n_gamma) / factorial(4) / factorial(n_gamma - 4))

    # SYK4 random coupling
    couplings = jax.random.normal(
        key=rng, shape=(n_terms, ), dtype=jnp.float64) * jnp.sqrt(6 /
                                                                  (n_gamma**3))

    ham_matrix = 0
    for idx, (x, y, w, z) in enumerate(combinations(range(n_gamma), 4)):
        ham_matrix += (couplings[idx] / 4) * jnp.linalg.multi_dot([
            gamma_matrices[x], gamma_matrices[y], gamma_matrices[w],
            gamma_matrices[z]
        ])

    return ham_matrix
Ejemplo n.º 22
0
    def __call__(self, inputs: Array) -> Array:
        """
        Applies a masked linear transformation to the inputs.

        Args:
          inputs: input data with dimensions (batch, length, features).

        Returns:
          The transformed data.
        """
        if inputs.ndim == 2:
            is_single_input = True
            inputs = jnp.expand_dims(inputs, axis=0)
        else:
            is_single_input = False

        batch, size, in_features = inputs.shape
        inputs = inputs.reshape((batch, size * in_features))

        if self.use_bias:
            bias = self.param(
                "bias", self.bias_init, (size, self.features), self.param_dtype
            )
        else:
            bias = None

        mask = jnp.ones((size, size), dtype=self.param_dtype)
        mask = jnp.triu(mask, self.exclusive)
        mask = jnp.kron(
            mask, jnp.ones((in_features, self.features), dtype=self.param_dtype)
        )

        kernel = self.param(
            "kernel",
            wrap_kernel_init(self.kernel_init, mask),
            (size * in_features, size * self.features),
            self.param_dtype,
        )

        inputs, mask, kernel, bias = promote_dtype(
            inputs, mask, kernel, bias, dtype=None
        )

        y = lax.dot(inputs, mask * kernel, precision=self.precision)

        y = y.reshape((batch, size, self.features))

        if is_single_input:
            y = y.squeeze(axis=0)

        if self.use_bias:
            y = y + bias

        return y
Ejemplo n.º 23
0
def circuit(params):
    """Returns the state evolved by
    the parametrized circuit
    
    Args:
        params (list): rotation angles for 
            x, y, and z rotations respectively.
        
    Returns:
        :obj:`jnp.array`: state evolved
        by a parametrized circuit
    """
    thetax, thetay, thetaz = params
    layer0 = jnp.kron(basis(2, 0), basis(2, 0))
    layer1 = jnp.kron(ry(jnp.pi / 4), ry(jnp.pi / 4))
    layer2 = jnp.kron(rx(thetax), jnp.eye(2))
    layer3 = jnp.kron(ry(thetay), rz(thetaz))
    layers = [layer1, cnot(), layer2, cnot(), layer3]
    unitary = reduce(lambda x, y: jnp.dot(x, y), layers)
    return jnp.dot(unitary, layer0)
Ejemplo n.º 24
0
 def hm(self, k, d_qtm_nk):
     data = tuple(
         map(lambda nd_qtm: self.kinetic(k, d_qtm_nk, nd_qtm),
             list(self.nd_basis.keys())))
     diag = jnp.kron(
         jnp.eye(self.num_nd_basis, dtype=jnp.complex64),
         jnp.ones((self.num_sub, self.num_sub), dtype=jnp.complex64))
     T = jnp.repeat(
         jnp.hstack(data).reshape(
             (1, -1)), self.num_nd_basis, axis=0).reshape(
                 (self.num_nd_bands, self.num_nd_bands)) * diag
     return jnp.asarray(T + self.V[d_qtm_nk])
Ejemplo n.º 25
0
def build_H_one_body(sites, L, H=None, sx=True, sy=True, sz=True):
    Sx = np.array([[0., 1.], [1., 0.]])
    Sy = np.array([[0., -1j], [1j, 0.]])
    Sz = np.array([[1., 0.], [0., -1.]])

    # S = [Sx, Sy, Sz]
    if H is None:
        H = np.zeros((2**L, 2**L), dtype=np.complex64)
    else:
        pass

    for i, V in sites:
        print("building", i)
        if sx:
            hx = np.kron(np.eye(2**(i - 1)), Sx)
            hx = np.kron(hx, np.eye(2**(L - i)))
            H = H + V * hx

        if sy:
            hy = np.kron(np.eye(2**(i - 1)), Sy)
            hy = np.kron(hy, np.eye(2**(L - i)))
            H = H + V * hy

        if sz:
            hz = np.kron(np.eye(2**(i - 1)), Sz)
            hz = np.kron(hz, np.eye(2**(L - i)))
            H = H + V * hz

    return H
Ejemplo n.º 26
0
def gate_expand_2toN(U, N, control=None, target=None):
    """
    Create a Qobj representing a two-qubit gate that act on a system with N
    qubits.
    Parameters
    ----------
    U : 4 X 4 unitary matrix
        The two-qubit gate
    N : integer
        The number of qubits in the target space.
    control : integer
        The index of the control qubit.
    target : integer
        The index of the target qubit.
    Returns
    -------
    gate :  (2 ** N) X (2 ** N) unitary matrix
        Quantum object representation of N-qubit gate.
    """

    if control is None or target is None:
        raise ValueError("Specify value of control and target")

    if N < 2:
        raise ValueError("integer N must be larger or equal to 2")

    if control >= N or target >= N:
        raise ValueError("control and not target must be integer < integer N")

    if control == target:
        raise ValueError("target and not control cannot be equal")

    p = list(range(N))

    if target == 0 and control == 1:
        p[control], p[target] = p[target], p[control]

    elif target == 0:
        p[1], p[target] = p[target], p[1]
        p[1], p[control] = p[control], p[1]

    else:
        p[1], p[target] = p[target], p[1]
        p[0], p[control] = p[control], p[0]

    matrix = jnp.kron(U, jnp.eye(2**(N - 2)))
    matrix = matrix.reshape(*([2 for _ in range(2 * N)]))
    matrix = matrix.transpose(p + [i + N for i in p])
    matrix = matrix.reshape(2**N, 2**N)

    return matrix
Ejemplo n.º 27
0
 def gate(self, params):
     # start with identity scalar and tensor-product all the gates
     mat = 1
     for g in self.gates:
         g = g.gate(params)
         mat = jnp.kron(mat, g)
     # if we have interleaved gates (i.e. a gate acting on qudit #1 and #3 but not #2)
     # then we need to un-permute the indices
     if self.permuted != self.regInfo.unpermuted:
         # reshape 2D unitary into qudit indices
         mat = mat.reshape(self.regInfo.shape)
         mat = jnp.moveaxis(mat, self.permuted, self.regInfo.unpermuted)
         mat = mat.reshape((self.regInfo.dim, self.regInfo.dim))
     return mat
Ejemplo n.º 28
0
def hadamard(n):
    """Hadamard operator for m qbits.

    :param n: Number of qbits
    :return: Matrix operator of size 2^m
    """
    if n < 0:
        raise ValueError(f'Invalid number of dimensions: {n}')
    if n == 0:
        return np.array(1, dtype=dtype)
    if n == 1:
        return np.array([[1, 1], [1, -1]], dtype=dtype) / np.sqrt(2)
    else:
        return np.kron(hadamard(1), hadamard(n - 1))
Ejemplo n.º 29
0
    def update_C_prior(self, params):

        """
        
        Using kronecker product to construct high-dimensional prior covariance.

        Given RF dims = [t, y, x], the prior covariance:

            C = kron(Ct, kron(Cy, Cx))
            Cinv = kron(Ctinv, kron(Cyinv, Cxinv))
            
        """

        n_hp_time = self.n_hp_time
        n_hp_space = self.n_hp_space

        rho = params[1]
        params_time = params[2: 2 + n_hp_time]

        # Covariance Matrix in Time
        C_t, C_t_inv = self.cov1d_time(params_time, self.dims[0])

        if len(self.dims) == 1:

            C, C_inv = rho * C_t, (1 / rho) * C_t_inv

        elif len(self.dims) == 2:

            # Covariance Matrix in Space 
            params_space = params[2 + n_hp_time: 2 + n_hp_time + n_hp_space]
            C_s, C_s_inv = self.cov1d_space(params_space, self.dims[1])

            # Build 2D Covariance Matrix 
            C = rho * jnp.kron(C_t, C_s)
            C_inv = (1 / rho) * jnp.kron(C_t_inv, C_s_inv)

        elif len(self.dims) == 3:

            # Covariance Matrix in Space 
            params_spacey = params[2 + n_hp_time: 2 + n_hp_time + n_hp_space]
            params_spacex = params[2 + n_hp_time + n_hp_space:]

            C_sy, C_sy_inv = self.cov1d_space(params_spacey, self.dims[1])
            C_sx, C_sx_inv = self.cov1d_space(params_spacex, self.dims[2])

            C_s = jnp.kron(C_sy, C_sx)
            C_s_inv = jnp.kron(C_sy_inv, C_sx_inv)

            # Build 3D Covariance Matrix
            C = rho * jnp.kron(C_t, C_s)
            C_inv = (1 / rho) * jnp.kron(C_t_inv, C_s_inv)

        else:
            raise NotImplementedError(len(self.dims))

        return C, C_inv
Ejemplo n.º 30
0
def simon(n, f):
    """Simon's Algorithm.

    Given function

        f :: {0, 1} ^ n -> {0, 1} ^ n

    that is periodic on a, i.e.

        f(x) = f(x ⊕ a)

    find a.

    :param n: Number of Qbits.
    :param f: Function which takes as input a number in [0, 2^n) and outputs.
    :return: The period of f.
    """
    x = hadamard(n) @ zero(n)  # Data register - top line.
    y = zero(n)
    uf = make_oracle(n, f)
    r = uf @ np.kron(x, y)
    s = np.kron(hadamard(n), eye(n)) @ r

    samples = [observe(s) for _ in range(n)]