Learned Joint ISAC OFDM Allocation#
Goal#
Train a portable power-allocation policy for one controlled frequency-selective OFDM protocol. Each record exposes per-subcarrier communication gain, sensing gain, noise level, and the declared sensing weight. The policy must return a non-negative unit-sum power vector.
The paired comparison contains equal power, communication-only water filling, a per-scene projected-gradient reference for the declared scalarized objective, and the returned learned policy. Channel gains, noise, tradeoff weight, power budget, and random seeds remain fixed within each paired unit.
CLI training summary#
Run this complete block from the repository:
(
set -euo pipefail
ROOT="$(git rev-parse --show-toplevel)"
BUNDLE="$ROOT/.noema/training_exports/isac_joint_allocation"
cd "$ROOT"
uv sync --extra onnx
uv run --project "$ROOT" --extra onnx noema differentiable export \
"$ROOT/recipes/isac_ofdm_joint_allocation.yaml" \
--training-plan "$ROOT/demo_trainings/isac_joint_allocation_deepsets/training_plan.yaml" \
--out "$BUNDLE" --force
uv run --project "$ROOT" --extra onnx python \
"$ROOT/demo_trainings/prepare_example.py" isac-joint-allocation "$BUNDLE" \
--project-root "$ROOT"
uv run --project "$ROOT" --extra onnx noema dataset-capture run \
"$BUNDLE/capture_train_recipe.yaml" --out "$BUNDLE/data/train" --force
uv run --project "$ROOT" --extra onnx noema dataset-capture run \
"$BUNDLE/capture_validation_recipe.yaml" --out "$BUNDLE/data/validation" --force
uv run --project "$ROOT" --extra onnx noema dataset-capture run \
"$BUNDLE/capture_test_recipe.yaml" --out "$BUNDLE/data/test" --force
cd "$BUNDLE"
uv run --project "$ROOT" --extra onnx python validate_contract.py
uv run --project "$ROOT" --extra onnx python train_demo.py
uv run --project "$ROOT" --extra onnx python evaluate_demo.py
cd "$BUNDLE/reference_training"
uv run --project "$ROOT" --extra onnx python build_benchmark.py
cd "$ROOT"
uv run --project "$ROOT" --extra onnx noema benchmark validate \
"$BUNDLE/reference_training/benchmark_pack.yaml"
uv run --project "$ROOT" --extra onnx noema benchmark run \
"$BUNDLE/reference_training/benchmark_pack.yaml"
)
1. Export and capture#
Select Train/replace for Allocator and retain isac_features from data.problem. No oracle
allocation labels are captured. The default plan collects 4,096 disjoint records over 0–20 dB.
2. Train and return the policy#
The starter uses a permutation-equivariant subcarrier scorer followed by softmax. Its power vector therefore satisfies the budget exactly. It trains directly against negative scalarized utility; validation utility selects the checkpoint and the test split remains sealed until evaluation.
The returned package contains artifacts/isac_allocator.onnx, trained_artifact.yaml, training
history, and held-out evaluation metrics.
3. Compare the allocation rules#
The generated campaign sweeps held-out SNRs and three fresh paired seeds. Read
isac.scalarized_utility together with communication rate and sensing SNR: the scalarized number is
meaningful only for the fixed weight declared by this contract.
Completed benchmark result#
The completed paired campaign contains 24 runs: four allocation rules, two held-out SNRs, and three fresh seeds. Points are means over the three seeds; bands are two-sided Student-t 95% confidence intervals.
Note
Three paired seeds make this a compact workflow result, not a publication-strength population claim.
The learned allocator has a higher mean than equal power and communication-only water filling at both tested SNRs and closely follows the per-scene projected-gradient reference. At 0 dB it is 0.02% above that finite-iteration reference; this tiny reversal is solver tolerance, not evidence that it exceeds the declared objective’s exact optimum.
SNR (dB) |
Method |
Role |
Mean Scalarized utility |
Mean Communication rate (bit/s/Hz) |
Mean Sensing SNR (dB) |
Primary 95% CI low |
Primary 95% CI high |
|---|---|---|---|---|---|---|---|
0 |
Equal power |
baseline |
0.370962720699 |
1.72054911719 |
-1.91404594238 |
0.361228145057 |
0.380697296341 |
0 |
Communication-only water filling |
baseline |
0.420181814876 |
2.72343483532 |
-1.86159400383 |
0.384913482969 |
0.455450146783 |
0 |
Per-scene scalarized optimization |
oracle |
0.511857119725 |
2.0689499996 |
0.175404343761 |
0.495151275195 |
0.528562964254 |
0 |
Learned joint allocator |
candidate |
0.511960092847 |
1.94913554621 |
0.265650654692 |
0.495730671341 |
0.528189514353 |
15 |
Equal power |
baseline |
2.85946475599 |
22.0769177571 |
13.0859542915 |
2.80416371701 |
2.91476579497 |
15 |
Communication-only water filling |
baseline |
2.90348074782 |
23.0316700932 |
13.0697946455 |
2.86375032339 |
2.94321117225 |
15 |
Per-scene scalarized optimization |
oracle |
2.98997398776 |
21.8217467616 |
14.2183107003 |
2.94960329728 |
3.03034467825 |
15 |
Learned joint allocator |
candidate |
2.98313806252 |
21.8994270016 |
14.1464084673 |
2.94248953125 |
3.02378659379 |
Download the run-level projection, chart data, or provenance manifest.
This is a synthetic resource-allocation demonstration. It has no waveform-level target detector, range/Doppler ambiguity function, clutter model, multi-user interference, or standards-conformance claim.