def _compute_unitary_oracle_matrix(bitstring_map: Dict[str, str]) -> Tuple[np.ndarray,
                                                                               Dict[str, str]]:
        """
        Computes the unitary matrix that encodes the oracle function  used in the Bernstein-Vazirani
        algorithm. It generates a dense matrix for a function :math:`f`

        .. math::

           f:\\{0,1\\}^n\\rightarrow \\{0,1\\}

           \\mathbf{x}\\rightarrow \\mathbf{a}\\cdot\\mathbf{x}+b\\pmod{2}

           (\\mathbf{a}\\in\\{0,1\\}^n, b\\in\\{0,1\\})

        where :math:`(\\cdot)` is the bitwise dot product, that represents the transition-matrix
        elements of the corresponding qubit and ancilla subsystems.

        :param Dict[String, String] bitstring_map: 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
        :rtype: Tuple[2darray, Dict[String, String]]
        """
        n_bits = len(list(bitstring_map.keys())[0])
        n_ancillas = 1

        # We instantiate an empty matrix of size n_bits + 1 to encode the mapping from n qubits
        # to one ancillas, which explains the additional +1 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 ** (n_bits + 1), 2 ** (n_bits + 1)))
        index_mapping_dct = defaultdict(dict)
        for b in range(2**n_ancillas):
            # padding according to ancilla state
            pad_str = np.binary_repr(b, width=1)
            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
Computes the unitary matrix that encodes the oracle function  used in the Bernstein-Vazirani
        algorithm. It generates a dense matrix for a function :math:`f`

        .. math::

           f:\\{0,1\\}^n\\rightarrow \\{0,1\\}

           \\mathbf{x}\\rightarrow \\mathbf{a}\\cdot\\mathbf{x}+b\\pmod{2}

           (\\mathbf{a}\\in\\{0,1\\}^n, b\\in\\{0,1\\})

        where :math:`(\\cdot)` is the bitwise dot product, that represents the transition-matrix
        elements of the corresponding qubit and ancilla subsystems.

        :param Dict[String, String] bitstring_map: 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
        :rtype: Tuple[2darray, Dict[String, String]]