qsharp-lang 1.0.32-dev → 1.0.34-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/katas-content.generated.js +17 -17
- package/dist/log.js +2 -3
- package/dist/ux/ticks.d.ts +6 -0
- package/dist/ux/ticks.js +125 -0
- package/lib/node/qsc_wasm.cjs +85 -92
- package/lib/node/qsc_wasm.d.cts +1 -1
- package/lib/node/qsc_wasm_bg.wasm +0 -0
- package/lib/web/qsc_wasm.d.ts +1 -1
- package/lib/web/qsc_wasm.js +80 -90
- package/lib/web/qsc_wasm_bg.wasm +0 -0
- package/package.json +1 -1
- package/ux/colormap.ts +51 -0
- package/ux/data.ts +68 -0
- package/ux/estimatesOverview.tsx +238 -0
- package/ux/generate_report_code.py +243 -0
- package/ux/index.ts +4 -2
- package/ux/output_data.md +537 -0
- package/ux/qsharp-ux.css +37 -0
- package/ux/reTable.tsx +7 -28
- package/ux/report.ts +591 -0
- package/ux/resultsTable.tsx +35 -49
- package/ux/scatterChart.tsx +369 -0
- package/ux/spaceChart.tsx +2 -2
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
// A component including the results table and the scatter chart together.
|
|
5
|
+
// The results table is also a legend for the scatter chart.
|
|
6
|
+
|
|
7
|
+
import { useState } from "preact/hooks";
|
|
8
|
+
import { ColorMap } from "./colormap.js";
|
|
9
|
+
import {
|
|
10
|
+
CreateSingleEstimateResult,
|
|
11
|
+
FrontierEntry,
|
|
12
|
+
ReData,
|
|
13
|
+
SingleEstimateResult,
|
|
14
|
+
} from "./data.js";
|
|
15
|
+
import { ResultsTable, Row } from "./resultsTable.js";
|
|
16
|
+
import {
|
|
17
|
+
Axis,
|
|
18
|
+
HideTooltip,
|
|
19
|
+
PlotItem,
|
|
20
|
+
ScatterChart,
|
|
21
|
+
ScatterSeries,
|
|
22
|
+
SelectPoint,
|
|
23
|
+
} from "./scatterChart.js";
|
|
24
|
+
|
|
25
|
+
const columnNames = [
|
|
26
|
+
"Run name",
|
|
27
|
+
"Estimate type",
|
|
28
|
+
"Qubit type",
|
|
29
|
+
"QEC scheme",
|
|
30
|
+
"Error budget",
|
|
31
|
+
"Logical qubits",
|
|
32
|
+
"Logical depth",
|
|
33
|
+
"Code distance",
|
|
34
|
+
"T states",
|
|
35
|
+
"T factories",
|
|
36
|
+
"T factory fraction",
|
|
37
|
+
"Runtime",
|
|
38
|
+
"rQOPS",
|
|
39
|
+
"Physical qubits",
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const initialColumns = [0, 1, 2, 3, 4, 10, 11, 12];
|
|
43
|
+
|
|
44
|
+
const xAxis: Axis = {
|
|
45
|
+
isTime: true,
|
|
46
|
+
label: "Runtime",
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const yAxis: Axis = {
|
|
50
|
+
isTime: false,
|
|
51
|
+
label: "Physical qubits",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function reDataToRow(input: ReData, color: string): Row {
|
|
55
|
+
const data = CreateSingleEstimateResult(input, 0);
|
|
56
|
+
const estimateType =
|
|
57
|
+
input.frontierEntries == null
|
|
58
|
+
? "Single"
|
|
59
|
+
: "Frontier (" + input.frontierEntries.length + " items)";
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
cells: [
|
|
63
|
+
data.jobParams.runName,
|
|
64
|
+
estimateType,
|
|
65
|
+
data.jobParams.qubitParams.name,
|
|
66
|
+
data.jobParams.qecScheme.name,
|
|
67
|
+
data.jobParams.errorBudget,
|
|
68
|
+
data.physicalCounts.breakdown.algorithmicLogicalQubits,
|
|
69
|
+
data.physicalCounts.breakdown.algorithmicLogicalDepth,
|
|
70
|
+
data.logicalQubit.codeDistance,
|
|
71
|
+
data.physicalCounts.breakdown.numTstates,
|
|
72
|
+
data.physicalCounts.breakdown.numTfactories,
|
|
73
|
+
data.physicalCountsFormatted.physicalQubitsForTfactoriesPercentage,
|
|
74
|
+
{
|
|
75
|
+
value: data.physicalCountsFormatted.runtime,
|
|
76
|
+
sortBy: data.physicalCounts.runtime,
|
|
77
|
+
},
|
|
78
|
+
data.physicalCounts.rqops,
|
|
79
|
+
data.physicalCounts.physicalQubits,
|
|
80
|
+
data.new ? "New" : "Cached",
|
|
81
|
+
],
|
|
82
|
+
color: color,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function frontierEntryToPlotEntry(entry: FrontierEntry): PlotItem {
|
|
87
|
+
return {
|
|
88
|
+
x: entry.physicalCounts.runtime,
|
|
89
|
+
y: entry.physicalCounts.physicalQubits,
|
|
90
|
+
label:
|
|
91
|
+
entry.physicalCountsFormatted.runtime +
|
|
92
|
+
" " +
|
|
93
|
+
entry.physicalCountsFormatted.physicalQubits,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function reDataToRowScatter(data: ReData, color: string): ScatterSeries {
|
|
98
|
+
if (data.frontierEntries == null || data.frontierEntries.length === 0) {
|
|
99
|
+
return {
|
|
100
|
+
color: color,
|
|
101
|
+
items: [
|
|
102
|
+
{
|
|
103
|
+
x: data.physicalCounts.runtime,
|
|
104
|
+
y: data.physicalCounts.physicalQubits,
|
|
105
|
+
label:
|
|
106
|
+
data.physicalCountsFormatted.runtime +
|
|
107
|
+
" " +
|
|
108
|
+
data.physicalCountsFormatted.physicalQubits,
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
color: color,
|
|
116
|
+
items: data.frontierEntries.map(frontierEntryToPlotEntry),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function EstimatesOverview(props: {
|
|
121
|
+
estimatesData: ReData[];
|
|
122
|
+
colors: string[] | null;
|
|
123
|
+
runNames: string[] | null;
|
|
124
|
+
isSimplifiedView: boolean;
|
|
125
|
+
onRowDeleted: (rowId: string) => void;
|
|
126
|
+
setEstimate: (estimate: SingleEstimateResult | null) => void;
|
|
127
|
+
}) {
|
|
128
|
+
const [selectedRow, setSelectedRow] = useState<string | null>(null);
|
|
129
|
+
|
|
130
|
+
props.estimatesData.forEach((item, idx) => {
|
|
131
|
+
if (
|
|
132
|
+
props.runNames != null &&
|
|
133
|
+
props.runNames.length == props.estimatesData.length
|
|
134
|
+
) {
|
|
135
|
+
item.jobParams.runName = props.runNames[idx];
|
|
136
|
+
} else {
|
|
137
|
+
if (item.jobParams.runName == null) {
|
|
138
|
+
// Start indexing with 0 to match with the original object indexing.
|
|
139
|
+
item.jobParams.runName = `(${idx})`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
function onPointSelected(seriesIndex: number, pointIndex: number): void {
|
|
145
|
+
const data = props.estimatesData[seriesIndex];
|
|
146
|
+
props.setEstimate(CreateSingleEstimateResult(data, pointIndex));
|
|
147
|
+
const rowId = props.estimatesData[seriesIndex].jobParams.runName;
|
|
148
|
+
setSelectedRow(rowId);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function onRowSelected(rowId: string) {
|
|
152
|
+
setSelectedRow(rowId);
|
|
153
|
+
// On any selection, clear the "new" flag on all rows. This ensures that
|
|
154
|
+
// new rows do not steal focus from the user selected row.
|
|
155
|
+
props.estimatesData.forEach((data) => (data.new = false));
|
|
156
|
+
HideTooltip();
|
|
157
|
+
if (!rowId) {
|
|
158
|
+
props.setEstimate(null);
|
|
159
|
+
} else {
|
|
160
|
+
const index = props.estimatesData.findIndex(
|
|
161
|
+
(data) => data.jobParams.runName === rowId,
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
if (index == -1) {
|
|
165
|
+
props.setEstimate(null);
|
|
166
|
+
} else {
|
|
167
|
+
const estimateFound = props.estimatesData[index];
|
|
168
|
+
props.setEstimate(CreateSingleEstimateResult(estimateFound, 0));
|
|
169
|
+
SelectPoint(index, 0);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const colormap =
|
|
175
|
+
props.colors != null && props.colors.length == props.estimatesData.length
|
|
176
|
+
? props.colors
|
|
177
|
+
: ColorMap(props.estimatesData.length);
|
|
178
|
+
|
|
179
|
+
if (props.isSimplifiedView) {
|
|
180
|
+
return (
|
|
181
|
+
<>
|
|
182
|
+
<ResultsTable
|
|
183
|
+
columnNames={columnNames}
|
|
184
|
+
rows={props.estimatesData.map((dataItem, index) =>
|
|
185
|
+
reDataToRow(dataItem, colormap[index]),
|
|
186
|
+
)}
|
|
187
|
+
initialColumns={initialColumns}
|
|
188
|
+
ensureSelected={true}
|
|
189
|
+
onRowDeleted={props.onRowDeleted}
|
|
190
|
+
selectedRow={selectedRow}
|
|
191
|
+
setSelectedRow={onRowSelected}
|
|
192
|
+
/>
|
|
193
|
+
<ScatterChart
|
|
194
|
+
xAxis={xAxis}
|
|
195
|
+
yAxis={yAxis}
|
|
196
|
+
data={props.estimatesData.map((dataItem, index) =>
|
|
197
|
+
reDataToRowScatter(dataItem, colormap[index]),
|
|
198
|
+
)}
|
|
199
|
+
onPointSelected={onPointSelected}
|
|
200
|
+
/>
|
|
201
|
+
</>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return (
|
|
206
|
+
<>
|
|
207
|
+
<details open>
|
|
208
|
+
<summary style="font-size: 1.5em; font-weight: bold; margin: 24px 8px;">
|
|
209
|
+
Results
|
|
210
|
+
</summary>
|
|
211
|
+
<ResultsTable
|
|
212
|
+
columnNames={columnNames}
|
|
213
|
+
rows={props.estimatesData.map((dataItem, index) =>
|
|
214
|
+
reDataToRow(dataItem, colormap[index]),
|
|
215
|
+
)}
|
|
216
|
+
initialColumns={initialColumns}
|
|
217
|
+
selectedRow={selectedRow}
|
|
218
|
+
setSelectedRow={onRowSelected}
|
|
219
|
+
ensureSelected={true}
|
|
220
|
+
onRowDeleted={props.onRowDeleted}
|
|
221
|
+
/>
|
|
222
|
+
</details>
|
|
223
|
+
<details open>
|
|
224
|
+
<summary style="font-size: 1.5em; font-weight: bold; margin: 24px 8px;">
|
|
225
|
+
Qubit-time diagram
|
|
226
|
+
</summary>
|
|
227
|
+
<ScatterChart
|
|
228
|
+
xAxis={xAxis}
|
|
229
|
+
yAxis={yAxis}
|
|
230
|
+
data={props.estimatesData.map((dataItem, index) =>
|
|
231
|
+
reDataToRowScatter(dataItem, colormap[index]),
|
|
232
|
+
)}
|
|
233
|
+
onPointSelected={onPointSelected}
|
|
234
|
+
/>
|
|
235
|
+
</details>
|
|
236
|
+
</>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
# Copyright (c) Microsoft Corporation.
|
|
2
|
+
# Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
# This script generates the code for the report page from the output_data.md file.
|
|
5
|
+
# To run, simply execute `python generate_report_code.py` in the npm/ux folder.
|
|
6
|
+
# copy the output and paste it into the report.tsx file.
|
|
7
|
+
# It provides a code for the CreateReport function.
|
|
8
|
+
|
|
9
|
+
import re
|
|
10
|
+
|
|
11
|
+
parse = False
|
|
12
|
+
|
|
13
|
+
title = ""
|
|
14
|
+
always_visible = True
|
|
15
|
+
first_entry = True
|
|
16
|
+
entries = []
|
|
17
|
+
|
|
18
|
+
label = ""
|
|
19
|
+
path = ""
|
|
20
|
+
value = ""
|
|
21
|
+
description = ""
|
|
22
|
+
explanation = ""
|
|
23
|
+
|
|
24
|
+
assumptions = []
|
|
25
|
+
|
|
26
|
+
ignore_paths = [
|
|
27
|
+
"floquet_code",
|
|
28
|
+
"surface_code",
|
|
29
|
+
"qubit_gate_ns_e3",
|
|
30
|
+
"qubit_gate_ns_e4",
|
|
31
|
+
"qubit_gate_us_e3",
|
|
32
|
+
"qubit_gate_us_e4",
|
|
33
|
+
"qubit_maj_ns_e4",
|
|
34
|
+
"qubit_maj_ns_e6",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
path_map = {
|
|
38
|
+
"errorBudget/rotations": "result.errorBudget.rotations",
|
|
39
|
+
"jobParams/qecScheme/crossingPrefactor": "result.jobParams.qecScheme.crossingPrefactor",
|
|
40
|
+
"jobParams/qecScheme/errorCorrectionThreshold": "result.jobParams.qecScheme.errorCorrectionThreshold",
|
|
41
|
+
"jobParams/qecScheme/logicalCycleTime": "result.jobParams.qecScheme.logicalCycleTime",
|
|
42
|
+
"jobParams/qecScheme/physicalQubitsPerLogicalQubit": "result.jobParams.qecScheme.physicalQubitsPerLogicalQubit",
|
|
43
|
+
"jobParams/qubitParams/tGateErrorRate": "result.jobParams.qubitParams.tGateErrorRate",
|
|
44
|
+
"logicalCounts/ccixCount": "numberFormat.format(result.logicalCounts.ccixCount)",
|
|
45
|
+
"logicalCounts/cczCount": "numberFormat.format(result.logicalCounts.cczCount)",
|
|
46
|
+
"logicalCounts/measurementCount": "numberFormat.format(result.logicalCounts.measurementCount)",
|
|
47
|
+
"logicalCounts/numQubits": "numberFormat.format(result.logicalCounts.numQubits)",
|
|
48
|
+
"logicalCounts/rotationCount": "numberFormat.format(result.logicalCounts.rotationCount)",
|
|
49
|
+
"logicalCounts/rotationDepth": "numberFormat.format(result.logicalCounts.rotationDepth)",
|
|
50
|
+
"logicalCounts/tCount": "numberFormat.format(result.logicalCounts.tCount)",
|
|
51
|
+
"logicalQubit/codeDistance": "result.logicalQubit.codeDistance",
|
|
52
|
+
"logicalQubit/logicalCyclesPerSecond": "numberFormatF64.format(result.physicalCounts.breakdown.clockFrequency)",
|
|
53
|
+
"logicalQubit/logicalCycleTime": "numberFormat.format(result.logicalQubit.logicalCycleTime)",
|
|
54
|
+
"logicalQubit/physicalQubits": "numberFormat.format(result.logicalQubit.physicalQubits)",
|
|
55
|
+
"physicalCounts/breakdown/algorithmicLogicalDepth": "numberFormat.format(result.physicalCountsFormatted.algorithmicLogicalDepth)",
|
|
56
|
+
"physicalCounts/breakdown/algorithmicLogicalQubits": "numberFormat.format(result.physicalCounts.breakdown.algorithmicLogicalQubits)",
|
|
57
|
+
"physicalCounts/breakdown/cliffordErrorRate": "result.physicalCounts.breakdown.cliffordErrorRate",
|
|
58
|
+
"physicalCounts/breakdown/logicalDepth": "numberFormat.format(result.physicalCounts.breakdown.logicalDepth)",
|
|
59
|
+
"physicalCounts/breakdown/physicalQubitsForAlgorithm": "numberFormat.format(result.physicalCounts.breakdown.physicalQubitsForAlgorithm)",
|
|
60
|
+
"physicalCounts/breakdown/physicalQubitsForTfactories": "numberFormat.format(result.physicalCounts.breakdown.physicalQubitsForTfactories)",
|
|
61
|
+
"physicalCounts/breakdown/numTfactories": "numberFormat.format(result.physicalCounts.breakdown.numTfactories)",
|
|
62
|
+
"physicalCounts/breakdown/numTfactoryRuns": "numberFormat.format(result.physicalCounts.breakdown.numTfactoryRuns)",
|
|
63
|
+
"physicalCounts/breakdown/numTstates": "numberFormat.format(result.physicalCounts.breakdown.numTstates)",
|
|
64
|
+
"physicalCounts/breakdown/requiredLogicalQubitErrorRate": "result.physicalCounts.breakdown.requiredLogicalQubitErrorRate",
|
|
65
|
+
"physicalCounts/physicalQubits": "numberFormat.format(result.physicalCounts.physicalQubits)",
|
|
66
|
+
"physicalCounts/runtime": "numberFormat.format(result.physicalCounts.runtime)",
|
|
67
|
+
"physicalCountsFormatted/clockFrequency": "result.physicalCountsFormatted.clockFrequency",
|
|
68
|
+
"physicalCountsFormatted/errorBudget": "result.physicalCountsFormatted.errorBudget",
|
|
69
|
+
"physicalCountsFormatted/errorBudgetLogical": "result.physicalCountsFormatted.errorBudgetLogical",
|
|
70
|
+
"physicalCountsFormatted/errorBudgetRotations": "result.physicalCountsFormatted.errorBudgetRotations",
|
|
71
|
+
"physicalCountsFormatted/errorBudgetTstates": "result.physicalCountsFormatted.errorBudgetTstates",
|
|
72
|
+
"physicalCountsFormatted/logicalCycleTime": "result.physicalCountsFormatted.logicalCycleTime",
|
|
73
|
+
"physicalCountsFormatted/numTsPerRotation": "result.physicalCountsFormatted.numTsPerRotation",
|
|
74
|
+
"physicalCountsFormatted/requiredLogicalQubitErrorRate": "result.physicalCountsFormatted.requiredLogicalQubitErrorRate",
|
|
75
|
+
"physicalCountsFormatted/requiredLogicalTstateErrorRate": "result.physicalCountsFormatted.requiredLogicalTstateErrorRate",
|
|
76
|
+
"physicalCountsFormatted/runtime": "result.physicalCountsFormatted.runtime",
|
|
77
|
+
"physicalCountsFormatted/tfactoryRuntime": "result.physicalCountsFormatted.tfactoryRuntime",
|
|
78
|
+
"physicalCountsFormatted/tstateLogicalErrorRate": "result.physicalCountsFormatted.tstateLogicalErrorRate",
|
|
79
|
+
"tfactory/physicalQubits": "numberFormat.format(result.tfactory == null ? 0 : result.tfactory.physicalQubits)",
|
|
80
|
+
"tfactory/numInputTstates": "numberFormat.format(result.tfactory == null ? 0 : result.tfactory.numInputTstates)",
|
|
81
|
+
"tfactory/numTstates": "numberFormat.format(result.tfactory == null ? 0 : result.tfactory.numTstates)",
|
|
82
|
+
"tfactory/runtime": "numberFormat.format(result.tfactory == null ? 0 : result.tfactory.runtime)",
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
print()
|
|
86
|
+
print()
|
|
87
|
+
print(
|
|
88
|
+
"// THIS CODE HAS BEEN AUTOMATICALLY GENERATED WITH generate_report_code.py from output_data.md"
|
|
89
|
+
)
|
|
90
|
+
print("export function CreateReport(result: ReData): ReportData {")
|
|
91
|
+
print(" const groups = [] as ReportGroup[];")
|
|
92
|
+
print(" let entries = [] as ReportEntry[];")
|
|
93
|
+
print(" const numberFormat = new Intl.NumberFormat();")
|
|
94
|
+
print(
|
|
95
|
+
" const numberFormatF64 = new Intl.NumberFormat(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2,});"
|
|
96
|
+
)
|
|
97
|
+
print()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def add_group():
|
|
101
|
+
global always_visible, entries, title
|
|
102
|
+
|
|
103
|
+
if len(entries) != 0:
|
|
104
|
+
if title == "T factory parameters":
|
|
105
|
+
print(" if (result.tfactory != null) {")
|
|
106
|
+
|
|
107
|
+
always_visible_str = "true" if always_visible else "false"
|
|
108
|
+
print(" entries = [];")
|
|
109
|
+
for path, label, description, explanation in entries:
|
|
110
|
+
if path in [
|
|
111
|
+
"jobParams/qubitParams/oneQubitGateTime",
|
|
112
|
+
"jobParams/qubitParams/twoQubitGateTime",
|
|
113
|
+
"jobParams/qubitParams/oneQubitGateErrorRate",
|
|
114
|
+
"jobParams/qubitParams/twoQubitGateErrorRate",
|
|
115
|
+
]:
|
|
116
|
+
print(
|
|
117
|
+
' if (result.jobParams.qubitParams.instructionSet == "GateBased") {'
|
|
118
|
+
)
|
|
119
|
+
print(
|
|
120
|
+
f' entries.push({{path: "{path}", label: "{label}", description: {description}, explanation: {explanation}}});'
|
|
121
|
+
)
|
|
122
|
+
print(" }")
|
|
123
|
+
elif path in [
|
|
124
|
+
"jobParams/qubitParams/twoQubitJointMeasurementTime",
|
|
125
|
+
"jobParams/qubitParams/twoQubitJointMeasurementErrorRate",
|
|
126
|
+
]:
|
|
127
|
+
print(
|
|
128
|
+
' if (result.jobParams.qubitParams.instructionSet == "Majorana") {'
|
|
129
|
+
)
|
|
130
|
+
print(
|
|
131
|
+
f' entries.push({{path: "{path}", label: "{label}", description: {description}, explanation: {explanation}}});'
|
|
132
|
+
)
|
|
133
|
+
print(" }")
|
|
134
|
+
else:
|
|
135
|
+
print(
|
|
136
|
+
f' entries.push({{path: "{path}", label: "{label}", description: {description}, explanation: {explanation}}});'
|
|
137
|
+
)
|
|
138
|
+
print(
|
|
139
|
+
f' groups.push({{ title: "{title}", alwaysVisible: {always_visible_str}, entries: entries }});'
|
|
140
|
+
)
|
|
141
|
+
print()
|
|
142
|
+
|
|
143
|
+
if title == "T factory parameters":
|
|
144
|
+
print(" }")
|
|
145
|
+
|
|
146
|
+
always_visible = False
|
|
147
|
+
entries.clear()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def create_fmt_string(string):
|
|
151
|
+
args = []
|
|
152
|
+
|
|
153
|
+
# Find in-text `paths`
|
|
154
|
+
pos = string.find("`")
|
|
155
|
+
while pos != -1:
|
|
156
|
+
pos2 = string.find("`", pos + 1)
|
|
157
|
+
path = string[pos + 1 : pos2]
|
|
158
|
+
|
|
159
|
+
if path in ignore_paths:
|
|
160
|
+
pos = string.find("`", pos2 + 1)
|
|
161
|
+
else:
|
|
162
|
+
string = string[:pos] + "${" + path_map[path] + "}" + string[pos2 + 1 :]
|
|
163
|
+
pos = string.find("`", pos + 1)
|
|
164
|
+
|
|
165
|
+
# Find in-math \mathtt{paths}
|
|
166
|
+
pos = string.find("\\mathtt{")
|
|
167
|
+
while pos != -1:
|
|
168
|
+
pos2 = string.find("}", pos + 1)
|
|
169
|
+
path = string[pos + 8 : pos2]
|
|
170
|
+
|
|
171
|
+
string = string[:pos] + "${" + path_map[path] + "}" + string[pos2 + 1 :]
|
|
172
|
+
pos = string.find("\\mathtt{", pos + 1)
|
|
173
|
+
|
|
174
|
+
if len(args) != 0:
|
|
175
|
+
args_list = ", ".join(args)
|
|
176
|
+
|
|
177
|
+
cur = 0
|
|
178
|
+
while cur < len(string):
|
|
179
|
+
if string[cur] == "{" and string[cur + 1] != "}":
|
|
180
|
+
string = string[:cur] + "{" + string[cur:]
|
|
181
|
+
cur += 2
|
|
182
|
+
elif string[cur] == "}" and string[cur - 1] != "{":
|
|
183
|
+
string = string[:cur] + "}" + string[cur:]
|
|
184
|
+
cur += 2
|
|
185
|
+
else:
|
|
186
|
+
cur += 1
|
|
187
|
+
|
|
188
|
+
string = string.replace("\\", "\\\\")
|
|
189
|
+
string = string.replace("`", "\\`")
|
|
190
|
+
return f"`{string}`"
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
with open("output_data.md", "r") as f:
|
|
194
|
+
for line in f.readlines():
|
|
195
|
+
line = line.strip()
|
|
196
|
+
|
|
197
|
+
if line == "":
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
if not parse:
|
|
201
|
+
if line.startswith("## "):
|
|
202
|
+
parse = True
|
|
203
|
+
else:
|
|
204
|
+
continue
|
|
205
|
+
|
|
206
|
+
if line.startswith("## "):
|
|
207
|
+
# Finish previous group?
|
|
208
|
+
if len(entries) != 0:
|
|
209
|
+
add_group()
|
|
210
|
+
|
|
211
|
+
title = line[3:].strip()
|
|
212
|
+
elif line.startswith("### "):
|
|
213
|
+
label = line[4:].strip()
|
|
214
|
+
elif line.startswith("[//]: #"):
|
|
215
|
+
path = line[9:-1]
|
|
216
|
+
elif line.startswith("_"):
|
|
217
|
+
description = line[1:-1]
|
|
218
|
+
elif line.startswith("-"):
|
|
219
|
+
assumptions.append(line[2:])
|
|
220
|
+
else:
|
|
221
|
+
explanation = line
|
|
222
|
+
|
|
223
|
+
entries.append(
|
|
224
|
+
(
|
|
225
|
+
path,
|
|
226
|
+
label,
|
|
227
|
+
create_fmt_string(description),
|
|
228
|
+
create_fmt_string(explanation),
|
|
229
|
+
)
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
# Add assumptions
|
|
233
|
+
assert title == "Assumptions"
|
|
234
|
+
print(" const assumptions = [")
|
|
235
|
+
for assumption in assumptions:
|
|
236
|
+
print(f" '{assumption}',")
|
|
237
|
+
print(" ];")
|
|
238
|
+
print()
|
|
239
|
+
print(" return { groups: groups, assumptions: assumptions };")
|
|
240
|
+
print("}")
|
|
241
|
+
print("// END OF AUTOMATICALLY GENERATED CODE")
|
|
242
|
+
print()
|
|
243
|
+
print()
|
package/ux/index.ts
CHANGED
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
// to a CSS file adjacent to the JS bundle and with the same name.
|
|
6
6
|
import "./qsharp-ux.css";
|
|
7
7
|
|
|
8
|
+
export { CreateSingleEstimateResult, type ReData } from "./data.js";
|
|
8
9
|
export { Histogram } from "./histogram.js";
|
|
9
|
-
export { ReTable
|
|
10
|
+
export { ReTable } from "./reTable.js";
|
|
10
11
|
export { SpaceChart } from "./spaceChart.js";
|
|
11
|
-
export {
|
|
12
|
+
export { ScatterChart } from "./scatterChart.js";
|
|
13
|
+
export { EstimatesOverview } from "./estimatesOverview.js";
|