Requirements¶
Requirements are first-class objects in phased-array-systems, enabling systematic tracking of design compliance with automatic verification and margin calculation.
Overview¶
The requirements system provides:
- Definition: Specify requirements with thresholds and operators
- Verification: Automatic pass/fail checking against metrics
- Margins: Quantify how much margin exists (positive or negative)
- Traceability: Link results back to requirement IDs
Defining Requirements¶
Single Requirement¶
from phased_array_systems.requirements import Requirement
req = Requirement(
id="REQ-001", # Unique identifier
name="Minimum EIRP", # Human-readable name
metric_key="eirp_dbw", # Key in metrics dictionary
op=">=", # Comparison operator
value=40.0, # Threshold value
units="dBW", # Optional units (documentation)
severity="must", # Importance level
)
Parameters¶
| Parameter | Type | Required | Description |
|---|---|---|---|
id |
str | Yes | Unique identifier (e.g., "REQ-001") |
name |
str | Yes | Human-readable description |
metric_key |
str | Yes | Key to check in metrics dict |
op |
str | Yes | Comparison operator |
value |
float | Yes | Threshold value |
units |
str | No | Units for documentation |
severity |
str | No | "must", "should", or "nice" |
Operators¶
| Operator | Meaning | Passes When |
|---|---|---|
>= |
Greater or equal | metric >= value |
<= |
Less or equal | metric <= value |
> |
Greater than | metric > value |
< |
Less than | metric < value |
== |
Equal to | metric == value |
Severity Levels¶
| Level | Meaning | Verification Impact |
|---|---|---|
"must" |
Mandatory | Fails overall if not met |
"should" |
Desired | Tracked but doesn't fail |
"nice" |
Optional | Tracked but doesn't fail |
RequirementSet¶
Group requirements together for verification:
from phased_array_systems.requirements import RequirementSet
requirements = RequirementSet(
requirements=[
Requirement("REQ-001", "Min EIRP", "eirp_dbw", ">=", 40.0, severity="must"),
Requirement("REQ-002", "Positive Margin", "link_margin_db", ">=", 0.0, severity="must"),
Requirement("REQ-003", "Max Cost", "cost_usd", "<=", 50000.0, severity="must"),
Requirement("REQ-004", "Target EIRP", "eirp_dbw", ">=", 45.0, severity="should"),
],
name="Communications Requirements",
)
Verification¶
Basic Verification¶
from phased_array_systems.evaluate import evaluate_case
# Evaluate design
metrics = evaluate_case(arch, scenario)
# Verify requirements
report = requirements.verify(metrics)
# Check overall status
print(f"Overall: {'PASS' if report.passes else 'FAIL'}")
VerificationReport¶
The verify() method returns a VerificationReport:
report = requirements.verify(metrics)
# Summary counts
print(f"Must: {report.must_pass_count}/{report.must_total_count}")
print(f"Should: {report.should_pass_count}/{report.should_total_count}")
# Failed requirement IDs
if report.failed_ids:
print(f"Failed: {report.failed_ids}")
# Individual results
for result in report.results:
status = "PASS" if result.passes else "FAIL"
print(f"{result.requirement.id}: {status}")
print(f" Actual: {result.actual_value:.2f}")
print(f" Threshold: {result.requirement.value:.2f}")
print(f" Margin: {result.margin:.2f}")
Margin Calculation¶
Margins indicate how much room exists:
- Positive margin: Requirement is satisfied with room to spare
- Zero margin: Exactly at threshold
- Negative margin: Requirement is not met
For different operators:
| Operator | Margin Formula |
|---|---|
>=, > |
actual - threshold |
<=, < |
threshold - actual |
== |
-abs(actual - threshold) |
# Example: EIRP >= 40 dBW with actual = 45 dBW
# Margin = 45 - 40 = 5 dB (passes with 5 dB margin)
# Example: Cost <= 50000 with actual = 45000
# Margin = 50000 - 45000 = 5000 (passes with $5k margin)
Integration with Batch Evaluation¶
Requirements integrate with the trade study workflow:
from phased_array_systems.trades import BatchRunner, filter_feasible
# Create runner with requirements
runner = BatchRunner(scenario, requirements)
# Run batch - results include verification columns
results = runner.run(doe)
# Results DataFrame includes:
# - verification.passes (1.0 or 0.0)
# - verification.must_pass_count
# - verification.must_total_count
# - verification.margin_* for each requirement
# Filter to feasible only
feasible = filter_feasible(results, requirements)
Verification Columns¶
After batch evaluation, the results DataFrame includes:
| Column | Description |
|---|---|
verification.passes |
1.0 if all must requirements pass |
verification.must_pass_count |
Number of must requirements passed |
verification.must_total_count |
Total must requirements |
verification.should_pass_count |
Should requirements passed |
verification.should_total_count |
Total should requirements |
Common Requirement Patterns¶
Communications Link¶
comms_requirements = RequirementSet(requirements=[
# Performance
Requirement("LINK-001", "Min EIRP", "eirp_dbw", ">=", 40.0, severity="must"),
Requirement("LINK-002", "Positive Margin", "link_margin_db", ">=", 0.0, severity="must"),
Requirement("LINK-003", "3dB Margin", "link_margin_db", ">=", 3.0, severity="should"),
# SWaP-C
Requirement("SWAP-001", "Max Cost", "cost_usd", "<=", 100000.0, severity="must"),
Requirement("SWAP-002", "Max Power", "prime_power_w", "<=", 1000.0, severity="must"),
# Antenna
Requirement("ANT-001", "Min Gain", "g_peak_db", ">=", 25.0, severity="should"),
])
Radar Detection¶
radar_requirements = RequirementSet(requirements=[
# Detection
Requirement("DET-001", "Positive SNR Margin", "snr_margin_db", ">=", 0.0, severity="must"),
Requirement("DET-002", "5dB SNR Margin", "snr_margin_db", ">=", 5.0, severity="should"),
# Range
Requirement("RNG-001", "Min Range", "detection_range_m", ">=", 100e3, severity="must"),
# SWaP-C
Requirement("SWAP-001", "Max Cost", "cost_usd", "<=", 500000.0, severity="must"),
])
YAML Configuration¶
Requirements can be defined in YAML:
requirements:
- id: REQ-001
name: Minimum EIRP
metric_key: eirp_dbw
op: ">="
value: 40.0
units: dBW
severity: must
- id: REQ-002
name: Positive Link Margin
metric_key: link_margin_db
op: ">="
value: 0.0
units: dB
severity: must
- id: REQ-003
name: Maximum Cost
metric_key: cost_usd
op: "<="
value: 50000.0
units: USD
severity: must
Load with:
from phased_array_systems.io import load_config
config = load_config("config.yaml")
requirements = config.get_requirement_set()
Serialization¶
To Dictionary¶
report = requirements.verify(metrics)
report_dict = report.to_dict()
# Contains:
# {
# "passes": True,
# "failed_ids": [],
# "must_pass_count": 3,
# "must_total_count": 3,
# "results": [
# {
# "id": "REQ-001",
# "name": "Minimum EIRP",
# "metric_key": "eirp_dbw",
# "threshold": 40.0,
# "operator": ">=",
# "actual_value": 45.0,
# "passes": True,
# "margin": 5.0,
# "severity": "must",
# },
# ...
# ]
# }
Export to Report¶
The report generators include requirement verification:
from phased_array_systems.reports import HTMLReport, ReportConfig
report_gen = HTMLReport(ReportConfig(title="Trade Study"))
html = report_gen.generate(results)
# Includes requirement pass/fail summary and margins
Best Practices¶
1. Use Meaningful IDs¶
Organize IDs by category:
Requirement("PERF-001", ...) # Performance
Requirement("SWAP-001", ...) # Size, Weight, Power, Cost
Requirement("ANT-001", ...) # Antenna
Requirement("LINK-001", ...) # Link budget
2. Define Both Minimum and Target¶
RequirementSet(requirements=[
Requirement("EIRP-MIN", "Min EIRP", "eirp_dbw", ">=", 40.0, severity="must"),
Requirement("EIRP-TGT", "Target EIRP", "eirp_dbw", ">=", 45.0, severity="should"),
])
3. Include Units for Documentation¶
4. Use Severity Appropriately¶
"must": Hard constraints that must be met"should": Important goals but not showstoppers"nice": Stretch goals for optimization
See Also¶
- Architecture Configuration - Define system parameters
- Trade Studies - Batch evaluation with requirements
- API Reference - Complete API documentation