Higher order versions of basic gates Q# - quantum-computing

Is there a higher order H-gate in Q# language? For example, if I want to apply Hadamard gate to an array(combined state) of 3 qubits. Is there a way to generate a tensor product version of H-gate or other gates?

One way to think of it is to think of the unitary operator H = |+⟩⟨0| + |−⟩⟨1| and the quantum operation H separately.
Taking this view, the unitary H is how we simulate the effect of applying the operation H on an ideal quantum processor.
The quantum operation ApplyToEach(H, _) is then represented by the unitary operator H ⊗ H ⊗ ⋯ ⊗ H in precisely the same way that H is represented by H.
One consequence of this mental model is that the tensor product is defined between unitary operators and not between quantum operations. Rather, the ideal action of quantum operations acting on distinct qubits is represented by the tensor product of the unitary representations of each individual operation.

Q# does not allow you to pass more qubits than the basic gate allows. So you have to run each of the qubits through the H() gate manually like this
let n = Length(qs);
for(index in 0 .. (n-1)) {
H(qs[index]);
}
Or use the convenient standard library function
ForEach(H,qs);
The basic reason why you can't apply a higher order H gate is it will increase the function signature to more qubits which creates complication. Also you may want to pass only some of the qubits of the same array to the gate, in that case you can't pass the entire array either and have to do it manually.

Related

is there a C function for regex using a deterministic automaton?

