File: quantum_ml_workshop/20260814/lab_02/qmllab/AAREADME.txt
Tool: The NEDC QML Workshop, qmllab Support Package
Version: 1.0.0

-------------------------------------------------------------------------------
Change Log:

20260813 (AM): initial version

-------------------------------------------------------------------------------
SUMMARY

qmllab is the small Python package used by Lab 02. It holds the plumbing so
that the notebook cells stay short and show only the idea being taught.

Nothing here is hidden or magic. The entire quantum kernel, for example, is
about five lines of numpy in kernels.py. You are encouraged to open these
files and read them; they are part of the lab, not a black box behind it.

The package contains six modules:

  data.py         loading, generating and scaling datasets
  kernels.py      the quantum similarity measures
  models.py       the classifiers for both paths
  backends.py     where circuits run: simulator, noisy simulator, hardware
  plotting.py     the figures
  experiments.py  whole experiments in one call

A. WHAT'S NEW

Version 1.0.0:
  + initial release

B. INSTALLATION REQUIREMENTS

None beyond Lab 02 itself. See the AAREADME.txt in the parent directory.

The package is imported by path, not installed, so it works as soon as your
working directory is lab_02:

  from qmllab import data, kernels, models, plotting, experiments, backends

C. USER'S GUIDE

C.1. THE MODULES

  data.py

    read_imld(path)                reads an IMLD csv into (X, y)
    write_imld(path, X, y)         writes data back out in the same format
    generate(name, n_samples)      builds one of seven 2-D datasets
    prepare(name, scaler, ...)     loads, splits and scales in one call
    range_width(X)                 the number that predicts kernel accuracy

    The scaler is not a detail. A ZZ feature map encodes a product of
    features, so the width of the scaled range controls how fast the kernel
    oscillates. This is the central result of Segment 2.

  kernels.py

    make_feature_map(kind, ...)    builds the encoding circuit
    exact_kernel(X1, X2)           the kernel by linear algebra, no sampling
    fidelity_kernel(X1, ...)       the kernel from measured shots
    hardware_kernel(X1, ...)       the kernel measured on a real processor
    kernel_stats(K)                summarizes a kernel matrix

    All four compute k(x,y) = |<phi(x)|phi(y)>|^2. Only the ruler changes.

  models.py

    classical_svm(...)             an ordinary sklearn SVM, the baseline
    qsvm(...)                      Path A: a quantum kernel plus an SVM
    qsvm_from_kernels(...)         fits on kernel matrices you already have
    reuploading_circuit(...)       a data re-uploading circuit
    vqc_reuploading(...)           Path B, done well
    vqc_naive(...)                 Path B, done the obvious way

  backends.py

    get_backend(kind)              "ideal", "noisy" or "hardware"
    discover_crn(token)            finds your IBM Quantum instance CRN
    get_service(token_path, crn)   connects to IBM Quantum
    list_hardware(service)         lists processors and queue depths
    qpu_cost(n_train, n_test)      estimates a job's cost before you spend it

  plotting.py

    plot_dataset(X, y)             scatters a dataset
    plot_kernel_matrix(K)          draws a kernel as a heatmap
    plot_decision_boundary(...)    draws a model's decision regions
    plot_margin_field(...)         draws the signed decision function
    plot_boundary_comparison(...)  several boundaries side by side
    plot_scaler_study(results)     accuracy against encoded range width
    plot_convergence(history)      a variational circuit's loss curve

  experiments.py

    run(config)                    one method on one dataset
    compare(config)                classical against quantum, with a verdict
    sweep(param, values)           one parameter varied over a list
    scaler_study(config)           every scaler, ordered by range width
    load_hardware_results(name)    reads a cached hardware run

C.2. A SHORT EXAMPLE

  from qmllab import data, kernels, models

  X_tr, X_te, y_tr, y_te, _ = data.prepare("two_moons", scaler="minmax")
  K = kernels.exact_kernel(X_tr)
  res = models.qsvm(X_tr, y_tr, X_te, y_te)
  print(res["test_acc"])

C.3. NOTES

  (1) Every experiment routine accepts an output directory. When one is
      given, the run writes a json record, a readable summary, and a
      decision boundary figure, so results can be reviewed later.

  (2) Decision boundaries are always rendered on the simulator. On real
      hardware a single boundary picture would cost hours of processor
      time, which is explained in Segment 4 of the notebook.

  (3) Sampling is seeded so that results reproduce. Set seed=None in the
      kernel routines if you want to see the run-to-run spread instead.

-------------------------------------------------------------------------------
If you have any additional comments or questions about this package, please
direct them to help@nedcdata.org. We will do our best to answer them.

Best regards,

Joe Picone
Sadia Afrin Purba
Abdullah Al Mamun

Copyright (c) 2026 Dr. Joseph Picone and the Neural Engineering Data
Consortium (NEDC), Temple University. All rights reserved.
