Quantum Finite Automata (QFA) are a quantum counterpart of classical finite automata, using the principles of quantum mechanics to process information. A QFA can exist in a superposition of states, and its transitions are determined by complex-valued amplitudes rather than probabilities. QFAs have the potential to solve specific problems more efficiently than their classical counterparts.
In this project, we aim to implement a QFA simulator in C++ with a focus on simplicity and elegance, showcasing the nature of QFAs.
Allow users to represent QFA states using N-state qubits, utilizing complex projective space and inner product to define the state space. This feature will enable users to define and manipulate quantum states in the automaton.
In a quantum system, a quantum state is a linear combination of basis states, and each basis state is associated with a complex number called the amplitude. These amplitudes contain information about the probability of the quantum system being in that particular basis state when measured. The square of the modulus of the amplitude of a basis state represents the probability of finding the quantum system in that specific state when a measurement is performed.
For example, consider a qubit (2-state system) in the following state:
Here,
In the context of the code example provided, the QuantumState
class represents a quantum state with N-state qubits (generalization of a qubit), and each entry in the std::vector
of complex numbers corresponds to the amplitude of a basis state in the quantum system.
class QuantumState {
public:
QuantumState(int n) : state_vector(n) {}
void set_amplitude(int index, const std::complex<double>& amplitude) {
state_vector[index] = amplitude;
}
std::complex<double> get_amplitude(int index) const {
return state_vector[index];
}
void print() const {
for (const auto& amplitude : state_vector) {
std::cout << amplitude << " ";
}
std::cout << std::endl;
}
private:
std::vector<std::complex<double>> state_vector;
};
int main() {
int N = 3; // Number of states in the QFA
QuantumState qfa_state(N);
// Set amplitudes for the quantum state
qfa_state.set_amplitude(0, std::complex<double>(0.5, 0.5));
qfa_state.set_amplitude(1, std::complex<double>(0.5, -0.5));
qfa_state.set_amplitude(2, std::complex<double>(0.0, 0.0));
// Print the quantum state
qfa_state.print();
return 0;
}
Implement state transitions using N×N unitary matrices for each input symbol. This feature allows users to specify quantum state transitions corresponding to each input symbol.
A transition matrix represents the evolution of the automaton's internal states when processing a specific input symbol. Each input symbol is associated with an
A unitary matrix
The transition matrix
In MO-QFA, the transition matrices are unitary to ensure the preservation of the quantum mechanical rules and the coherence of the quantum system during the transitions. These matrices play a crucial role in determining the probability of acceptance of a given input string by the automaton.
class QuantumTransition {
public:
QuantumTransition(int n) : n_states(n) {}
void set_transition_matrix(char symbol, const std::vector<std::vector<std::complex<double>>>& matrix) {
transition_matrices[symbol] = matrix;
}
QuantumState apply_transition(char symbol, const QuantumState& initial_state) {
QuantumState final_state(n_states);
for (int i = 0; i < n_states; ++i) {
std::complex<double> new_amplitude(0, 0);
for (int j = 0; j < n_states; ++j) {
new_amplitude += transition_matrices[symbol][i][j] * initial_state.get_amplitude(j);
}
final_state.set_amplitude(i, new_amplitude);
}
return final_state;
}
private:
int n_states;
std::unordered_map<char, std::vector<std::vector<std::complex<double>>>> transition_matrices;
};
int main() {
int N = 3; // Number of states in the QFA
// Define the quantum state
QuantumState qfa_state(N);
// Set amplitudes for the quantum state
qfa_state.set_amplitude(0, std::complex<double>(0.5, 0.5));
qfa_state.set_amplitude(1, std::complex<double>(0.5, -0.5));
qfa_state.set_amplitude(2, std::complex<double>(0.0, 0.0));
// Print the quantum state
qfa_state.print();
// Define the QuantumTransition with the number of states
QuantumTransition qfa_transition(N);
// Set transition matrices for each input symbol
qfa_transition.set_transition_matrix('a', {{{1.0, 0.0, 0.0},
{0.0, 0.5, 0.5},
{0.0, 0.5, -0.5}}});
qfa_transition.set_transition_matrix('b', {{{0.5, 0.5, 0.0},
{0.5, -0.5, 0.0},
{0.0, 0.0, 1.0}}});
// Apply the transition based on an input symbol
QuantumState final_state = qfa_transition.apply_transition('a', qfa_state);
// Print the final quantum state after the transition
final_state.print();
return 0;
}
Provide the functionality to create a quantum semiautomaton with the triple
class QuantumSemiautomaton {
public:
QuantumSemiautomaton(int n, const std::vector<char>& input_alphabet)
: n_states(n), alphabet(input_alphabet), qfa_state(n), qfa_transition(n) {}
void set_initial_amplitude(int index, const std::complex<double>& amplitude) {
qfa_state.set_amplitude(index, amplitude);
}
void set_transition_matrix(char symbol, const std::vector<std::vector<std::complex<double>>>& matrix) {
qfa_transition.set_transition_matrix(symbol, matrix);
}
QuantumState apply_transition(const std::string& input) {
QuantumState current_state = qfa_state;
for (char symbol : input) {
current_state = qfa_transition.apply_transition(symbol, current_state);
}
return current_state;
}
private:
int n_states;
std::vector<char> alphabet;
QuantumState qfa_state;
QuantumTransition qfa_transition;
};
int main() {
int N = 3; // Number of states in the QFA
std::vector<char> input_alphabet = {'a', 'b'};
// Define the quantum semiautomaton
QuantumSemiautomaton qfa(N, input_alphabet);
// Set initial amplitudes for the quantum state
qfa.set_initial_amplitude(0, std::complex<double>(0.5, 0.5));
qfa.set_initial_amplitude(1, std::complex<double>(0.5, -0.5));
qfa.set_initial_amplitude(2, std::complex<double>(0.0, 0.0));
// Set transition matrices for each input symbol
qfa.set_transition_matrix('a', {{{1.0, 0.0, 0.0},
{0.0, 0.5, 0.5},
{0.0, 0.5, -0.5}}});
qfa.set_transition_matrix('b', {{{0.5, 0.5, 0.0},
{0.5, -0.5, 0.0},
{0.0, 0.0, 1.0}}});
// Apply the transition based on an input string
std::string input_string = "ab";
QuantumState final_state = qfa.apply_transition(input_string);
// Print the final quantum state after the transition
final_state.print();
return 0;
}
Implement a method to calculate the acceptance probability of a QFA for a given input string using the projection matrix
Define a probability threshold
Allow users to calculate the probability of the initial state being an accepted state with:
This is an excerpt from https://en.wikipedia.org/wiki/Probability_amplitude , it nicely explains the meaning of probability amplitudes using the polarization of light as a real life example.
Take the simplest meaningful example of the discrete case: a quantum system that can be in two possible states: for example, the light polarization of a photon. When the polarization is measured, it could be the horizontal state
The probability amplitudes of
Therefore, for example, a photon in a state
We should probably include a little bit about this https://en.wikipedia.org/wiki/Semiautomaton
Something about De Rham curves and quantum finite state machines, it's gonna be harder than we thought
The De Rham curve can be used as an example of a non-simple matrix in the context of a quantum finite state machine (QFSM) because it involves non-trivial quantum interference between two or more paths.
In a QFSM, the state of the system is described by a quantum state, which can be represented by a vector in a Hilbert space. The evolution of this state is described by a unitary matrix, which maps the initial state to the final state. In a classical deterministic finite state machine, the evolution is described by a simple transition matrix.
The De Rham curve can be thought of as a geometric object that defines a non-trivial unitary matrix for a QFSM. In particular, the De Rham curve is a continuous path in a two-dimensional space, and the quantum interference between different paths along this curve can be used to define a non-simple unitary matrix for the QFSM.
This non-simple unitary matrix can then result in more subtle behavior for the QFSM, such as superposition and entanglement, which are not possible in classical deterministic finite state machines.
In summary, the De Rham curve is an example of a non-simple unitary matrix for a quantum finite state machine, which can result in more subtle and non-classical behavior.
https://link.springer.com/article/10.1007/BF00122683 Bloom, S.L., Sabadini, N. & Walters, R.F.C. Matrices, machines and behaviors. Appl Categor Struct 4, 343–360 (1996). https://doi.org/10.1007/BF00122683
In this section, we consider the question of how to model a machine with
One possible definition of a machine from
consists of a finite set of states
subject to the following restrictions.
- The sets
${b_1,..., b_n}$ and${e_1,..., e_p}$ are disjoint. - For each exit state
$e_i$ , and each$x \in X_1$ ,$\delta(e_i, x) = 0$ . - For each begin
$b_i,x \in X_1$ ,$b_i \notin \delta(q,x)$ , for any$q \subseteq Q$