Example #1
0
    def _compute_unitary_oracle_matrix(
            bitstring_map: Dict[str,
                                str]) -> Tuple[np.ndarray, Dict[str, str]]:
        """
        Computes the unitary matrix that encodes the orcale function for Simon's algorithm

        :param bitstring_map: A truth-table of the input bitstring map in dictionary format.
        :return: A dense matrix containing the permutation of the bit strings and a dictionary
            containing the indices of the non-zero elements of the computed permutation matrix as
            key-value-pairs.
        """
        n_bits = len(list(bitstring_map.keys())[0])

        # We instantiate an empty matrix of size 2 * n_bits to encode the mapping from n qubits
        # to n ancillae, which explains the factor 2 overhead.
        # To construct the matrix we go through all possible state transitions and pad the index
        # according to all possible states the ancilla-subsystem could be in
        ufunc = np.zeros(shape=(2**(2 * n_bits), 2**(2 * n_bits)))
        index_mapping_dct = defaultdict(dict)
        for b in range(2**n_bits):
            # padding according to ancilla state
            pad_str = np.binary_repr(b, n_bits)
            for k, v in bitstring_map.items():
                # add mapping from initial state to the state in the ancilla system.
                # pad_str corresponds to the initial state of the ancilla system.
                index_mapping_dct[pad_str +
                                  k] = utils.bitwise_xor(pad_str, v) + k
                # calculate matrix indices that correspond to the transition-matrix-element
                # of the oracle unitary
                i, j = int(pad_str + k,
                           2), int(utils.bitwise_xor(pad_str, v) + k, 2)
                ufunc[i, j] = 1
        return ufunc, index_mapping_dct
Example #2
0
def create_1to1_bitmap(mask: str) -> Dict[str, str]:
    """
    Create a bit map function (as a dictionary) for a given mask.

    e.g., for a mask
    :math:`m = 10` the return is a dictionary:

    >>> create_1to1_bitmap('10')
    ... {
    ...     '00': '10',
    ...     '01': '11',
    ...     '10': '00',
    ...     '11': '01'
    ... }

    :param mask: A binary mask as a string of 0's and 1's.
    :return: A dictionary containing a mapping of all possible bit strings of the same length as the
        mask's string and their mapped bit-string value.
    """
    n_bits = len(mask)
    form_string = "{0:0" + str(n_bits) + "b}"
    bit_map_dct = {}
    for idx in range(2**n_bits):
        bit_string = form_string.format(idx)
        bit_map_dct[bit_string] = utils.bitwise_xor(bit_string, mask)
    return bit_map_dct
Example #3
0
    def _check_mask_correct(self):
        """
        Checks if a given mask correctly reproduces the function that was provided to the Simon
        algorithm. This can be done in :math:`O(n)` as it is a simple list traversal.

        :return: True if mask reproduces the input function
        :rtype: Bool
        """
        mask_str = ''.join([str(b) for b in self.mask])
        return all([self.bit_map[k] == self.bit_map[utils.bitwise_xor(k, mask_str)]
                    for k in self.bit_map.keys()])
Example #4
0
def test_bit_masking():
    bit_string = '101'
    mask_string = '110'
    assert u.bitwise_xor(bit_string, mask_string) == '011'