Skip to content

Commit 8a98a92

Browse files
authored
Overhaul Q50 model (#28)
* Update documentation * Update documentation * Update resource estimator defaults for values and remove depth from q50 entry * Update cli tool * Add method to train simple linear model, improve docstrings * Add Helmi model type, add new analytical model for Q50 * Update and add new tests * Update changelog * Update actual vs predicted plot * Update documentation * Update creation of plots * Clean up codebase and move logic to new modules
1 parent 76fc97d commit 8a98a92

15 files changed

+1477
-161
lines changed

CHANGELOG.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22
Changelog
33
=========
44

5-
Version 0.3.1
5+
Version 0.4.0
66
==========================
77

8-
* Add device-specific qubit limits
9-
* Display maximum qubit count hint in the UI for each device
8+
* Overhauled VTT Q50 model to use an analytical model without a depth parameters
9+
* Not using depth avoids numerical instability and unphysical behavior while maintaining high accuracy
10+
* Updated UI to remove depth input and reflect new model structure
11+
* Modify the CLI build process to allow both Helmi (polynomial model) and Q50 (analytical model) approaches
12+
* Update the documentation.
1013

1114
Version 0.3.0
1215
============
109 KB
Loading

public/documentation.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
Data is gathered by submitting quantum circuits with varying values for shots, depth, number of circuits in a batch and number of qubits. You can view the data gathered [here](https://github.com/FiQCI/resource-estimator/tree/main/data_analysis/data). QPU seconds is calculated from timestamps returned via IQM Client as explained [here](https://docs.meetiqm.com/iqm-client/integration_guide.html#job-phases-and-related-timestamps). QPU seconds is calculated as `execution_end` - `execution_start`.
55

6-
The data is analyzed using **polynomial ridge regression models** implemented with scikit-learn's [`Ridge`](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html) and [`PolynomialFeatures`](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html). A separate model is created for each quantum computer:
7-
- **Helmi**: Degree-2 polynomial
8-
- **VTT Q50**: Degree-3 polynomial with **log-transform**
6+
The data is analyzed using different modeling approaches depending on the quantum computer:
7+
- **Helmi**: Polynomial ridge regression model (degree-2) implemented with scikit-learn's [`Ridge`](https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.Ridge.html) and [`PolynomialFeatures`](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.PolynomialFeatures.html)
8+
- **VTT Q50**: Analytical model.
99

1010
## Helmi
1111

@@ -21,15 +21,19 @@ Where $kshots = shots/1000$ and $B$ is number of circuits in a batch.
2121

2222
## VTT Q50
2323

24-
The model for VTT Q50 uses a **degree-3 polynomial regression with log-transform**. The equation (showing only the most significant terms) is:
24+
The model for VTT Q50 uses an **analytical model** that tries to capture the scaling of parameters:
2525

26-
$$\log(QPU + 0.001) = -0.531 + 0.364 \times B + 0.221 \times kshots + 0.030 \times qubits - 0.022 \times B^2 + ...$$
26+
$$T = T_{init} + \eta(B) \times B \times shots \times \alpha$$
2727

28-
$$QPU = \exp(\text{result}) - 0.001$$
28+
Where:
29+
- $T_{init} = ~0.88$ seconds (baseline overhead)
30+
- $\eta(B) = ~0.986^{\min(B, 19)}$ (batching efficiency factor)
31+
- $\alpha = ~0.000625$ (throughput coefficient)
32+
- $B$ = number of circuits in a batch
2933

30-
Where only the most significant terms are included. This shows that VTT Q50 is strongly dependent on batches and shots. VTT Q50 has a baseline initialization time of approximately **1.2 seconds**.
34+
Note that the circuit depth does not affect runtime by a noticeable amount. The number of qubits has a minimal impact.
3135

32-
Where $kshots = shots/1000$ and $B$ is number of circuits in a batch.
36+
The initialization overhead ($T_{init}$) is approximately **1.1-1.2 seconds**.
3337

3438
![image](./actual_vs_predicted-vtt-q50.png)
3539

@@ -43,6 +47,10 @@ The model does not work well for circuits with a high depth (`>1000`) count, how
4347

4448
Both VTT Q50 and Helmi have a constant initialization time associated with any quantum job submitted to them. For a batch of circuits, the constant initialization time applies to the whole batch (list of circuits). However, submitting many smaller batches of quantum circuits does apply this time. This is mostly due to the initialization of the control electronics needed before job submission.
4549

50+
- **Why does VTT Q50's model not include circuit depth or qubit count?**
51+
52+
The circuit depth and number of qubits has minimal impact on QPU execution time. The runtime is largely dominated by the number of circuit executions (shots × batches) and qubit count. Removing depth from the VTT Q50 model simplifies the estimation model.
53+
4654
- **Is the initialization time needed every time a parameter is updated in the quantum circuit?**
4755

4856
When running variational algorithms you often perform parameter updates outside of the quantum job. Therefore, for each parameter update the constant initialization time is added to the total runtime.

src/components/ResourceEstimator.jsx

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { DEVICE_PARAMS, calculateQPUSeconds } from '../utils/ResourceEstimatorMo
77

88
const fontFamily = '-apple-system,BlinkMacSystemFont,"Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Arial,sans-serif';
99

10-
const ParameterInput = ({ label, value, onChange, hint, error }) => {
10+
const ParameterInput = ({ label, value, onChange, hint, error, disabled = false }) => {
1111
const inputContainerStyle = {
1212
flex: '1 0 45%',
1313
marginBottom: '0.75rem',
@@ -20,7 +20,7 @@ const ParameterInput = ({ label, value, onChange, hint, error }) => {
2020
display: 'block',
2121
fontSize: '1.1rem',
2222
fontWeight: '500',
23-
color: '#374151',
23+
color: disabled ? '#9CA3AF' : '#374151',
2424
marginBottom: '0.35rem',
2525
fontFamily: fontFamily
2626
};
@@ -46,13 +46,14 @@ const ParameterInput = ({ label, value, onChange, hint, error }) => {
4646
display: 'block',
4747
width: '100%',
4848
padding: '0.5rem 0.7rem',
49-
backgroundColor: 'white',
49+
backgroundColor: disabled ? '#F3F4F6' : 'white',
5050
border: error ? '2px solid #DC2626' : '1px solid #D1D5DB',
5151
borderRadius: '0.35rem',
5252
boxSizing: 'border-box',
53-
color: '#000',
53+
color: disabled ? '#9CA3AF' : '#000',
5454
fontFamily: fontFamily,
5555
fontSize: '1.1rem',
56+
cursor: disabled ? 'not-allowed' : 'text',
5657
// Hide up/down arrows for number inputs
5758
WebkitAppearance: 'none',
5859
MozAppearance: 'textfield'
@@ -81,6 +82,7 @@ const ParameterInput = ({ label, value, onChange, hint, error }) => {
8182
onChange={handleInputChange}
8283
style={inputStyle}
8384
placeholder="Enter value"
85+
disabled={disabled}
8486
/>
8587
{error ? <span style={errorStyle}>{error}</span> : hint && <span style={hintStyle}>{hint}</span>}
8688
</div>
@@ -91,9 +93,9 @@ const ResourceEstimator = () => {
9193
const [selectedDevice, setSelectedDevice] = useState('helmi');
9294
const [formData, setFormData] = useState({
9395
batches: 1,
94-
depth: 10,
9596
shots: 1000,
96-
qubits: 5
97+
qubits: 5,
98+
depth: 1
9799
});
98100

99101
const [estimatedQPU, setEstimatedQPU] = useState(null);
@@ -154,7 +156,10 @@ const ResourceEstimator = () => {
154156

155157
const calculateQPU = () => {
156158
// Validate all fields first
157-
const requiredFields = ['batches', 'depth', 'shots', 'qubits'];
159+
const requiredFields = ['batches', 'shots', 'qubits'];
160+
if (selectedDevice === 'helmi') {
161+
requiredFields.push('depth');
162+
}
158163
requiredFields.forEach(field => validateField(field, formData[field]));
159164

160165
// Check if there are any validation errors
@@ -168,11 +173,15 @@ const ResourceEstimator = () => {
168173
// Convert any string values to numbers
169174
const numericFormData = {
170175
batches: parseInt(formData.batches, 10),
171-
depth: parseInt(formData.depth, 10),
172176
shots: parseInt(formData.shots, 10),
173177
qubits: parseInt(formData.qubits, 10)
174178
}
175179

180+
// Add depth for Helmi
181+
if (selectedDevice === 'helmi') {
182+
numericFormData.depth = parseInt(formData.depth, 10);
183+
}
184+
176185
// Calculate QPU seconds using our model
177186
const qpuSeconds = calculateQPUSeconds(selectedDevice, numericFormData);
178187
setEstimatedQPU(qpuSeconds);
@@ -313,27 +322,32 @@ const ResourceEstimator = () => {
313322
label="Circuits in Batch"
314323
value={formData.batches}
315324
onChange={(value) => handleInputChange('batches', value)}
316-
/>
317-
318-
<ParameterInput
319-
label="Circuit Depth (Gates)"
320-
value={formData.depth}
321-
onChange={(value) => handleInputChange('depth', value)}
325+
error={validationErrors.batches}
322326
/>
323327

324328
<ParameterInput
325329
label="Shots per Circuit"
326330
value={formData.shots}
327331
onChange={(value) => handleInputChange('shots', value)}
332+
error={validationErrors.shots}
328333
/>
329334

330335
<ParameterInput
331336
label="Number of Qubits"
332337
value={formData.qubits}
333-
onChange={(value) => handleInputChange('qubits', value)}
334-
hint={`Max: ${DEVICE_PARAMS[selectedDevice].max_qubits} qubits`}
335-
error={validationErrors.qubits}
336-
/>
338+
onChange={(value) => handleInputChange('qubits', value)}
339+
hint={`Max: ${DEVICE_PARAMS[selectedDevice].max_qubits} qubits`}
340+
error={validationErrors.qubits}
341+
/>
342+
343+
<ParameterInput
344+
label="Circuit Depth"
345+
value={formData.depth}
346+
onChange={(value) => handleInputChange('depth', value)}
347+
hint={selectedDevice === 'helmi' ? 'Number of layers in circuit' : 'Not used for VTT Q50'}
348+
error={validationErrors.depth}
349+
disabled={selectedDevice === 'vtt-q50'}
350+
/>
337351
</div>
338352

339353
<div style={{marginTop: '1rem', textAlign: 'center'}}>

0 commit comments

Comments
 (0)