The POSIX regex functions compile the regular expressions into non-deterministic finite automata (NFAs). One problem with that is there is no way to tell at compilation time whether those automata will use excessive stack space or take excessive cpu time. That makes them (in some sense) unsuitable for use in a real time system.
An equivalent deterministic finite automaton executes in linear time. It disadvantage is that it may use an excessive number of states, which translates to a large amount of program memory. On the plus side, though, is the fact that you know the number of states used at the time you compile the regular expression.
That means you can know at regular expression compile time whether it is suitable for your application. That brings me to my question: Is there a regular expression library for C that compiles to a DFA? The answer to a question that might be as useful would answer the question: Is there a regular expression library for C that gives useful information on memory and cpu utilization?
Ken
Yes. 2. It's a matter of simple algebra. 3. Here
https://github.com/RockBrentwood/RegEx
(originally in the comp.compilers archive.)
Here an early description on comp.compilers, from which this ultimately descended.
https://compilers.iecc.com/comparch/article/93-05-083
and another later description
https://compilers.iecc.com/comparch/article/93-10-022
The older version of the RegEx C programs on GitHub may be found in the AI repository at Carnegie Mellon University here
https://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/areas/nlp/parsing/regex
I will try to retcon the 1993-2021 evolution-stream of it into the current GitHub snapshot so that you can have the whole history, rather than just the snapshot of the latest versions. (It would be nice if GitHub supported retconning and retrofitting history-streams, by the way.)
An automaton is little more than the graphic display of a finite right linear system of inequations. Every rational expression is the least fixed point solution to such a system, which can be unfolded from the expression purely by algebraic means.
This is a general result of Kleene algebra, so it goes well beyond just regular expressions; e.g. rational subsets of any monoid; a special case being rational subsets of product monoids, which includes rational transductions as a special case. And the algebraic method used in the C routines is mostly (but not entirely) generic to Kleene algebras.
I'm trying to adapt the calculation in {nfa,dfa}.c to handle both inputs and outputs. There are a few places where it makes specific assumption that the Kleene algebra is the free Kleene algebra ( = regular expression algebra). And that has to be modified, to allow it to be generalized to non-free Kleene algebras, like the rational transductions.
Regular expressions over an alphabet $X$ comprise the Kleene algebra $ℜX^*$ of the rational subsets of the free monoid $X^*$ generated by $X$. Correspondingly, $ℜX^*$ is the free Kleene algebra generated by $X$.
The underlying theory (with respect to which "free" refers to) can be 1st-order or 2nd order.
The 1st-order theory (notwithstanding Conway's "no finite axiomatization" result, mis-stated and mis-applied as a folklore theorem) is a finitely axiomatized algebra consisting of (a) the axioms for a semiring, with an idempotent sum $x + x = x$ (usually denoted $x | x$) ... i.e. a "dioid", and (b) the corresponding partial ordering relation defined by ($x ≥ y ⇔ (∃z) x = z + y ⇔ x = x + y$); (c) the Kleene star operator $x ↦ x^*$, which (d) provides least fixed point solutions $b^* a c^* = μx (x ≥ a + bx + xc)$. (A set of axioms to embody (d) are $x^* = 1 + x x^*$ and $x ≥ a + bx + xc ⇒ x ≥ b^* a c^*$.) That dates from the mid 1990's by Kozen.
The algebra presented by the 1st order theory is not closed under congruence relations (because, in fact, all computations can be represented by a Kleene algebra taken over a suitably defined non-trivial monoid; so the word problem isn't solvable either). The 2nd order formulation - which predates the 1st order formulation - is the closure of the 1st order formulation under congruence. It has (a) the axioms of a dioid and (b) the least fixed points of all rational subsets and (c) distributivity with respect to the rational least fixed point. The last two axioms can be narrowed and combined into a single axiom for the least fixed point: $μ_{n≥0}(ab^nc) = ab^*c$.
Using the terminology in LNCS 4988 (https://link.springer.com/chapter/10.1007%2F978-3-540-78913-0_14), this comprises the category of "rational dioids" = rationally closed idempotent semirings. It has a tensor product ⊗, which was part of the suite of additional infrastructure and expanded terminology laid out in LNCS11194 (pp. 21-36, 37-52) https://dblp.org/db/conf/RelMiCS/ramics2018.html.
The software requires and uses only the 1st order formulation.
Rational transductions over an input alphabet $X$ and output alphabet $Y$, similarly, comprise the rational subsets $ℜ(X^* × Y^*)$ of the product monoid $X^* × Y^*$; and in the rational-dioid category, the rational transduction algebra is the tensor product $ℜ(X^* × Y^*) = ℜX^* ⊗ ℜY^*$ of the respective regular expression algebras.
In turn, that algebra is effectively just the algebra of regular expressions over the disjoint union of $X$ and $Y$ modulo the commutativity rule $xy = yx$ for $x ∈ X, y ∈ Y$, so the process can be adapted and generalized adapted to:
(a) "transducers" - where both X and Y are present,
(b) "generators", where only $Y$ is present and $X = {1}$,
(c) "recognizers", where only $X$ is present and $Y = {1}$ and even
(d) generalizations of these where multiple input and/or output channels are allowed.
Example: the Kleene algebra $ℜX_0^* ⊗ ℜX_1^* ⊗ ℜY_0^* ⊗ ℜY_1^*$ would be for transducers with two input channels (one with alphabet $X_0$ the other with alphabet $X_1$) and two output channels (with respective alphabets $Y_0$ and $Y_1$).

How to make a gate which generates |0> or |1> based on a parameter?

I would like to make a single-qubit gate which gives |0> or |1> with reference to a parameter.
For example, I set a parameter theta in range of 0 to 2π. When theta is in range of 0 to π, the gate returns |0> and when theta is in range of π to 2π, the gate returns |1>.
I am in the environment as follows:
Qiskit: 0.12.0
Python 3.7.3 .
Quantum gates don't "return" a state, they transform a qubit state into another one. A singe-qubit quantum gate is represented as a 2x2 unitary matrix, and the way it transforms the qubit state is represented as matrix multiplication of this matrix and a vector of length 2 which represents the input state. So the closest to the thing you're trying to do is a gate which transforms an arbitrary input state to |0⟩ or to |1⟩ depending on the value of the parameter.
Quantum gates also have to be reversible, i.e. you need to be able to undo the transformation. The transformation you described makes it impossible, since multiple inputs are mapped to the same output, and you can not recover the input state from the result.
Non-reversible transformations are done not using gates but using measurements. If you need to collapse the input qubit to |0⟩ or |1⟩ depending on a parameter, you can measure it, and depending on the measurement result and the state you need, apply an X gate to the qubit. I.e., if the qubit was measured in the |0⟩ state and you need a |1⟩ (or vice versa), apply X gate, otherwise don't apply it.

Difference of using different population size and different crossover method

I have couple of general questions on genetic algorithm. In selection step where you pick up chromosomes from the population, is there an ideal number of chromosomes to be picked up? What difference does it make if I pick, say 10 chromosomes instead of 20? Does it have any effect on final result? At mutation stage, I've learnt there are different ways to mutate - Single point crossover, two points crossover, uniform crossover and arithmetic crossover. When should I choose one over the other? I know they sound very basic, but I couldn't find answer anywhere. So I thought I should ask in Stackoverflow.
Thanks
It seems to me that your terminology and concepts are a little bit messed up. Let me clarify.
First of all - there are many ways people call the members of the population: genotype, genome, chromosome, individual, solution... I will use solution for now as it is, in my opinion, the most general term, it is what we are eventually evolve, and also I'm not a biologist so I don't know whether genotype, genome and chromosome somehow differ and if they do what is the difference...
Population
Genetic Algorithms are population-based evolutionary algorithms. The algorithms have (usually) a fixed-sized population of solutions of the problem it is solving.
Genetic operators
There are two principal genetic operators - crossover and mutation. The goal of crossover is to take two (or more in some cases) solutions and combine them to create a solution that has some properties of both, optimally the best of both. The goal of mutation is to create new genetic material that was not previously present in the population by doing a small random change.
The choice of the particular operators, i.e. whether a single-point or multi-point crossover..., is totally problem-dependent. For example, if your solutions are composed of some logical blocks of bits that work together in each block, it might not be a good idea to use uniform crossover because it will destroy these blocks. In such case a single- or multi-point crossover is a better choice and the best choice is probably to restrict the crossover points to be on the boundaries of the blocks only.
You have to try what works best for your problem. Also, you can always use all of them, i.e. by randomly choosing which crossover operator is going to be used each time the crossover is about to be performed. Similarly for mutation.
Modes of operation
Now to your first question about the number of selected solutions. Genetic Algorithms can run in two basic modes - generational mode and steady-state mode.
Generational mode
In generational mode, the whole population is replaced in every generation (iteration) of the algorithm. A simple python-like pseudo-code for a generational-mode GA could look like this:
P = [...] # initial population
while not stopping_condition():
Pc = [] # empty population of children
while len(Pc) < len(P):
a = select(P) # select a solution from P using some selection strategy
b = select(P)
if rand() < crossover_probability:
a, b = crossover(a, b)
if rand() < mutation_probability:
a - mutation(a)
if rand() < mutation_probability:
b = mutation(b)
Pc.append(a)
Pc.append(b)
P = Pc # replace the population with the population of children
Evaluation of the solutions was omitted.
Steady-state mode
In steady-state mode, the population persists and only a few solutions are replaced in each iteration. Again, a simple steady-state GA could look like this:
P = [...] # initial population
while not stopping_condition():
a = select(P) # select a solution from P using some selection strategy
b = select(P)
if rand() < crossover_probability:
a, b = crossover(a, b)
if rand() < mutation_probability:
a - mutation(a)
if rand() < mutation_probability:
b = mutation(b)
replace(P, a) # put a child back into P based on some replacement strategy
replace(P, b)
Evaluation of the solutions was omitted.
So, the number of selected solutions depends on how do you want your algorithm to operate.

How do I implement a set of qubits on my computer?

I would like to get familiar with quantum computing basics.
A good way to get familiar with it would be writing very basic virtual quantum computer machines.
From what I can understand of it, the, effort of implementing a single qubit cannot simply be duplicated to implement a two qubit system. But I don't know how I would implement a single qubit either.
How do I implement a qubit?
How do I implement a set of qubits?
Example Code
If you want to start from something simple but working, you can play around with this basic quantum circuit simulator on jsfiddle (about ~2k lines, but most of that is UI stuff [drawing and clicking] and maths stuff [defining complex numbers and matrices]).
State
The state of a quantum computer is a set of complex weights, called amplitudes. There's one amplitude for each possible classical state. In the case of qubits, the classical states are just the various states a normal bit can be in.
For example, if you have three bits, then you need a complex weight for the 000, 001, 010, 011, 100, 101, 110, and 111 states.
var threeQubitState = new Complex[8];
The amplitudes must satisfy a constraint: if you add up their squared magnitudes, the result is 1. Classical states correspond to one amplitude having magnitude 1 while the others are all 0:
threeQubitState[3] = 1; // the system is 100% in the 011 state
Operations
Operations on quantum states let you redistribute the amplitude by flowing it between the classical states, but the flows you choose must preserve the squared-magnitudes-add-up-to-1 property in all cases. More technically, the operation must correspond to some unitary matrix.
var myOperation = state => new[] {
(state[1] + state[0])/sqrt(2),
(state[1] - state[0])/sqrt(2),
state[2],
state[3],
state[4],
state[5],
state[6],
state[7]
};
var myNewState = myOperation(threeQubitState);
... and those are the basics. The state is a list of complex numbers with unit 2-norm, the operations are unitary matrices, and the probability of measuring a state is just its squared amplitude.
Etc
Other things you probably need to consider:
What kinds of operations do you want to include?
A 1-qubit operation is a 2x2 matrix and a 3-qubit operation is an 8x8 matrix. How do you convert a 1-qubit operation into an 8x8 matrix when applying it to a single qubit in a 3-qubit state? (Use the Kronecker Product.)
What kinds of tricks can you use to speed up the simulation? For example, if only a few states are non-zero, or if the qubits are not entangled, there's no need to do a full matrix multiplication.
How does the user tell the simulation what to do? How can you represent what's going on for the user? There's an awful lot of numbers flowing around...
I don't actually know the answer, but an interesting place to start reading about qubits is this article. It doesn't describe in detail how entangled qubits work, but it hints at the complexity involved:
If this is how complicated things can get with only two qubits, how
complicated will it get for 3 or 4, or 100? It turns out that the
state of an N-qubit quantum computer can only be completely defined
when plotted as a point in a space with (4^N-1) dimensions. That means
we need 4^N good old fashion classical numbers to simulate it.
Note that this is the maximum space complexity, which for example is about 1 billion numbers (2^30=4^15) for 15 qubits. It says nothing about the time complexity of a simulation.
The article that #Qwertie cites is a very good introduction. If you want to implement these on your computer, you can play with the libquantum simulator, which implements sophisticated quantum operations in a C library. You can look at this example to see what using the code is like.
The information is actually stored in the interaction between different Qbits, so no implementing 1 Qbit will not translate to using multiple. I'd think another way you could play around is to use existing languages like QCL or google QCP http://qcplayground.withgoogle.com/#/home to play around

Fast way to in-place update one vector with another

I have a vector A, represented by an angle and a length. I want to add vector B, updating the original A. B comes from a lookup table, so it can be represented in which ever way makes the computation easier.
Specifically, A is defined thusly:
uint16_t A_angle; // 0-65535 = 0-2π
int16_t A_length;
Approximations are fine. Checking for overflow is not necessary. A fast sin/cos approximation is available.
The fastest way I can think is to have B represented as a component vector, convert A to component, add A and B, convert the result back to angle/length and replace A. (This requires the addition of a fast asin/acos)
I am not especially good at math and wonder if I am missing a more sensible approach?
I am primarily looking for a general approach, but specific answers/comments about useful micro-optimizations in C is also interesting.
If you need to do a lot of additive operations, it would probably be worth considering storing everything in Cartesian coordinates, rather than polar.
Polar is well-suited to rotation operations (and scaling, I guess), but sticking with Cartesian (where a rotation is four multiplies, see below) is probably going to be cheaper than using cos/sin/acos/asin every time you want to do a vector addition. Although, of course, it depends on the distribution of operations in your case.
FYI, a rotation in Cartesian coordinates is as follows (see http://en.wikipedia.org/wiki/Rotation_matrix):
x' = x.cos(a) - y.sin(a)
y' = x.sin(a) + y.cos(a)
If a is known ahead of time, then cos(a) and sin(a) can be precomputed.

Resources