Before diving into the fascinating realm of quantum logic, mastering the fundamentals of classical logic and traditional logic gates is essential.
Logic gates are the foundational building blocks of digital electronics and modern computing. They manipulate binary signals—units of information represented by bits that take one of two distinct values: “0” (false, low, off) or “1” (true, high, on).
Logical Gates
Basic logic gates are the elementary building blocks of any digital system. These gates are: NOT, AND, OR, NAND, NOR, XOR, and XNOR. Each gate exhibits a specific behavior, formally defined by a truth table that maps its inputs to its output.
The NOT Gate (Inverter)
The NOT gate is the simplest of all logic gates. It takes a single input and returns its inverse.
Symbol :
Code
# 1. Initialize the drawing contextwith schemdraw.Drawing() as d:# Set global configuration for clean technical typography d.config(fontsize=14, unit=2.5)# 2. Add an input lead line on the left, labeled 'A' input_line = d.add(elm.Line().right(1.5).label('A', loc='left'))# 3. Add the NOT gate (inverter with bubble) connected to the input# The output label 'Y' can be written with LaTeX notation: $\overline{A}$ not_gate = d.add( logic.Not() .right() .at(input_line.end) )# 4. Add an output lead line extending to the right d.add( elm.Line() .right(1.5) .at(not_gate.out) .label('$B$', loc='right') )
Truth Table: NOT Gate
Input (\(A\))
Output (\(B\))
0
1
1
0
The output is the inverse of the input.
Throughout this blog, we will express all circuits in matrix form. So, we might as well get comfortable with this concept right from the start.
You can think of a matrix as a “box” that embodies a function.
They all share the exact same format:
- The rows correspond to an enumeration of all possible input combinations.
- The columns correspond to an enumeration of all possible output combinations.
If a function has \(M\) binary inputs and \(N\) binary outputs, the resulting matrix will have \(2^M\) rows and \(2^N\) columns.
The column containing the value 1 marks the precise spot where a given input maps to its corresponding output. This is known as a transition matrix in mathematics.
Here is the matrix representing the NOT gate. Labels representing the inputs on the left and the outputs on the top have been added for increased readability :
Rather than using standard matrix brackets, transition matrices are intentionally rendered as closed grid boxes. This visually reinforces their role as discrete computational components mapping input configurations to output states.
(Yes, this is a feature, not a bug.)
Even the logical states follow the same format. You can think of a logical state as a function with zero input and one output (the logical state).
The output is 1 only if both inputs \(A\) and \(B\) are 1.
Symbol :
Code
# 1. Initialize the drawing contextwith schemdraw.Drawing() as d:# Set global configuration for crisp, technical diagrams d.config(fontsize=14, unit=2.5)# 2. Add the 2-input AND gate and_gate = d.add(logic.And().right())# 3. Add input lead lines on the left, labeled 'A' and 'B' d.add(elm.Line().left(1.5).at(and_gate.in1).label('A', loc='left')) d.add(elm.Line().left(1.5).at(and_gate.in2).label('B', loc='left'))# 4. Add the output lead line on the right d.add(elm.Line().right(1.5).at(and_gate.out).label('C', loc='right'))
The output is 1 if at least one of the inputs is 1.
Symbol :
Code
# 1. Initialize the drawing contextwith schemdraw.Drawing() as d:# Set global configuration for crisp, technical diagrams d.config(fontsize=14, unit=2.5)# 2. Add the 2-input OR gate and_gate = d.add(logic.Or().right())# 3. Add input lead lines on the left, labeled 'A' and 'B' d.add(elm.Line().left(1.5).at(and_gate.in1).label('A', loc='left')) d.add(elm.Line().left(1.5).at(and_gate.in2).label('B', loc='left'))# 4. Add the output lead line on the right, labeled 'C' d.add(elm.Line().right(1.5).at(and_gate.out).label('C', loc='right'))
# 1. Initialize the drawing contextwith schemdraw.Drawing() as d:# Set global configuration for crisp, technical diagrams d.config(fontsize=14, unit=2.5)# 2. Add the 2-input NAND gate and_gate = d.add(logic.Nand().right())# 3. Add input lead lines on the left, labeled 'A' and 'B' d.add(elm.Line().left(1.5).at(and_gate.in1).label('A', loc='left')) d.add(elm.Line().left(1.5).at(and_gate.in2).label('B', loc='left'))# 4. Add the output lead line on the right d.add(elm.Line().right(1.5).at(and_gate.out).label('C', loc='right'))
# 1. Initialize the drawing contextwith schemdraw.Drawing() as d:# Set global configuration for crisp, technical diagrams d.config(fontsize=14, unit=2.5)# 2. Add the 2-input NOR gate and_gate = d.add(logic.Nor().right())# 3. Add input lead lines on the left, labeled 'A' and 'B' d.add(elm.Line().left(1.5).at(and_gate.in1).label('A', loc='left')) d.add(elm.Line().left(1.5).at(and_gate.in2).label('B', loc='left'))# 4. Add the output lead line on the right d.add(elm.Line().right(1.5).at(and_gate.out).label('C', loc='right'))
The output is 1 if the inputs are different, and 0 if they are identical.
Symbol :
Code
# 1. Initialize the drawing contextwith schemdraw.Drawing() as d:# Set global configuration for crisp, technical diagrams d.config(fontsize=14, unit=2.5)# 2. Add the 2-input XOR gate and_gate = d.add(logic.Xor().right())# 3. Add input lead lines on the left, labeled 'A' and 'B' d.add(elm.Line().left(1.5).at(and_gate.in1).label('A', loc='left')) d.add(elm.Line().left(1.5).at(and_gate.in2).label('B', loc='left'))# 4. Add the output lead line on the right d.add(elm.Line().right(1.5).at(and_gate.out).label('C', loc='right'))
The inverse of XOR. The output is 1 only if the inputs are identical.
Symbol :
Code
# 1. Initialize the drawing contextwith schemdraw.Drawing() as d:# Set global configuration for crisp, technical diagrams d.config(fontsize=14, unit=2.5)# 2. Add the 2-input XNOR gate and_gate = d.add(logic.Xnor().right())# 3. Add input lead lines on the left, labeled 'A' and 'B' d.add(elm.Line().left(1.5).at(and_gate.in1).label('A', loc='left')) d.add(elm.Line().left(1.5).at(and_gate.in2).label('B', loc='left'))# 4. Add the output lead line on the right d.add(elm.Line().right(1.5).at(and_gate.out).label('C', loc='right'))
For logic gates with two inputs, \(A\) and \(B\), one might naively expect something like \(A \cdot B \cdot \text{AND}\). However, that will not work dimensionally. \(A\) and \(B\) are \(1 \times 2\) matrices, whereas the \(\text{AND}\) gate is a \(4 \times 2\) matrix.
To give the inputs, \(A\) and \(B\), the proper dimension to interface with the AND gate, they must first be combined using the Kronecker tensor product (\(A \otimes B\)).
This operation takes two matrices of arbitrary sizes and constructs a larger composite matrix. It is the fundamental mathematical tool used to describe the joint state of independent systems.
The Formal Rule
If matrix \(A\) has dimensions \(m \times n\) and matrix \(B\) has dimensions \(p \times q\), their Kronecker product \(A \otimes B\) is a block matrix of size \((m \cdot p) \times (n \cdot q)\) obtained by multiplying every single element of \(A\) by the entire matrix \(B\):
\[
A \otimes B = \begin{pmatrix}
a_{11} B & a_{12} B & \cdots & a_{1n} B \\
a_{21} B & a_{22} B & \cdots & a_{2n} B \\
\vdots & \vdots & \ddots & \vdots \\
a_{m1} B & a_{m2} B & \cdots & a_{mn} B
\end{pmatrix}
\]
A Concrete Example with Input Bits (Row Vectors)
In our framework, single-bit inputs are represented as \(1 \times 2\) matrices.
To find the composite matrix for the input pair \((A = 1, B = 0)\), we compute \(\text{One} \otimes \text{Zero}\):
The resulting \(1 \times 4\) matrix cleanly indexes the fourth basis state (corresponding to binary "10"), making it dimensionally compatible with any 2-input gate matrix.
Let’s look at an enumeration of all 4 possibilities for A and B with labels included:
NAND and NOR gates are known as universal gates because they can be used to construct every other logic gate on their own. This means that, given enough NAND or NOR gates, any arbitrary logic circuit can be realized.
The following is an XOR gate constructed using only NOR gates :
These elementary gates serve as the building blocks for much more complex digital architectures — such as the Arithmetic Logic Unit (ALU), which lies at the very heart of modern microprocessors: