Correspondence Matrices · practice and reference
Beginner setup and worked CM lab
Start here before the programming lessons if you have not used Python. You need the full CM_Computation repository checkout, because the lab imports its CM modules. The HTML and videos alone do not include those modules. Allow time to read, run and change the example; pause the videos as needed.
The lab works through the rules already shown in Lessons 20 and 23. The independent checkpoints use a different rule; attempt those before opening their separate answer keys.
1. Open PowerShell at the repository root
Open the folder containing cm_build.py and cm_exprlib.py. Open a PowerShell terminal there. Replace the path below with your repository checkout:
Set-Location 'C:\path\to\CM_Computation'
Test-Path .\cm_build.py
Test-Path .\cm_exprlib.py
Both checks should print True. Substitute your checkout's folder in the first command if it is elsewhere.
2. Choose the Python environment
If this checkout already has a working virtual environment, use its interpreter directly. A virtual environment keeps this project's installed libraries together. No activation command is required:
.\.venv\Scripts\python.exe --version
.\.venv\Scripts\python.exe -B -c "import numpy; print(numpy.__version__)"
The first command should report Python 3.10 or newer; the second should print a NumPy version. This lab was verified with this checkout's Python 3.13 and NumPy 2.3.2. If either command is unavailable, follow the separate-environment route below.
Create a separate environment if you need one
Install Python 3.10 or newer with its Windows launcher first, if Python is not installed. Save the dependency list linked below as requirements.txt in the repository root. Then run:
py -3 --version
py -3 -m venv .venv-cm-course
.\.venv-cm-course\Scripts\python.exe -m pip install -r requirements.txt
This creates a separate folder and installs NumPy, the lab's one external dependency. The installation needs internet access. If .venv-cm-course already exists, check its interpreter and NumPy first. In the run commands below, use .venv-cm-course in place of .venv when you chose this route.
3. Run the worked lab
Open the complete Python source · Minimal dependency list. Save both downloaded files in the repository root, then run:
.\.venv\Scripts\python.exe -B -X utf8 worked_lab.py
-B suppresses Python bytecode files; -X utf8 selects UTF-8 text output. The lab uses the local CM modules and prints its results. It needs no service account or API key.
You should see:
Rule matrix (AB rows / CD columns, false-first):
[0, 1, 1, 1]
[0, 1, 1, 1]
[0, 1, 1, 1]
[1, 0, 0, 0]
1100 -> row 3, column 0 -> 1
Packed output: 7918; accepted cases: 10/16
Policy matrix (AO rows / DS columns, false-first):
[0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 1, 0]
[1, 0, 1, 0]
Policy allowed: 3/16
PASS: 48 rule + 48 policy = 96 scalar lookup checks
Direct, reused-compiled and current lazy-wrapper arrays agree in all three layouts.
4. Read the small amount of Python used here
| Construct | Meaning in this lab |
|---|---|
from cm_exprlib import Var, And, Or, Xor, Not | Import names supplied by the repository. Not is required for Lesson 23's suspension condition. |
range(4) and [Var(i) for i in range(4)] | Visit indices 0, 1, 2, 3 and build a list of four expression inputs. Assigning that list to A, B, C, D gives each input a readable name. |
["x0", "x1"] | An ordered list. It declares A then B as the row bits. The quoted names are text strings; the order determines each bit's place. |
{"x0": 1, "x1": 1, "x2": 0, "x3": 0} | A dictionary pairs each input name with its bit. {} means an empty dictionary: the example fixes no inputs. |
for values in product((0, 1), repeat=4): | A loop visits all 16 four-bit assignments, from 0000 through 1111. Indented lines run once for each assignment. |
dict(zip(names, values)) | Pair each name with the corresponding bit, then make the assignment dictionary. All four inputs are included. |
def rule_oracle(...): and return | Define a reusable function. Its indented return line computes a scalar answer directly from bits. |
assert actual == expected | == compares values. If they differ, Python stops with an assertion error. A single = assigns a value to a name. |
In expression construction, use Xor(And(A, B), Or(C, D)) to record (A∧B)⇕(C∨D). Here A–D are expression objects. In the independent oracle, (a_bit & b_bit) ^ (c_bit | d_bit) operates on actual 0/1 integers. Python's ^ is the bitwise exclusive-or operator. Ordinary Python and, or and not are suitable for the scalar policy oracle; they do not build CM expression objects.
5. Connect the output to the lessons
Var(0) corresponds to x0, and similarly through Var(3)/x3. The first layout uses AB rows and CD columns, both in false-first order 00, 01, 10, 11. Assignment 1100 selects row 3 and column 0, whose value is 1. The scalar rule independently computes (1∧1)⇕(0∨0)=1.
The lab checks three layouts for each of two rules: 3 × 16 = 48 comparisons per rule, 96 in total. It also checks that materializing a reusable compiled node and using the current lazy-named wrapper give the same arrays as direct construction. The current lazy wrapper still returns a dense array.
The packed integer 7918 contains the 16 outputs of the first rule, with truth-row k stored at bit k; ten bits are 1. The second rule uses A for authentication, O for owner, D for administrator and S for suspension: A∧(O∨D)∧¬S. It allows three input cases. These are small correctness examples; they do not measure execution speed.
Troubleshooting
- Python command not found: use the interpreter path for the environment you created and confirm it exists.
- No module named numpy: install the supplied minimal requirements with that same environment's
python.exe -m pip. - No module named cm_build: run the downloaded script from the CM_Computation repository root, which must contain
cm_build.py. The script needs the repository modules as well as NumPy. - AssertionError: keep the full error, assignment and layout. Compare your changes with the supplied source before proceeding; a printed partial result is not a pass.
After reproducing the worked result, explain why changing the row/column split changes the address while preserving the output. Then attempt the independent executable checkpoint before opening its answers.

