Skip to content

Commit 860017c

Browse files
committed
Add error explanations to the table.
1 parent ae53ae3 commit 860017c

File tree

4 files changed

+83
-9
lines changed

4 files changed

+83
-9
lines changed

src/herbie/HerbieTypes.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ export class PointLocalErrorAnalysis {
206206
type Explanation = [
207207
string, // operator
208208
string, // expression
209-
string, // type
209+
string, // type (the actual error code, e.g. "cancellation")
210210
number, // occurrences
211211
number, // errors
212212
any[] , // details

src/herbie/HerbieUI.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,12 @@ button, select {
117117

118118
select {
119119
font-family: 'IBM Plex Serif', serif;
120-
font-size: 10px;
120+
font-size: 14px;
121121
}
122122

123123
button {
124124
font-family: 'Ruda', sans-serif;
125-
font-size: 10px;
125+
font-size: 14px;
126126
}
127127

128128
button:disabled {

src/herbie/LocalError/newLocalError.css

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
overflow-x: auto;
2525
display: block;
2626
text-align: left;
27-
max-width: 300px;
27+
max-width: 200px;
2828
}
2929

30-
.local-error td:not(.program-col) {
30+
.local-error td:not(.program-col), th:not(.program-col) {
3131
text-align: right;
3232
}
3333

@@ -44,3 +44,6 @@
4444
color: black;
4545
}
4646

47+
.no-explanations .explanation {
48+
display: none;
49+
}

src/herbie/LocalError/newLocalError.tsx

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,16 @@ function shouldExpand(currentPath: number[], allErrorPaths: number[][]): boolean
6161
);
6262
}
6363

64+
type LocalErrorTreeWithExplanation = LocalErrorTree & { explanation?: string, path?: number[] };
65+
66+
6467
function TreeRow({
6568
node,
6669
depth,
6770
currentPath,
6871
errorPaths,
6972
}: {
70-
node: LocalErrorTree;
73+
node: LocalErrorTreeWithExplanation;
7174
depth: number;
7275
currentPath: number[];
7376
errorPaths: number[][];
@@ -131,6 +134,31 @@ function TreeRow({
131134
<td className="accuracy-col">
132135
{parseFloat(node["percent-accuracy"]).toFixed(1)}%
133136
</td>
137+
<td className="explanation">
138+
{node.explanation ?
139+
node.explanation === "cancellation" ? (
140+
<a href="https://en.wikipedia.org/wiki/Catastrophic_cancellation" target="_blank" rel="noopener noreferrer">
141+
<span className="explanation-link" title="Click for more information about this error type">
142+
{node.explanation}
143+
</span>
144+
</a>
145+
) :
146+
node.explanation === "oflow-rescue" ? (
147+
<a href="https://en.wikipedia.org/wiki/Floating-point_arithmetic#:~:text=including%20the%20zeros.-,overflow,-%2C%20set%20if%20the" target="_blank" rel="noopener noreferrer">
148+
<span className="explanation-link" title="Click for more information about this error type">
149+
{node.explanation}
150+
</span>
151+
</a>
152+
) :
153+
// TODO handle other explanations
154+
(
155+
<span className="explanation">
156+
{node.explanation}
157+
</span>
158+
) : (
159+
<span className="no-explanation"></span>
160+
)}
161+
</td>
134162
{/* <td>
135163
<span >
136164
{parseFloat(node["ulps-error"]).toFixed(1)}
@@ -152,11 +180,35 @@ function TreeRow({
152180
);
153181
}
154182

183+
// Applies a function on a tree structure, providing a current path
184+
// in the tree as [] for the root, [1] for the first child, [[1, 2]] for the second child of the first child, etc.
185+
function treeMapWithPath<T, U>(
186+
tree: T,
187+
fn: (node: T, path: number[]) => U,
188+
getChildren: (node: T) => T[] | undefined,
189+
path: number[] = []
190+
): U {
191+
const result = fn(tree, path);
192+
const children = getChildren(tree);
193+
194+
if (children) {
195+
children.forEach((child, index) => {
196+
treeMapWithPath(child, fn, getChildren, [...path, index+1]);
197+
});
198+
}
199+
200+
return result;
201+
}
202+
155203
function NewLocalError({ expressionId }: { expressionId: number }) {
156204
const [selectedPointsLocalError] = HerbieContext.useGlobal(HerbieContext.SelectedPointsLocalErrorContext);
157205
const [localError, setLocalError] = useState<LocalErrorTree | null>(null);
158206
const [errorPaths, setErrorPaths] = useState<number[][]>([]);
207+
const [selectedPointsErrorExp,] = HerbieContext.useGlobal(HerbieContext.SelectedPointsErrorExpContext);
208+
209+
const pointErrorExp = selectedPointsErrorExp.find(a => a.expressionId === expressionId)?.error;
159210

211+
// TODO we probably don't need these useState hooks, we can just use the context directly
160212
useEffect(() => {
161213
const pointLocalError = selectedPointsLocalError.find(
162214
(a) => a.expressionId === expressionId
@@ -170,16 +222,34 @@ function NewLocalError({ expressionId }: { expressionId: number }) {
170222
}
171223
}, [selectedPointsLocalError, expressionId]);
172224

173-
if (!localError) {
225+
if (!localError || !pointErrorExp
226+
) {
174227
return (
175228
<div className="not-computed">
176229
<div>No local error computed for this expression. Select a point to compute.</div>
177230
</div>
178231
);
179232
}
233+
console.log("pointErrorExp", pointErrorExp)
234+
const explanations = pointErrorExp.explanation.map(e => e[2]);
235+
const explanationPaths = pointErrorExp.explanation.map(e => e[6][0]);
236+
console.log(explanations, explanationPaths);
237+
238+
// For each node in the local error tree, attach its explanation if it exists
239+
const localErrorWithExplanations = treeMapWithPath(localError as LocalErrorTreeWithExplanation, (node, path) => {
240+
// Find the explanation for this node, if it exists
241+
const explanationIndex = explanationPaths.findIndex(ep =>
242+
ep.length === path.length &&
243+
ep.join(',') === path.join(',')
244+
);
245+
node.explanation = explanationIndex !== -1 ? explanations[explanationIndex] : undefined;
246+
return node;
247+
}, (node) => node.children);
180248

249+
const hasNoExplanations = explanationPaths.length === 0
250+
181251
return (
182-
<div className="local-error">
252+
<div className={`local-error ${hasNoExplanations ? ' no-explanations' : ''}`}>
183253
<table>
184254
<thead>
185255
<tr>
@@ -190,10 +260,11 @@ function NewLocalError({ expressionId }: { expressionId: number }) {
190260
Difference
191261
</th>
192262
<th>Accuracy</th>
263+
<th className="explanation">Explanation</th>
193264
</tr>
194265
</thead>
195266
<tbody>
196-
<TreeRow node={localError} depth={0} currentPath={[]} errorPaths={errorPaths} />
267+
<TreeRow node={localErrorWithExplanations} depth={0} currentPath={[]} errorPaths={errorPaths} />
197268
</tbody>
198269
</table>
199270
</div>

0 commit comments

Comments
 (0)