├── .github └── workflows │ └── publish.yml ├── .gitignore ├── .gitmodules ├── .vscode └── extensions.json ├── LICENSE ├── README.md ├── eslint.config.js ├── examples └── manual │ ├── homepage.json │ └── python-functions.json ├── index.html ├── package.json ├── postcss.config.js ├── public └── vite.svg ├── src ├── App.tsx ├── Loading.tsx ├── Monaco.tsx ├── Visualizer.tsx ├── assets │ └── react.svg ├── examples.ts ├── index.css ├── layout.ts ├── main.tsx ├── queryClient.ts └── vite-env.d.ts ├── tailwind.config.js ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.node.json ├── vite.config.ts └── yarn.lock /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Build and Publish to NPM 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - "*" 9 | 10 | jobs: 11 | build-and-publish: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: write 15 | pages: write 16 | id-token: write 17 | environment: 18 | name: github-pages 19 | url: ${{ steps.deployment.outputs.page_url }} 20 | steps: 21 | - uses: actions/checkout@v4 22 | with: 23 | submodules: true 24 | - run: corepack enable 25 | - uses: actions/setup-node@v4 26 | with: 27 | node-version: "22.x" 28 | cache: "yarn" 29 | registry-url: "https://registry.npmjs.org" 30 | - run: yarn install 31 | - run: yarn build 32 | - run: yarn pack -o package.tgz 33 | - uses: softprops/action-gh-release@v2 34 | if: startsWith(github.ref, 'refs/tags/') 35 | with: 36 | files: package.tgz 37 | - name: Setup Pages 38 | uses: actions/configure-pages@v4 39 | - name: Upload artifact 40 | uses: actions/upload-pages-artifact@v3 41 | with: 42 | # Upload dist folder 43 | path: "./dist" 44 | - name: Deploy to GitHub Pages 45 | id: deployment 46 | uses: actions/deploy-pages@v4 47 | # Publish all dist at top level so that esm.sh can find web worker... 48 | - run: npm publish --provenance --access public package.tgz 49 | if: startsWith(github.ref, 'refs/tags/') 50 | env: 51 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 52 | 53 | lint: 54 | runs-on: ubuntu-latest 55 | steps: 56 | - uses: actions/checkout@v4 57 | - run: corepack enable 58 | - uses: actions/setup-node@v4 59 | with: 60 | node-version: "22.x" 61 | cache: "yarn" 62 | - run: yarn install 63 | - run: yarn lint 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | .yarn 26 | 27 | .pnp.cjs 28 | .pnp.loader.mjs 29 | .yarnrc 30 | *.tsbuildinfo 31 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "examples/extraction-gym"] 2 | path = examples/extraction-gym 3 | url = https://github.com/egraphs-good/extraction-gym 4 | [submodule "examples/egraph-serialize"] 5 | path = examples/egraph-serialize 6 | url = https://github.com/egraphs-good/egraph-serialize 7 | [submodule "src/react-aria-components-tailwind-starter"] 8 | path = src/react-aria-components-tailwind-starter 9 | url = https://github.com/zaichaopan/react-aria-components-tailwind-starter.git 10 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "arcanis.vscode-zipfs", 4 | "dbaeumer.vscode-eslint" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Saul Shanabrook 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EGraph Visualizer 2 | 3 | This packages aims to help with debugging and teaching e-graphs through an interactive visualization. 4 | 5 | It supports any e-graph [serialized in the JSON format](https://github.com/egraphs-good/egraph-serialize/) 6 | 7 | ## Packaging 8 | 9 | Currently, this visualizer is packaged as an [AnyWidget JS ESM file](https://anywidget.dev/) with all dependencies included. 10 | On every Git tag, a new verison is bundled and published as a Github release. 11 | 12 | It is also published as an NPM package, which can be imported and used in the browser like this: 13 | 14 | ```html 15 |
16 | 17 | 64 | ``` 65 | 66 | There is also a demo site published on Github Pages, which allows you to upload and edit a serialized e-graph and see 67 | the visualization. 68 | 69 | _If other ways of packaging would be helpful, please open an issue._ 70 | 71 | ## Development 72 | 73 | First install [Yarn](https://yarnpkg.com/getting-started/install), then run: 74 | 75 | ```sh 76 | yarn install 77 | yarn run [build|start|lint] 78 | ``` 79 | 80 | ## Releasing 81 | 82 | Releasing is totally automated. Just update the version in `package.json` and push a new tag to the repository. 83 | 84 | You can purge the cache for jsDelivr so that egglog will pull in the new version, by entering these two URLs [here](https://www.jsdelivr.com/tools/purge). 85 | 86 | ``` 87 | https://cdn.jsdelivr.net/npm/egraph-visualizer@2/dist/style.css 88 | https://cdn.jsdelivr.net/npm/egraph-visualizer@2/+esm 89 | ``` 90 | 91 | ## Contributing 92 | 93 | This package is open to external contributors. Feel free to open a pull request or an issue for bugs or desired features. 94 | It is developed as part of the EGRAPHS community and can also be discussed in the [EGRAPHS zulip](https://egraphs.org/zulip/). 95 | 96 | @saulshanabrook is the current maintainor of this package, but others can be added after contributing. 97 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | import js from '@eslint/js' 2 | import globals from 'globals' 3 | import reactHooks from 'eslint-plugin-react-hooks' 4 | import reactRefresh from 'eslint-plugin-react-refresh' 5 | import tseslint from 'typescript-eslint' 6 | import pluginQuery from '@tanstack/eslint-plugin-query' 7 | 8 | export default tseslint.config( 9 | ...pluginQuery.configs['flat/recommended'], 10 | { ignores: ['dist'] }, 11 | { 12 | extends: [js.configs.recommended, ...tseslint.configs.recommended], 13 | files: ['**/*.{ts,tsx}'], 14 | languageOptions: { 15 | ecmaVersion: 2020, 16 | globals: globals.browser, 17 | }, 18 | plugins: { 19 | 'react-hooks': reactHooks, 20 | 'react-refresh': reactRefresh, 21 | }, 22 | rules: { 23 | ...reactHooks.configs.recommended.rules, 24 | 'react-refresh/only-export-components': [ 25 | 'warn', 26 | { allowConstantExport: true }, 27 | ], 28 | }, 29 | }, 30 | ) 31 | -------------------------------------------------------------------------------- /examples/manual/homepage.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "//": { 4 | "op": "/", 5 | "children": ["*", "2"], 6 | "eclass": "top" 7 | }, 8 | "**": { 9 | "op": "*", 10 | "eclass": "top", 11 | "children": ["a", "/"] 12 | }, 13 | "*": { 14 | "op": "*", 15 | "eclass": "middle", 16 | "children": ["a", "2"] 17 | }, 18 | "<<": { 19 | "op": "<<", 20 | "eclass": "middle", 21 | "children": ["a", "1"] 22 | }, 23 | "a": { 24 | "op": "a", 25 | "eclass": "top" 26 | }, 27 | "2": { 28 | "op": "2", 29 | "eclass": "bottom" 30 | }, 31 | "1": { 32 | "op": "1", 33 | "eclass": "right" 34 | }, 35 | "/": { 36 | "op": "/", 37 | "eclass": "right", 38 | "children": ["2", "2"] 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /examples/manual/python-functions.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "function-0-NDArray_dtype": { 4 | "op": "·.dtype", 5 | "children": ["function-1-assume_shape"], 6 | "eclass": "DType-17", 7 | "cost": 1 8 | }, 9 | "function-2-NDArray_dtype": { 10 | "op": "NDArray.var(\"X\").dtype", 11 | "children": [], 12 | "eclass": "DType-17", 13 | "cost": 202 14 | }, 15 | "function-0-dims-TupleInt_i-Int__TupleInt___getitem___dims_i_": { 16 | "op": "lambda dims, i: dims[i](·, Int(4))", 17 | "children": ["function-1-NDArray_shape"], 18 | "eclass": "Int-12", 19 | "cost": 3 20 | }, 21 | "function-0-Int___eq__": { 22 | "op": "Int(4) == Int(0)", 23 | "children": [], 24 | "eclass": "Boolean-460", 25 | "cost": 5 26 | }, 27 | "function-1-Int___eq__": { 28 | "op": "Int(4) == Int(1)", 29 | "children": [], 30 | "eclass": "split-0-function-0-FALSE", 31 | "cost": 5 32 | }, 33 | "primitive-bool-1": { 34 | "op": "true", 35 | "children": [], 36 | "eclass": "bool-1", 37 | "cost": 1 38 | }, 39 | "function-0-Boolean_bool": { 40 | "op": "TRUE.bool", 41 | "children": [], 42 | "eclass": "bool-1", 43 | "cost": 2 44 | }, 45 | "primitive-bool-0": { 46 | "op": "false", 47 | "children": [], 48 | "eclass": "bool-0", 49 | "cost": 1 50 | }, 51 | "function-3-Boolean_bool": { 52 | "op": "FALSE.bool", 53 | "children": [], 54 | "eclass": "bool-0", 55 | "cost": 2 56 | }, 57 | "function-0-ShapeAPI_select": { 58 | "op": "·.select", 59 | "children": ["function-0-ShapeAPI___init__", "function-16-TupleInt___init__"], 60 | "eclass": "ShapeAPI-18", 61 | "cost": 1 62 | }, 63 | "function-0-ShapeAPI___init__": { 64 | "op": "ShapeAPI", 65 | "children": ["function-11-TupleInt___init__"], 66 | "eclass": "ShapeAPI-14", 67 | "cost": 1 68 | }, 69 | "function-1-ShapeAPI___init__": { 70 | "op": "ShapeAPI", 71 | "children": ["function-2-TupleInt_map"], 72 | "eclass": "ShapeAPI-15", 73 | "cost": 1 74 | }, 75 | "function-2-ShapeAPI___init__": { 76 | "op": "ShapeAPI", 77 | "children": ["function-3-TupleInt_map"], 78 | "eclass": "ShapeAPI-18", 79 | "cost": 1 80 | }, 81 | "function-0-Int___add__": { 82 | "op": "Int(-2) + Int(1)", 83 | "children": [], 84 | "eclass": "Int-341", 85 | "cost": 5 86 | }, 87 | "function-1-Int___add__": { 88 | "op": "Int(1) + Int(3)", 89 | "children": [], 90 | "eclass": "Int-269", 91 | "cost": 5 92 | }, 93 | "function-2-Int___add__": { 94 | "op": "Int(3) + Int(1)", 95 | "children": [], 96 | "eclass": "split-0-function-5-Int___init__", 97 | "cost": 5 98 | }, 99 | "function-3-Int___add__": { 100 | "op": "Int(1) + Int(1)", 101 | "children": [], 102 | "eclass": "Int-300", 103 | "cost": 5 104 | }, 105 | "function-4-Int___add__": { 106 | "op": "Int(1) + Int(2)", 107 | "children": [], 108 | "eclass": "Int-69", 109 | "cost": 5 110 | }, 111 | "function-5-Int___add__": { 112 | "op": "Int(2) + Int(1)", 113 | "children": [], 114 | "eclass": "split-0-function-1-Int___init__", 115 | "cost": 5 116 | }, 117 | "function-6-Int___add__": { 118 | "op": "Int(0) + Int(1)", 119 | "children": [], 120 | "eclass": "Int-227", 121 | "cost": 5 122 | }, 123 | "function-7-Int___add__": { 124 | "op": "Int(1) + Int(0)", 125 | "children": [], 126 | "eclass": "split-0-function-2-Int___init__", 127 | "cost": 5 128 | }, 129 | "function-8-Int___add__": { 130 | "op": "Int(-1) + Int(1)", 131 | "children": [], 132 | "eclass": "Int-422", 133 | "cost": 5 134 | }, 135 | "primitive-Vec_Int-31": { 136 | "op": "Vec(Int(3), Int(2), Int(3), Int(4))", 137 | "children": [], 138 | "eclass": "Vec_Int-31", 139 | "cost": 9 140 | }, 141 | "function-2-TupleInt_from_vec": { 142 | "op": "TupleInt.from_vec", 143 | "children": ["primitive-Vec_Int-31"], 144 | "eclass": "TupleInt-13", 145 | "cost": 1 146 | }, 147 | "primitive-Vec_Int-32": { 148 | "op": "Vec(Int(0), Int(1))", 149 | "children": [], 150 | "eclass": "Vec_Int-32", 151 | "cost": 5 152 | }, 153 | "function-3-TupleInt_from_vec": { 154 | "op": "TupleInt.from_vec", 155 | "children": ["primitive-Vec_Int-32"], 156 | "eclass": "TupleInt-9", 157 | "cost": 1 158 | }, 159 | "function-1-assume_shape": { 160 | "op": "assume_shape(NDArray.var(\"X\"), ·)", 161 | "children": ["function-2-TupleInt_from_vec"], 162 | "eclass": "NDArray-6", 163 | "cost": 202 164 | }, 165 | "function-0-TupleInt_length": { 166 | "op": "·.length", 167 | "children": ["function-0-TupleInt___init__"], 168 | "eclass": "split-1-function-1-Int___init__", 169 | "cost": 1 170 | }, 171 | "function-1-TupleInt_length": { 172 | "op": "·.length", 173 | "children": ["function-4-TupleInt___init__"], 174 | "eclass": "split-1-function-2-Int___init__", 175 | "cost": 1 176 | }, 177 | "function-2-TupleInt_length": { 178 | "op": "·.length", 179 | "children": ["function-12-TupleInt___init__"], 180 | "eclass": "split-2-function-2-Int___init__", 181 | "cost": 1 182 | }, 183 | "function-3-TupleInt_length": { 184 | "op": "·.length", 185 | "children": ["function-9-TupleInt___init__"], 186 | "eclass": "split-1-function-5-Int___init__", 187 | "cost": 1 188 | }, 189 | "function-4-TupleInt_length": { 190 | "op": "·.length", 191 | "children": ["function-1-NDArray_shape"], 192 | "eclass": "split-2-function-5-Int___init__", 193 | "cost": 1 194 | }, 195 | "function-5-TupleInt_length": { 196 | "op": "·.length", 197 | "children": ["function-15-TupleInt___init__"], 198 | "eclass": "split-0-function-9-Int___init__", 199 | "cost": 1 200 | }, 201 | "function-6-TupleInt_length": { 202 | "op": "·.length", 203 | "children": ["function-19-TupleInt___init__"], 204 | "eclass": "split-0-function-10-Int___init__", 205 | "cost": 1 206 | }, 207 | "primitive-UnstableFn_Int_Int-2": { 208 | "op": "lambda dims, i: dims[i]", 209 | "children": ["function-1-NDArray_shape"], 210 | "eclass": "UnstableFn_Int_Int-2", 211 | "cost": 1 212 | }, 213 | "function-0-f-UnstableFn_Int_Int_self-TupleInt_i-Int__unstable-app_f__TupleInt___getitem___self_i__": { 214 | "op": "lambda f, self, i: f(self[i])(·, ·, Int(2))", 215 | "children": ["primitive-UnstableFn_Int_Int-2", "function-0-TupleInt_filter"], 216 | "eclass": "Int-12", 217 | "cost": 3 218 | }, 219 | "function-0-TupleInt_if_": { 220 | "op": "TupleInt.if_(TRUE, ·, ·)", 221 | "children": ["function-4-TupleInt___add__", "function-5-TupleInt_filter"], 222 | "eclass": "TupleInt-42", 223 | "cost": 2 224 | }, 225 | "function-1-TupleInt_if_": { 226 | "op": "TupleInt.if_(TRUE, ·, ·)", 227 | "children": ["function-1-TupleInt_if_", "function-0-TupleInt_if_"], 228 | "eclass": "TupleInt-25", 229 | "cost": 2 230 | }, 231 | "function-2-TupleInt_if_": { 232 | "op": "TupleInt.if_(TRUE, ·, ·)", 233 | "children": ["function-2-TupleInt_if_", "function-6-TupleInt_filter"], 234 | "eclass": "TupleInt-62", 235 | "cost": 2 236 | }, 237 | "function-3-TupleInt_if_": { 238 | "op": "TupleInt.if_(TRUE, ·, ·)", 239 | "children": ["function-3-TupleInt_if_", "function-1-TupleInt_filter"], 240 | "eclass": "TupleInt-84", 241 | "cost": 2 242 | }, 243 | "function-7-TupleInt_if_": { 244 | "op": "TupleInt.if_(FALSE, ·, ·)", 245 | "children": ["function-4-TupleInt___init__", "function-13-TupleInt_filter"], 246 | "eclass": "TupleInt-28", 247 | "cost": 2 248 | }, 249 | "function-1-i-Int__-Int_i": { 250 | "op": "lambda i, _: i(Int(4), Int(1))", 251 | "children": [], 252 | "eclass": "split-3-function-5-Int___init__", 253 | "cost": 5 254 | }, 255 | "function-4-i-Int__-Int_i": { 256 | "op": "lambda i, _: i(Int(4), Int(-1))", 257 | "children": [], 258 | "eclass": "split-4-function-5-Int___init__", 259 | "cost": 5 260 | }, 261 | "function-6-i-Int__-Int_i": { 262 | "op": "lambda i, _: i(Int(4), Int(2))", 263 | "children": [], 264 | "eclass": "split-5-function-5-Int___init__", 265 | "cost": 5 266 | }, 267 | "function-7-i-Int__-Int_i": { 268 | "op": "lambda i, _: i(Int(4), Int(0))", 269 | "children": [], 270 | "eclass": "split-6-function-5-Int___init__", 271 | "cost": 5 272 | }, 273 | "function-0-TupleInt_range": { 274 | "op": "TupleInt.range(Int(4))", 275 | "children": [], 276 | "eclass": "TupleInt-24", 277 | "cost": 3 278 | }, 279 | "function-0-index_vec_int": { 280 | "op": "index_vec_int(·, Int(4))", 281 | "children": ["primitive-Vec_Int-31"], 282 | "eclass": "Int-12", 283 | "cost": 3 284 | }, 285 | "function-1-index_vec_int": { 286 | "op": "index_vec_int(·, Int(1))", 287 | "children": ["primitive-Vec_Int-32"], 288 | "eclass": "split-3-function-2-Int___init__", 289 | "cost": 3 290 | }, 291 | "function-2-index_vec_int": { 292 | "op": "index_vec_int(·, Int(0))", 293 | "children": ["primitive-Vec_Int-32"], 294 | "eclass": "split-1-function-10-Int___init__", 295 | "cost": 3 296 | }, 297 | "function-0-axis-TupleInt_i-Int__TupleInt_contains_axis_i_": { 298 | "op": "lambda axis, i: axis.contains(i)(·, Int(4))", 299 | "children": ["function-16-TupleInt___init__"], 300 | "eclass": "split-1-function-0-FALSE", 301 | "cost": 3 302 | }, 303 | "function-0-linalg_norm": { 304 | "op": "linalg_norm", 305 | "children": ["function-1-assume_shape", "function-3-TupleInt_from_vec"], 306 | "eclass": "NDArray-10", 307 | "cost": 1 308 | }, 309 | "split-0-split-24-function-5-Int___init__": { 310 | "op": "Int(4)", 311 | "children": [], 312 | "eclass": "split-0-split-24-function-5-Int___init__", 313 | "cost": 2 314 | }, 315 | "split-0-split-21-function-5-Int___init__": { 316 | "op": "Int(4)", 317 | "children": [], 318 | "eclass": "split-0-split-21-function-5-Int___init__", 319 | "cost": 2 320 | }, 321 | "function-0-i-Int_i": { 322 | "op": "lambda i: i(Int(4))", 323 | "children": [], 324 | "eclass": "split-7-function-5-Int___init__", 325 | "cost": 3 326 | }, 327 | "function-1-i-Int_i": { 328 | "op": "lambda i: i(Int(2))", 329 | "children": [], 330 | "eclass": "split-1-function-9-Int___init__", 331 | "cost": 3 332 | }, 333 | "primitive-i64-3": { 334 | "op": "3", 335 | "children": [], 336 | "eclass": "i64-3", 337 | "cost": 1 338 | }, 339 | "function-0-Int_i64": { 340 | "op": "Int(3).i64", 341 | "children": [], 342 | "eclass": "i64-3", 343 | "cost": 3 344 | }, 345 | "primitive-i64-1": { 346 | "op": "1", 347 | "children": [], 348 | "eclass": "i64-1", 349 | "cost": 1 350 | }, 351 | "function-1-Int_i64": { 352 | "op": "Int(1).i64", 353 | "children": [], 354 | "eclass": "i64-1", 355 | "cost": 3 356 | }, 357 | "primitive-i64-18446744073709551614": { 358 | "op": "-2", 359 | "children": [], 360 | "eclass": "i64-18446744073709551614", 361 | "cost": 1 362 | }, 363 | "function-2-Int_i64": { 364 | "op": "Int(-2).i64", 365 | "children": [], 366 | "eclass": "i64-18446744073709551614", 367 | "cost": 3 368 | }, 369 | "primitive-i64-4": { 370 | "op": "4", 371 | "children": [], 372 | "eclass": "i64-4", 373 | "cost": 1 374 | }, 375 | "function-3-Int_i64": { 376 | "op": "Int(4).i64", 377 | "children": [], 378 | "eclass": "i64-4", 379 | "cost": 3 380 | }, 381 | "primitive-i64-18446744073709551615": { 382 | "op": "-1", 383 | "children": [], 384 | "eclass": "i64-18446744073709551615", 385 | "cost": 1 386 | }, 387 | "function-4-Int_i64": { 388 | "op": "Int(-1).i64", 389 | "children": [], 390 | "eclass": "i64-18446744073709551615", 391 | "cost": 3 392 | }, 393 | "primitive-i64-2": { 394 | "op": "2", 395 | "children": [], 396 | "eclass": "i64-2", 397 | "cost": 1 398 | }, 399 | "function-5-Int_i64": { 400 | "op": "Int(2).i64", 401 | "children": [], 402 | "eclass": "i64-2", 403 | "cost": 3 404 | }, 405 | "primitive-i64-0": { 406 | "op": "0", 407 | "children": [], 408 | "eclass": "i64-0", 409 | "cost": 1 410 | }, 411 | "function-6-Int_i64": { 412 | "op": "Int(0).i64", 413 | "children": [], 414 | "eclass": "i64-0", 415 | "cost": 3 416 | }, 417 | "primitive-UnstableFn_Value_TupleInt-0": { 418 | "op": "lambda X, reduce_axis, k: sqrt(LoopNestAPI.from_tuple(reduce_axis).unwrap().fold(lambda carry, i: carry + real(conj(X[IndexKey.multi_axis(MultiAxisIndexKey((i + k).length(), lambda i: MultiAxisIndexKeyItem.int((i + k)[i])))]) * X[IndexKey.multi_axis(MultiAxisIndexKey((i + k).length(), lambda i: MultiAxisIndexKeyItem.int((i + k)[i])))]), NDArray.scalar(Value.float(Float(0.0))))).to_value()", 419 | "children": ["function-1-assume_shape", "function-18-TupleInt___init__"], 420 | "eclass": "UnstableFn_Value_TupleInt-0", 421 | "cost": 1 422 | }, 423 | "function-0-NDArray___init__": { 424 | "op": "NDArray", 425 | "children": ["function-0-NDArray_shape", "function-2-NDArray_dtype", "primitive-UnstableFn_Value_TupleInt-0"], 426 | "eclass": "NDArray-10", 427 | "cost": 1 428 | }, 429 | "function-1-Boolean___invert__": { 430 | "op": "~FALSE", 431 | "children": [], 432 | "eclass": "Boolean-297", 433 | "cost": 2 434 | }, 435 | "function-1-TupleInt_single": { 436 | "op": "TupleInt.single(Int(4))", 437 | "children": [], 438 | "eclass": "TupleInt-56", 439 | "cost": 3 440 | }, 441 | "function-0-Int___sub__": { 442 | "op": "Int(-1) - Int(1)", 443 | "children": [], 444 | "eclass": "Int-299", 445 | "cost": 5 446 | }, 447 | "function-1-Int___sub__": { 448 | "op": "Int(2) - Int(1)", 449 | "children": [], 450 | "eclass": "split-4-function-2-Int___init__", 451 | "cost": 5 452 | }, 453 | "function-2-Int___sub__": { 454 | "op": "Int(1) - Int(1)", 455 | "children": [], 456 | "eclass": "split-2-function-10-Int___init__", 457 | "cost": 5 458 | }, 459 | "function-3-Int___sub__": { 460 | "op": "Int(0) - Int(1)", 461 | "children": [], 462 | "eclass": "split-0-function-7-Int___init__", 463 | "cost": 5 464 | }, 465 | "function-2-other-TupleInt_self-TupleInt_i-Int__Int_if___Int___lt___i__TupleInt_length_self____TupleInt___getitem___self_i___TupleInt___getitem___other__Int___sub___i__TupleInt_length_self____": { 466 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])(·, ·, Int(1))", 467 | "children": ["function-15-TupleInt___init__", "function-12-TupleInt___init__"], 468 | "eclass": "split-8-function-5-Int___init__", 469 | "cost": 3 470 | }, 471 | "function-4-other-TupleInt_self-TupleInt_i-Int__Int_if___Int___lt___i__TupleInt_length_self____TupleInt___getitem___self_i___TupleInt___getitem___other__Int___sub___i__TupleInt_length_self____": { 472 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])(·, ·, Int(-1))", 473 | "children": ["function-14-TupleInt_filter", "function-1-TupleInt_single"], 474 | "eclass": "split-9-function-5-Int___init__", 475 | "cost": 3 476 | }, 477 | "function-6-other-TupleInt_self-TupleInt_i-Int__Int_if___Int___lt___i__TupleInt_length_self____TupleInt___getitem___self_i___TupleInt___getitem___other__Int___sub___i__TupleInt_length_self____": { 478 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])(·, ·, Int(2))", 479 | "children": ["function-0-TupleInt___init__", "function-12-TupleInt___init__"], 480 | "eclass": "split-10-function-5-Int___init__", 481 | "cost": 3 482 | }, 483 | "function-7-other-TupleInt_self-TupleInt_i-Int__Int_if___Int___lt___i__TupleInt_length_self____TupleInt___getitem___self_i___TupleInt___getitem___other__Int___sub___i__TupleInt_length_self____": { 484 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])(·, ·, Int(0))", 485 | "children": ["function-6-TupleInt_filter", "function-1-TupleInt_single"], 486 | "eclass": "split-11-function-5-Int___init__", 487 | "cost": 3 488 | }, 489 | "function-0-Boolean___or__": { 490 | "op": "FALSE | FALSE", 491 | "children": [], 492 | "eclass": "split-2-function-0-FALSE", 493 | "cost": 3 494 | }, 495 | "primitive-UnstableFn_Boolean_Boolean_Int-8": { 496 | "op": "lambda i, acc, j: acc | (i == j)(Int(4))", 497 | "children": [], 498 | "eclass": "UnstableFn_Boolean_Boolean_Int-8", 499 | "cost": 3 500 | }, 501 | "function-0-TupleInt_fold_boolean": { 502 | "op": "·.fold_boolean(·, FALSE, ·)", 503 | "children": ["function-16-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 504 | "eclass": "split-3-function-0-FALSE", 505 | "cost": 2 506 | }, 507 | "function-1-TupleInt_fold_boolean": { 508 | "op": "·.fold_boolean(·, FALSE, ·)", 509 | "children": ["function-3-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 510 | "eclass": "split-4-function-0-FALSE", 511 | "cost": 2 512 | }, 513 | "function-2-TupleInt_fold_boolean": { 514 | "op": "·.fold_boolean(·, FALSE, ·)", 515 | "children": ["function-20-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 516 | "eclass": "split-5-function-0-FALSE", 517 | "cost": 2 518 | }, 519 | "function-3-TupleInt_fold_boolean": { 520 | "op": "·.fold_boolean(·, FALSE, ·)", 521 | "children": ["function-5-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 522 | "eclass": "split-6-function-0-FALSE", 523 | "cost": 2 524 | }, 525 | "function-4-TupleInt_fold_boolean": { 526 | "op": "·.fold_boolean(·, FALSE, ·)", 527 | "children": ["function-6-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 528 | "eclass": "split-7-function-0-FALSE", 529 | "cost": 2 530 | }, 531 | "function-5-TupleInt_fold_boolean": { 532 | "op": "·.fold_boolean(·, FALSE, ·)", 533 | "children": ["function-7-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 534 | "eclass": "split-8-function-0-FALSE", 535 | "cost": 2 536 | }, 537 | "function-6-TupleInt_fold_boolean": { 538 | "op": "·.fold_boolean(·, FALSE, ·)", 539 | "children": ["function-13-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 540 | "eclass": "split-9-function-0-FALSE", 541 | "cost": 2 542 | }, 543 | "function-7-TupleInt_fold_boolean": { 544 | "op": "·.fold_boolean(·, FALSE, ·)", 545 | "children": ["function-21-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 546 | "eclass": "split-10-function-0-FALSE", 547 | "cost": 2 548 | }, 549 | "function-8-TupleInt_fold_boolean": { 550 | "op": "·.fold_boolean(·, FALSE, ·)", 551 | "children": ["function-22-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 552 | "eclass": "split-11-function-0-FALSE", 553 | "cost": 2 554 | }, 555 | "function-9-TupleInt_fold_boolean": { 556 | "op": "·.fold_boolean(·, FALSE, ·)", 557 | "children": ["function-23-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 558 | "eclass": "split-12-function-0-FALSE", 559 | "cost": 2 560 | }, 561 | "function-10-TupleInt_fold_boolean": { 562 | "op": "·.fold_boolean(·, FALSE, ·)", 563 | "children": ["function-24-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 564 | "eclass": "split-13-function-0-FALSE", 565 | "cost": 2 566 | }, 567 | "function-11-TupleInt_fold_boolean": { 568 | "op": "·.fold_boolean(·, FALSE, ·)", 569 | "children": ["function-25-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 570 | "eclass": "split-14-function-0-FALSE", 571 | "cost": 2 572 | }, 573 | "function-12-TupleInt_fold_boolean": { 574 | "op": "·.fold_boolean(·, FALSE, ·)", 575 | "children": ["function-26-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 576 | "eclass": "split-15-function-0-FALSE", 577 | "cost": 2 578 | }, 579 | "function-13-TupleInt_fold_boolean": { 580 | "op": "·.fold_boolean(·, FALSE, ·)", 581 | "children": ["function-27-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 582 | "eclass": "split-16-function-0-FALSE", 583 | "cost": 2 584 | }, 585 | "function-14-TupleInt_fold_boolean": { 586 | "op": "·.fold_boolean(·, FALSE, ·)", 587 | "children": ["function-14-TupleInt___init__", "primitive-UnstableFn_Boolean_Boolean_Int-8"], 588 | "eclass": "split-17-function-0-FALSE", 589 | "cost": 2 590 | }, 591 | "function-1-Int___init__": { 592 | "op": "Int(3)", 593 | "children": [], 594 | "eclass": "Int-69", 595 | "cost": 2 596 | }, 597 | "function-2-Int___init__": { 598 | "op": "Int(1)", 599 | "children": [], 600 | "eclass": "Int-227", 601 | "cost": 2 602 | }, 603 | "function-4-Int___init__": { 604 | "op": "Int(-2)", 605 | "children": [], 606 | "eclass": "Int-299", 607 | "cost": 2 608 | }, 609 | "function-5-Int___init__": { 610 | "op": "Int(4)", 611 | "children": [], 612 | "eclass": "Int-269", 613 | "cost": 2 614 | }, 615 | "function-7-Int___init__": { 616 | "op": "Int(-1)", 617 | "children": [], 618 | "eclass": "Int-341", 619 | "cost": 2 620 | }, 621 | "function-9-Int___init__": { 622 | "op": "Int(2)", 623 | "children": [], 624 | "eclass": "Int-300", 625 | "cost": 2 626 | }, 627 | "function-10-Int___init__": { 628 | "op": "Int(0)", 629 | "children": [], 630 | "eclass": "Int-422", 631 | "cost": 2 632 | }, 633 | "function-2-TupleInt___getitem__": { 634 | "op": "·[Int(-2)]", 635 | "children": ["function-15-TupleInt_filter"], 636 | "eclass": "split-2-function-9-Int___init__", 637 | "cost": 3 638 | }, 639 | "function-3-TupleInt___getitem__": { 640 | "op": "·[Int(4)]", 641 | "children": ["function-29-TupleInt___init__"], 642 | "eclass": "Int-12", 643 | "cost": 3 644 | }, 645 | "function-7-TupleInt___getitem__": { 646 | "op": "·[Int(1)]", 647 | "children": ["function-2-TupleInt_filter"], 648 | "eclass": "split-12-function-5-Int___init__", 649 | "cost": 3 650 | }, 651 | "function-8-TupleInt___getitem__": { 652 | "op": "·[Int(1)]", 653 | "children": ["function-12-TupleInt___init__"], 654 | "eclass": "split-13-function-5-Int___init__", 655 | "cost": 3 656 | }, 657 | "function-11-TupleInt___getitem__": { 658 | "op": "·[Int(-1)]", 659 | "children": ["function-7-TupleInt___add__"], 660 | "eclass": "split-14-function-5-Int___init__", 661 | "cost": 3 662 | }, 663 | "function-12-TupleInt___getitem__": { 664 | "op": "·[Int(-1)]", 665 | "children": ["function-1-TupleInt_single"], 666 | "eclass": "split-15-function-5-Int___init__", 667 | "cost": 3 668 | }, 669 | "function-15-TupleInt___getitem__": { 670 | "op": "·[Int(2)]", 671 | "children": ["function-8-TupleInt___init__"], 672 | "eclass": "Int-12", 673 | "cost": 3 674 | }, 675 | "function-16-TupleInt___getitem__": { 676 | "op": "·[Int(2)]", 677 | "children": ["function-9-TupleInt___init__"], 678 | "eclass": "split-16-function-5-Int___init__", 679 | "cost": 3 680 | }, 681 | "function-17-TupleInt___getitem__": { 682 | "op": "·[Int(2)]", 683 | "children": ["function-12-TupleInt___init__"], 684 | "eclass": "split-17-function-5-Int___init__", 685 | "cost": 3 686 | }, 687 | "function-18-TupleInt___getitem__": { 688 | "op": "·[Int(0)]", 689 | "children": ["function-1-TupleInt_single"], 690 | "eclass": "split-18-function-5-Int___init__", 691 | "cost": 3 692 | }, 693 | "function-19-TupleInt___getitem__": { 694 | "op": "·[Int(0)]", 695 | "children": ["function-5-TupleInt_filter"], 696 | "eclass": "split-19-function-5-Int___init__", 697 | "cost": 3 698 | }, 699 | "split-0-split-25-function-5-Int___init__": { 700 | "op": "Int(4)", 701 | "children": [], 702 | "eclass": "split-0-split-25-function-5-Int___init__", 703 | "cost": 2 704 | }, 705 | "split-0-split-4-function-9-Int___init__": { 706 | "op": "Int(2)", 707 | "children": [], 708 | "eclass": "split-0-split-4-function-9-Int___init__", 709 | "cost": 2 710 | }, 711 | "primitive-UnstableFn_Int_Int-9": { 712 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(lambda idx_fn, i: idx_fn(i + Int(1))(lambda i: i))", 713 | "children": [], 714 | "eclass": "UnstableFn_Int_Int-9", 715 | "cost": 3 716 | }, 717 | "primitive-UnstableFn_Int_Int-14": { 718 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))", 719 | "children": ["primitive-UnstableFn_Int_Int-9"], 720 | "eclass": "UnstableFn_Int_Int-14", 721 | "cost": 1 722 | }, 723 | "function-0-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 724 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(·, Int(-2))", 725 | "children": ["primitive-UnstableFn_Int_Int-14"], 726 | "eclass": "split-3-function-9-Int___init__", 727 | "cost": 3 728 | }, 729 | "function-1-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 730 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(·, Int(1))", 731 | "children": ["primitive-UnstableFn_Int_Int-9"], 732 | "eclass": "split-20-function-5-Int___init__", 733 | "cost": 3 734 | }, 735 | "function-2-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 736 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(lambda i: i, Int(3))", 737 | "children": [], 738 | "eclass": "split-21-function-5-Int___init__", 739 | "cost": 4 740 | }, 741 | "function-3-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 742 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(·, Int(-1))", 743 | "children": ["primitive-UnstableFn_Int_Int-9"], 744 | "eclass": "split-4-function-9-Int___init__", 745 | "cost": 3 746 | }, 747 | "function-4-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 748 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(lambda i: i, Int(1))", 749 | "children": [], 750 | "eclass": "split-5-function-9-Int___init__", 751 | "cost": 4 752 | }, 753 | "function-5-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 754 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(lambda idx_fn, i: idx_fn(i + Int(1))(lambda i: i), Int(2))", 755 | "children": [], 756 | "eclass": "split-22-function-5-Int___init__", 757 | "cost": 5 758 | }, 759 | "primitive-UnstableFn_Int_Int-92": { 760 | "op": "index_vec_int", 761 | "children": ["primitive-Vec_Int-32"], 762 | "eclass": "UnstableFn_Int_Int-92", 763 | "cost": 1 764 | }, 765 | "function-6-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 766 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(·, Int(0))", 767 | "children": ["primitive-UnstableFn_Int_Int-92"], 768 | "eclass": "split-5-function-2-Int___init__", 769 | "cost": 3 770 | }, 771 | "function-7-idx_fn-UnstableFn_Int_Int_i-Int__unstable-app_idx_fn__Int___add___i__Int___init___1___": { 772 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))(lambda idx_fn, i: idx_fn(i + Int(1))(lambda i: i), Int(0))", 773 | "children": [], 774 | "eclass": "split-6-function-9-Int___init__", 775 | "cost": 5 776 | }, 777 | "function-1-axis-TupleInt_i-Int__Boolean___invert____TupleInt_contains_axis_i__": { 778 | "op": "lambda axis, i: ~axis.contains(i)(·, Int(4))", 779 | "children": ["function-3-TupleInt_from_vec"], 780 | "eclass": "split-0-function-1-TRUE", 781 | "cost": 3 782 | }, 783 | "function-1-ShapeAPI_to_tuple": { 784 | "op": "·.to_tuple", 785 | "children": ["function-2-ShapeAPI___init__"], 786 | "eclass": "TupleInt-19", 787 | "cost": 1 788 | }, 789 | "function-2-ShapeAPI_to_tuple": { 790 | "op": "·.to_tuple", 791 | "children": ["function-1-ShapeAPI___init__"], 792 | "eclass": "TupleInt-11", 793 | "cost": 1 794 | }, 795 | "function-2-TupleInt_map": { 796 | "op": "·.map", 797 | "children": ["function-0-TupleInt_filter", "primitive-UnstableFn_Int_Int-2"], 798 | "eclass": "TupleInt-11", 799 | "cost": 100 800 | }, 801 | "function-3-TupleInt_map": { 802 | "op": "·.map", 803 | "children": ["function-16-TupleInt_filter", "primitive-UnstableFn_Int_Int-2"], 804 | "eclass": "TupleInt-19", 805 | "cost": 100 806 | }, 807 | "function-0-i-Int_acc-Boolean_j-Int__Boolean___or___acc__Int___eq___i_j__": { 808 | "op": "lambda i, acc, j: acc | (i == j)(Int(4), FALSE, Int(0))", 809 | "children": [], 810 | "eclass": "split-18-function-0-FALSE", 811 | "cost": 6 812 | }, 813 | "function-1-i-Int_acc-Boolean_j-Int__Boolean___or___acc__Int___eq___i_j__": { 814 | "op": "lambda i, acc, j: acc | (i == j)(Int(4), FALSE, Int(1))", 815 | "children": [], 816 | "eclass": "split-19-function-0-FALSE", 817 | "cost": 6 818 | }, 819 | "function-0-ShapeAPI_deselect": { 820 | "op": "·.deselect", 821 | "children": ["function-0-ShapeAPI___init__", "function-16-TupleInt___init__"], 822 | "eclass": "ShapeAPI-15", 823 | "cost": 1 824 | }, 825 | "function-0-NDArray_shape": { 826 | "op": "·.shape", 827 | "children": ["function-0-NDArray___init__"], 828 | "eclass": "TupleInt-11", 829 | "cost": 1 830 | }, 831 | "function-1-NDArray_shape": { 832 | "op": "·.shape", 833 | "children": ["function-1-assume_shape"], 834 | "eclass": "TupleInt-13", 835 | "cost": 1 836 | }, 837 | "primitive-UnstableFn_Int_Int-15": { 838 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])", 839 | "children": ["function-6-TupleInt___add__", "function-12-TupleInt___init__"], 840 | "eclass": "UnstableFn_Int_Int-15", 841 | "cost": 1 842 | }, 843 | "function-0-TupleInt___init__": { 844 | "op": "TupleInt(Int(3), ·)", 845 | "children": ["primitive-UnstableFn_Int_Int-15"], 846 | "eclass": "TupleInt-42", 847 | "cost": 3 848 | }, 849 | "function-1-TupleInt___init__": { 850 | "op": "TupleInt(Int(3), lambda idx_fn, i: idx_fn(i + Int(1))(lambda i: i))", 851 | "children": [], 852 | "eclass": "TupleInt-41", 853 | "cost": 5 854 | }, 855 | "function-2-TupleInt___init__": { 856 | "op": "TupleInt(Int(1), ·)", 857 | "children": ["primitive-UnstableFn_Int_Int-14"], 858 | "eclass": "TupleInt-83", 859 | "cost": 3 860 | }, 861 | "primitive-UnstableFn_Int_Int-93": { 862 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))", 863 | "children": ["primitive-UnstableFn_Int_Int-92"], 864 | "eclass": "UnstableFn_Int_Int-93", 865 | "cost": 1 866 | }, 867 | "function-3-TupleInt___init__": { 868 | "op": "TupleInt(Int(1), ·)", 869 | "children": ["primitive-UnstableFn_Int_Int-93"], 870 | "eclass": "TupleInt-103", 871 | "cost": 3 872 | }, 873 | "primitive-UnstableFn_Int_Int-52": { 874 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])", 875 | "children": ["function-7-TupleInt_if_", "function-1-TupleInt_single"], 876 | "eclass": "UnstableFn_Int_Int-52", 877 | "cost": 1 878 | }, 879 | "function-4-TupleInt___init__": { 880 | "op": "TupleInt(Int(1), ·)", 881 | "children": ["primitive-UnstableFn_Int_Int-52"], 882 | "eclass": "TupleInt-84", 883 | "cost": 3 884 | }, 885 | "function-5-TupleInt___init__": { 886 | "op": "TupleInt(Int(1), ·)", 887 | "children": ["primitive-UnstableFn_Int_Int-93"], 888 | "eclass": "TupleInt-236", 889 | "cost": 3 890 | }, 891 | "function-6-TupleInt___init__": { 892 | "op": "TupleInt(Int(1), ·)", 893 | "children": ["primitive-UnstableFn_Int_Int-93"], 894 | "eclass": "TupleInt-278", 895 | "cost": 3 896 | }, 897 | "function-7-TupleInt___init__": { 898 | "op": "TupleInt(Int(1), ·)", 899 | "children": ["primitive-UnstableFn_Int_Int-93"], 900 | "eclass": "TupleInt-336", 901 | "cost": 3 902 | }, 903 | "primitive-UnstableFn_Int_Int-4": { 904 | "op": "lambda f, self, i: f(self[i])", 905 | "children": ["primitive-UnstableFn_Int_Int-2", "function-5-TupleInt___add__"], 906 | "eclass": "UnstableFn_Int_Int-4", 907 | "cost": 1 908 | }, 909 | "function-8-TupleInt___init__": { 910 | "op": "TupleInt(Int(4), ·)", 911 | "children": ["primitive-UnstableFn_Int_Int-4"], 912 | "eclass": "TupleInt-11", 913 | "cost": 3 914 | }, 915 | "primitive-UnstableFn_Int_Int-27": { 916 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])", 917 | "children": ["function-0-TupleInt_if_", "function-12-TupleInt___init__"], 918 | "eclass": "UnstableFn_Int_Int-27", 919 | "cost": 1 920 | }, 921 | "function-9-TupleInt___init__": { 922 | "op": "TupleInt(Int(4), ·)", 923 | "children": ["primitive-UnstableFn_Int_Int-27"], 924 | "eclass": "TupleInt-25", 925 | "cost": 3 926 | }, 927 | "function-10-TupleInt___init__": { 928 | "op": "TupleInt(Int(4), lambda i: i)", 929 | "children": [], 930 | "eclass": "TupleInt-24", 931 | "cost": 4 932 | }, 933 | "primitive-UnstableFn_Int_Int-95": { 934 | "op": "index_vec_int", 935 | "children": ["primitive-Vec_Int-31"], 936 | "eclass": "UnstableFn_Int_Int-95", 937 | "cost": 1 938 | }, 939 | "function-11-TupleInt___init__": { 940 | "op": "TupleInt(Int(4), ·)", 941 | "children": ["primitive-UnstableFn_Int_Int-95"], 942 | "eclass": "TupleInt-13", 943 | "cost": 3 944 | }, 945 | "primitive-UnstableFn_Int_Int-88": { 946 | "op": "lambda i, _: i(Int(4))", 947 | "children": [], 948 | "eclass": "UnstableFn_Int_Int-88", 949 | "cost": 3 950 | }, 951 | "function-12-TupleInt___init__": { 952 | "op": "TupleInt(Int(1), ·)", 953 | "children": ["primitive-UnstableFn_Int_Int-88"], 954 | "eclass": "TupleInt-56", 955 | "cost": 3 956 | }, 957 | "function-13-TupleInt___init__": { 958 | "op": "TupleInt(Int(1), ·)", 959 | "children": ["primitive-UnstableFn_Int_Int-93"], 960 | "eclass": "TupleInt-388", 961 | "cost": 3 962 | }, 963 | "function-14-TupleInt___init__": { 964 | "op": "TupleInt(Int(1), ·)", 965 | "children": ["primitive-UnstableFn_Int_Int-93"], 966 | "eclass": "TupleInt-450", 967 | "cost": 3 968 | }, 969 | "primitive-UnstableFn_Int_Int-35": { 970 | "op": "lambda other, self, i: Int.if_(i < self.length(), self[i], other[i - self.length()])", 971 | "children": ["function-4-TupleInt___init__", "function-12-TupleInt___init__"], 972 | "eclass": "UnstableFn_Int_Int-35", 973 | "cost": 1 974 | }, 975 | "function-15-TupleInt___init__": { 976 | "op": "TupleInt(Int(2), ·)", 977 | "children": ["primitive-UnstableFn_Int_Int-35"], 978 | "eclass": "TupleInt-62", 979 | "cost": 3 980 | }, 981 | "function-16-TupleInt___init__": { 982 | "op": "TupleInt(Int(2), ·)", 983 | "children": ["primitive-UnstableFn_Int_Int-92"], 984 | "eclass": "TupleInt-9", 985 | "cost": 3 986 | }, 987 | "function-17-TupleInt___init__": { 988 | "op": "TupleInt(Int(2), ·)", 989 | "children": ["primitive-UnstableFn_Int_Int-9"], 990 | "eclass": "TupleInt-57", 991 | "cost": 3 992 | }, 993 | "primitive-UnstableFn_Int_Int-3": { 994 | "op": "lambda f, self, i: f(self[i])", 995 | "children": ["primitive-UnstableFn_Int_Int-2", "function-19-TupleInt___init__"], 996 | "eclass": "UnstableFn_Int_Int-3", 997 | "cost": 1 998 | }, 999 | "function-18-TupleInt___init__": { 1000 | "op": "TupleInt(Int(0), ·)", 1001 | "children": ["primitive-UnstableFn_Int_Int-3"], 1002 | "eclass": "TupleInt-19", 1003 | "cost": 3 1004 | }, 1005 | "primitive-UnstableFn_Int_Int-19": { 1006 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))", 1007 | "children": ["primitive-UnstableFn_Int_Int-14"], 1008 | "eclass": "UnstableFn_Int_Int-19", 1009 | "cost": 1 1010 | }, 1011 | "function-19-TupleInt___init__": { 1012 | "op": "TupleInt(Int(0), ·)", 1013 | "children": ["primitive-UnstableFn_Int_Int-19"], 1014 | "eclass": "TupleInt-28", 1015 | "cost": 3 1016 | }, 1017 | "primitive-UnstableFn_Int_Int-94": { 1018 | "op": "lambda idx_fn, i: idx_fn(i + Int(1))", 1019 | "children": ["primitive-UnstableFn_Int_Int-93"], 1020 | "eclass": "UnstableFn_Int_Int-94", 1021 | "cost": 1 1022 | }, 1023 | "function-20-TupleInt___init__": { 1024 | "op": "TupleInt(Int(0), ·)", 1025 | "children": ["primitive-UnstableFn_Int_Int-94"], 1026 | "eclass": "TupleInt-134", 1027 | "cost": 3 1028 | }, 1029 | "function-21-TupleInt___init__": { 1030 | "op": "TupleInt(Int(1), ·)", 1031 | "children": ["primitive-UnstableFn_Int_Int-93"], 1032 | "eclass": "TupleInt-459", 1033 | "cost": 3 1034 | }, 1035 | "function-22-TupleInt___init__": { 1036 | "op": "TupleInt(Int(0), ·)", 1037 | "children": ["primitive-UnstableFn_Int_Int-94"], 1038 | "eclass": "TupleInt-462", 1039 | "cost": 3 1040 | }, 1041 | "function-23-TupleInt___init__": { 1042 | "op": "TupleInt(Int(0), ·)", 1043 | "children": ["primitive-UnstableFn_Int_Int-94"], 1044 | "eclass": "TupleInt-466", 1045 | "cost": 3 1046 | }, 1047 | "function-24-TupleInt___init__": { 1048 | "op": "TupleInt(Int(0), ·)", 1049 | "children": ["primitive-UnstableFn_Int_Int-94"], 1050 | "eclass": "TupleInt-470", 1051 | "cost": 3 1052 | }, 1053 | "function-25-TupleInt___init__": { 1054 | "op": "TupleInt(Int(0), ·)", 1055 | "children": ["primitive-UnstableFn_Int_Int-94"], 1056 | "eclass": "TupleInt-474", 1057 | "cost": 3 1058 | }, 1059 | "function-26-TupleInt___init__": { 1060 | "op": "TupleInt(Int(0), ·)", 1061 | "children": ["primitive-UnstableFn_Int_Int-94"], 1062 | "eclass": "TupleInt-478", 1063 | "cost": 3 1064 | }, 1065 | "function-27-TupleInt___init__": { 1066 | "op": "TupleInt(Int(0), ·)", 1067 | "children": ["primitive-UnstableFn_Int_Int-94"], 1068 | "eclass": "TupleInt-482", 1069 | "cost": 3 1070 | }, 1071 | "function-29-TupleInt___init__": { 1072 | "op": "TupleInt(Int(4), ·)", 1073 | "children": ["primitive-UnstableFn_Int_Int-95"], 1074 | "eclass": "TupleInt-13", 1075 | "cost": 3 1076 | }, 1077 | "function-0-TupleInt_contains": { 1078 | "op": "·.contains(·, Int(4))", 1079 | "children": ["function-16-TupleInt___init__"], 1080 | "eclass": "split-20-function-0-FALSE", 1081 | "cost": 3 1082 | }, 1083 | "function-0-FALSE": { 1084 | "op": "FALSE", 1085 | "children": [], 1086 | "eclass": "Boolean-460", 1087 | "cost": 1 1088 | }, 1089 | "primitive-UnstableFn_Boolean_Int-0": { 1090 | "op": "lambda axis, i: ~axis.contains(i)", 1091 | "children": ["function-16-TupleInt___init__"], 1092 | "eclass": "UnstableFn_Boolean_Int-0", 1093 | "cost": 1 1094 | }, 1095 | "function-0-TupleInt_filter": { 1096 | "op": "·.filter", 1097 | "children": ["function-10-TupleInt___init__", "primitive-UnstableFn_Boolean_Int-0"], 1098 | "eclass": "TupleInt-25", 1099 | "cost": 100 1100 | }, 1101 | "primitive-UnstableFn_Boolean_Int-1": { 1102 | "op": "lambda axis, i: axis.contains(i)", 1103 | "children": ["function-16-TupleInt___init__"], 1104 | "eclass": "UnstableFn_Boolean_Int-1", 1105 | "cost": 1 1106 | }, 1107 | "function-1-TupleInt_filter": { 1108 | "op": "·.filter", 1109 | "children": ["function-0-TupleInt_range", "primitive-UnstableFn_Boolean_Int-1"], 1110 | "eclass": "TupleInt-28", 1111 | "cost": 100 1112 | }, 1113 | "function-2-TupleInt_filter": { 1114 | "op": "·.filter", 1115 | "children": ["function-1-TupleInt___init__", "primitive-UnstableFn_Boolean_Int-0"], 1116 | "eclass": "TupleInt-42", 1117 | "cost": 100 1118 | }, 1119 | "function-5-TupleInt_filter": { 1120 | "op": "·.filter", 1121 | "children": ["function-17-TupleInt___init__", "primitive-UnstableFn_Boolean_Int-0"], 1122 | "eclass": "TupleInt-62", 1123 | "cost": 100 1124 | }, 1125 | "function-6-TupleInt_filter": { 1126 | "op": "·.filter", 1127 | "children": ["function-2-TupleInt___init__", "primitive-UnstableFn_Boolean_Int-0"], 1128 | "eclass": "TupleInt-84", 1129 | "cost": 100 1130 | }, 1131 | "function-12-TupleInt_filter": { 1132 | "op": "·.filter", 1133 | "children": ["function-14-TupleInt_filter", "primitive-UnstableFn_Boolean_Int-0"], 1134 | "eclass": "TupleInt-28", 1135 | "cost": 100 1136 | }, 1137 | "function-13-TupleInt_filter": { 1138 | "op": "·.filter", 1139 | "children": ["function-16-TupleInt_filter", "primitive-UnstableFn_Boolean_Int-1"], 1140 | "eclass": "TupleInt-28", 1141 | "cost": 100 1142 | }, 1143 | "function-14-TupleInt_filter": { 1144 | "op": "·.filter", 1145 | "children": ["function-2-TupleInt___init__", "primitive-UnstableFn_Boolean_Int-1"], 1146 | "eclass": "TupleInt-28", 1147 | "cost": 100 1148 | }, 1149 | "function-15-TupleInt_filter": { 1150 | "op": "·.filter", 1151 | "children": ["function-17-TupleInt___init__", "primitive-UnstableFn_Boolean_Int-1"], 1152 | "eclass": "TupleInt-28", 1153 | "cost": 100 1154 | }, 1155 | "function-16-TupleInt_filter": { 1156 | "op": "·.filter", 1157 | "children": ["function-1-TupleInt___init__", "primitive-UnstableFn_Boolean_Int-1"], 1158 | "eclass": "TupleInt-28", 1159 | "cost": 100 1160 | }, 1161 | "function-1-TRUE": { 1162 | "op": "TRUE", 1163 | "children": [], 1164 | "eclass": "Boolean-297", 1165 | "cost": 1 1166 | }, 1167 | "function-1-Int_if_": { 1168 | "op": "Int.if_(TRUE, Int(4), Int(2))", 1169 | "children": [], 1170 | "eclass": "split-23-function-5-Int___init__", 1171 | "cost": 6 1172 | }, 1173 | "function-2-Int_if_": { 1174 | "op": "Int.if_(TRUE, Int(4), Int(4))", 1175 | "children": [], 1176 | "eclass": "split-24-function-5-Int___init__", 1177 | "cost": 6 1178 | }, 1179 | "function-5-Int_if_": { 1180 | "op": "Int.if_(FALSE, Int(4), Int(4))", 1181 | "children": [], 1182 | "eclass": "split-25-function-5-Int___init__", 1183 | "cost": 6 1184 | }, 1185 | "function-0-Int___lt__": { 1186 | "op": "Int(-1) < Int(1)", 1187 | "children": [], 1188 | "eclass": "split-1-function-1-TRUE", 1189 | "cost": 5 1190 | }, 1191 | "function-3-Int___lt__": { 1192 | "op": "Int(0) < Int(1)", 1193 | "children": [], 1194 | "eclass": "split-2-function-1-TRUE", 1195 | "cost": 5 1196 | }, 1197 | "function-4-Int___lt__": { 1198 | "op": "Int(1) < Int(1)", 1199 | "children": [], 1200 | "eclass": "split-21-function-0-FALSE", 1201 | "cost": 5 1202 | }, 1203 | "function-5-Int___lt__": { 1204 | "op": "Int(2) < Int(1)", 1205 | "children": [], 1206 | "eclass": "split-22-function-0-FALSE", 1207 | "cost": 5 1208 | }, 1209 | "function-4-TupleInt___add__": { 1210 | "op": "· + ·", 1211 | "children": ["function-1-TupleInt_single", "function-5-TupleInt_filter"], 1212 | "eclass": "TupleInt-42", 1213 | "cost": 1 1214 | }, 1215 | "function-5-TupleInt___add__": { 1216 | "op": "· + ·", 1217 | "children": ["function-12-TupleInt___init__", "function-4-TupleInt___add__"], 1218 | "eclass": "TupleInt-25", 1219 | "cost": 1 1220 | }, 1221 | "function-6-TupleInt___add__": { 1222 | "op": "· + ·", 1223 | "children": ["function-1-TupleInt_single", "function-7-TupleInt___add__"], 1224 | "eclass": "TupleInt-62", 1225 | "cost": 1 1226 | }, 1227 | "function-7-TupleInt___add__": { 1228 | "op": "· + ·", 1229 | "children": ["function-12-TupleInt___init__", "function-12-TupleInt_filter"], 1230 | "eclass": "TupleInt-84", 1231 | "cost": 1 1232 | }, 1233 | "split-0-function-0-FALSE": { 1234 | "op": "FALSE", 1235 | "children": [], 1236 | "eclass": "split-0-function-0-FALSE", 1237 | "cost": 1 1238 | }, 1239 | "split-1-function-0-FALSE": { 1240 | "op": "FALSE", 1241 | "children": [], 1242 | "eclass": "split-1-function-0-FALSE", 1243 | "cost": 1 1244 | }, 1245 | "split-2-function-0-FALSE": { 1246 | "op": "FALSE", 1247 | "children": [], 1248 | "eclass": "split-2-function-0-FALSE", 1249 | "cost": 1 1250 | }, 1251 | "split-3-function-0-FALSE": { 1252 | "op": "FALSE", 1253 | "children": [], 1254 | "eclass": "split-3-function-0-FALSE", 1255 | "cost": 1 1256 | }, 1257 | "split-4-function-0-FALSE": { 1258 | "op": "FALSE", 1259 | "children": [], 1260 | "eclass": "split-4-function-0-FALSE", 1261 | "cost": 1 1262 | }, 1263 | "split-5-function-0-FALSE": { 1264 | "op": "FALSE", 1265 | "children": [], 1266 | "eclass": "split-5-function-0-FALSE", 1267 | "cost": 1 1268 | }, 1269 | "split-6-function-0-FALSE": { 1270 | "op": "FALSE", 1271 | "children": [], 1272 | "eclass": "split-6-function-0-FALSE", 1273 | "cost": 1 1274 | }, 1275 | "split-7-function-0-FALSE": { 1276 | "op": "FALSE", 1277 | "children": [], 1278 | "eclass": "split-7-function-0-FALSE", 1279 | "cost": 1 1280 | }, 1281 | "split-8-function-0-FALSE": { 1282 | "op": "FALSE", 1283 | "children": [], 1284 | "eclass": "split-8-function-0-FALSE", 1285 | "cost": 1 1286 | }, 1287 | "split-9-function-0-FALSE": { 1288 | "op": "FALSE", 1289 | "children": [], 1290 | "eclass": "split-9-function-0-FALSE", 1291 | "cost": 1 1292 | }, 1293 | "split-10-function-0-FALSE": { 1294 | "op": "FALSE", 1295 | "children": [], 1296 | "eclass": "split-10-function-0-FALSE", 1297 | "cost": 1 1298 | }, 1299 | "split-11-function-0-FALSE": { 1300 | "op": "FALSE", 1301 | "children": [], 1302 | "eclass": "split-11-function-0-FALSE", 1303 | "cost": 1 1304 | }, 1305 | "split-12-function-0-FALSE": { 1306 | "op": "FALSE", 1307 | "children": [], 1308 | "eclass": "split-12-function-0-FALSE", 1309 | "cost": 1 1310 | }, 1311 | "split-13-function-0-FALSE": { 1312 | "op": "FALSE", 1313 | "children": [], 1314 | "eclass": "split-13-function-0-FALSE", 1315 | "cost": 1 1316 | }, 1317 | "split-14-function-0-FALSE": { 1318 | "op": "FALSE", 1319 | "children": [], 1320 | "eclass": "split-14-function-0-FALSE", 1321 | "cost": 1 1322 | }, 1323 | "split-15-function-0-FALSE": { 1324 | "op": "FALSE", 1325 | "children": [], 1326 | "eclass": "split-15-function-0-FALSE", 1327 | "cost": 1 1328 | }, 1329 | "split-16-function-0-FALSE": { 1330 | "op": "FALSE", 1331 | "children": [], 1332 | "eclass": "split-16-function-0-FALSE", 1333 | "cost": 1 1334 | }, 1335 | "split-17-function-0-FALSE": { 1336 | "op": "FALSE", 1337 | "children": [], 1338 | "eclass": "split-17-function-0-FALSE", 1339 | "cost": 1 1340 | }, 1341 | "split-18-function-0-FALSE": { 1342 | "op": "FALSE", 1343 | "children": [], 1344 | "eclass": "split-18-function-0-FALSE", 1345 | "cost": 1 1346 | }, 1347 | "split-19-function-0-FALSE": { 1348 | "op": "FALSE", 1349 | "children": [], 1350 | "eclass": "split-19-function-0-FALSE", 1351 | "cost": 1 1352 | }, 1353 | "split-20-function-0-FALSE": { 1354 | "op": "FALSE", 1355 | "children": [], 1356 | "eclass": "split-20-function-0-FALSE", 1357 | "cost": 1 1358 | }, 1359 | "split-21-function-0-FALSE": { 1360 | "op": "FALSE", 1361 | "children": [], 1362 | "eclass": "split-21-function-0-FALSE", 1363 | "cost": 1 1364 | }, 1365 | "split-22-function-0-FALSE": { 1366 | "op": "FALSE", 1367 | "children": [], 1368 | "eclass": "split-22-function-0-FALSE", 1369 | "cost": 1 1370 | }, 1371 | "split-0-split-1-function-1-TRUE": { 1372 | "op": "TRUE", 1373 | "children": [], 1374 | "eclass": "split-0-split-1-function-1-TRUE", 1375 | "cost": 1 1376 | }, 1377 | "split-0-primitive-bool-1": { 1378 | "op": "true", 1379 | "children": [], 1380 | "eclass": "split-0-primitive-bool-1", 1381 | "cost": 1 1382 | }, 1383 | "split-0-primitive-bool-0": { 1384 | "op": "false", 1385 | "children": [], 1386 | "eclass": "split-0-primitive-bool-0", 1387 | "cost": 1 1388 | }, 1389 | "split-0-function-7-Int___init__": { 1390 | "op": "Int(-1)", 1391 | "children": [], 1392 | "eclass": "split-0-function-7-Int___init__", 1393 | "cost": 2 1394 | }, 1395 | "split-0-split-5-function-2-Int___init__": { 1396 | "op": "Int(1)", 1397 | "children": [], 1398 | "eclass": "split-0-split-5-function-2-Int___init__", 1399 | "cost": 2 1400 | }, 1401 | "split-0-function-5-Int___init__": { 1402 | "op": "Int(4)", 1403 | "children": [], 1404 | "eclass": "split-0-function-5-Int___init__", 1405 | "cost": 2 1406 | }, 1407 | "split-1-function-5-Int___init__": { 1408 | "op": "Int(4)", 1409 | "children": [], 1410 | "eclass": "split-1-function-5-Int___init__", 1411 | "cost": 2 1412 | }, 1413 | "split-2-function-5-Int___init__": { 1414 | "op": "Int(4)", 1415 | "children": [], 1416 | "eclass": "split-2-function-5-Int___init__", 1417 | "cost": 2 1418 | }, 1419 | "split-3-function-5-Int___init__": { 1420 | "op": "Int(4)", 1421 | "children": [], 1422 | "eclass": "split-3-function-5-Int___init__", 1423 | "cost": 2 1424 | }, 1425 | "split-4-function-5-Int___init__": { 1426 | "op": "Int(4)", 1427 | "children": [], 1428 | "eclass": "split-4-function-5-Int___init__", 1429 | "cost": 2 1430 | }, 1431 | "split-5-function-5-Int___init__": { 1432 | "op": "Int(4)", 1433 | "children": [], 1434 | "eclass": "split-5-function-5-Int___init__", 1435 | "cost": 2 1436 | }, 1437 | "split-6-function-5-Int___init__": { 1438 | "op": "Int(4)", 1439 | "children": [], 1440 | "eclass": "split-6-function-5-Int___init__", 1441 | "cost": 2 1442 | }, 1443 | "split-7-function-5-Int___init__": { 1444 | "op": "Int(4)", 1445 | "children": [], 1446 | "eclass": "split-7-function-5-Int___init__", 1447 | "cost": 2 1448 | }, 1449 | "split-8-function-5-Int___init__": { 1450 | "op": "Int(4)", 1451 | "children": [], 1452 | "eclass": "split-8-function-5-Int___init__", 1453 | "cost": 2 1454 | }, 1455 | "split-9-function-5-Int___init__": { 1456 | "op": "Int(4)", 1457 | "children": [], 1458 | "eclass": "split-9-function-5-Int___init__", 1459 | "cost": 2 1460 | }, 1461 | "split-10-function-5-Int___init__": { 1462 | "op": "Int(4)", 1463 | "children": [], 1464 | "eclass": "split-10-function-5-Int___init__", 1465 | "cost": 2 1466 | }, 1467 | "split-11-function-5-Int___init__": { 1468 | "op": "Int(4)", 1469 | "children": [], 1470 | "eclass": "split-11-function-5-Int___init__", 1471 | "cost": 2 1472 | }, 1473 | "split-12-function-5-Int___init__": { 1474 | "op": "Int(4)", 1475 | "children": [], 1476 | "eclass": "split-12-function-5-Int___init__", 1477 | "cost": 2 1478 | }, 1479 | "split-13-function-5-Int___init__": { 1480 | "op": "Int(4)", 1481 | "children": [], 1482 | "eclass": "split-13-function-5-Int___init__", 1483 | "cost": 2 1484 | }, 1485 | "split-14-function-5-Int___init__": { 1486 | "op": "Int(4)", 1487 | "children": [], 1488 | "eclass": "split-14-function-5-Int___init__", 1489 | "cost": 2 1490 | }, 1491 | "split-15-function-5-Int___init__": { 1492 | "op": "Int(4)", 1493 | "children": [], 1494 | "eclass": "split-15-function-5-Int___init__", 1495 | "cost": 2 1496 | }, 1497 | "split-16-function-5-Int___init__": { 1498 | "op": "Int(4)", 1499 | "children": [], 1500 | "eclass": "split-16-function-5-Int___init__", 1501 | "cost": 2 1502 | }, 1503 | "split-17-function-5-Int___init__": { 1504 | "op": "Int(4)", 1505 | "children": [], 1506 | "eclass": "split-17-function-5-Int___init__", 1507 | "cost": 2 1508 | }, 1509 | "split-18-function-5-Int___init__": { 1510 | "op": "Int(4)", 1511 | "children": [], 1512 | "eclass": "split-18-function-5-Int___init__", 1513 | "cost": 2 1514 | }, 1515 | "split-19-function-5-Int___init__": { 1516 | "op": "Int(4)", 1517 | "children": [], 1518 | "eclass": "split-19-function-5-Int___init__", 1519 | "cost": 2 1520 | }, 1521 | "split-20-function-5-Int___init__": { 1522 | "op": "Int(4)", 1523 | "children": [], 1524 | "eclass": "split-20-function-5-Int___init__", 1525 | "cost": 2 1526 | }, 1527 | "split-21-function-5-Int___init__": { 1528 | "op": "Int(4)", 1529 | "children": [], 1530 | "eclass": "split-21-function-5-Int___init__", 1531 | "cost": 2 1532 | }, 1533 | "split-22-function-5-Int___init__": { 1534 | "op": "Int(4)", 1535 | "children": [], 1536 | "eclass": "split-22-function-5-Int___init__", 1537 | "cost": 2 1538 | }, 1539 | "split-23-function-5-Int___init__": { 1540 | "op": "Int(4)", 1541 | "children": [], 1542 | "eclass": "split-23-function-5-Int___init__", 1543 | "cost": 2 1544 | }, 1545 | "split-24-function-5-Int___init__": { 1546 | "op": "Int(4)", 1547 | "children": [], 1548 | "eclass": "split-24-function-5-Int___init__", 1549 | "cost": 2 1550 | }, 1551 | "split-25-function-5-Int___init__": { 1552 | "op": "Int(4)", 1553 | "children": [], 1554 | "eclass": "split-25-function-5-Int___init__", 1555 | "cost": 2 1556 | }, 1557 | "split-0-split-22-function-5-Int___init__": { 1558 | "op": "Int(4)", 1559 | "children": [], 1560 | "eclass": "split-0-split-22-function-5-Int___init__", 1561 | "cost": 2 1562 | }, 1563 | "split-0-function-9-Int___init__": { 1564 | "op": "Int(2)", 1565 | "children": [], 1566 | "eclass": "split-0-function-9-Int___init__", 1567 | "cost": 2 1568 | }, 1569 | "split-1-function-9-Int___init__": { 1570 | "op": "Int(2)", 1571 | "children": [], 1572 | "eclass": "split-1-function-9-Int___init__", 1573 | "cost": 2 1574 | }, 1575 | "split-2-function-9-Int___init__": { 1576 | "op": "Int(2)", 1577 | "children": [], 1578 | "eclass": "split-2-function-9-Int___init__", 1579 | "cost": 2 1580 | }, 1581 | "split-3-function-9-Int___init__": { 1582 | "op": "Int(2)", 1583 | "children": [], 1584 | "eclass": "split-3-function-9-Int___init__", 1585 | "cost": 2 1586 | }, 1587 | "split-4-function-9-Int___init__": { 1588 | "op": "Int(2)", 1589 | "children": [], 1590 | "eclass": "split-4-function-9-Int___init__", 1591 | "cost": 2 1592 | }, 1593 | "split-5-function-9-Int___init__": { 1594 | "op": "Int(2)", 1595 | "children": [], 1596 | "eclass": "split-5-function-9-Int___init__", 1597 | "cost": 2 1598 | }, 1599 | "split-6-function-9-Int___init__": { 1600 | "op": "Int(2)", 1601 | "children": [], 1602 | "eclass": "split-6-function-9-Int___init__", 1603 | "cost": 2 1604 | }, 1605 | "split-0-split-3-function-9-Int___init__": { 1606 | "op": "Int(2)", 1607 | "children": [], 1608 | "eclass": "split-0-split-3-function-9-Int___init__", 1609 | "cost": 2 1610 | }, 1611 | "split-0-function-1-Int___init__": { 1612 | "op": "Int(3)", 1613 | "children": [], 1614 | "eclass": "split-0-function-1-Int___init__", 1615 | "cost": 2 1616 | }, 1617 | "split-1-function-1-Int___init__": { 1618 | "op": "Int(3)", 1619 | "children": [], 1620 | "eclass": "split-1-function-1-Int___init__", 1621 | "cost": 2 1622 | }, 1623 | "split-0-split-6-function-9-Int___init__": { 1624 | "op": "Int(2)", 1625 | "children": [], 1626 | "eclass": "split-0-split-6-function-9-Int___init__", 1627 | "cost": 2 1628 | }, 1629 | "split-0-function-2-Int___init__": { 1630 | "op": "Int(1)", 1631 | "children": [], 1632 | "eclass": "split-0-function-2-Int___init__", 1633 | "cost": 2 1634 | }, 1635 | "split-1-function-2-Int___init__": { 1636 | "op": "Int(1)", 1637 | "children": [], 1638 | "eclass": "split-1-function-2-Int___init__", 1639 | "cost": 2 1640 | }, 1641 | "split-2-function-2-Int___init__": { 1642 | "op": "Int(1)", 1643 | "children": [], 1644 | "eclass": "split-2-function-2-Int___init__", 1645 | "cost": 2 1646 | }, 1647 | "split-3-function-2-Int___init__": { 1648 | "op": "Int(1)", 1649 | "children": [], 1650 | "eclass": "split-3-function-2-Int___init__", 1651 | "cost": 2 1652 | }, 1653 | "split-4-function-2-Int___init__": { 1654 | "op": "Int(1)", 1655 | "children": [], 1656 | "eclass": "split-4-function-2-Int___init__", 1657 | "cost": 2 1658 | }, 1659 | "split-5-function-2-Int___init__": { 1660 | "op": "Int(1)", 1661 | "children": [], 1662 | "eclass": "split-5-function-2-Int___init__", 1663 | "cost": 2 1664 | }, 1665 | "split-0-split-20-function-5-Int___init__": { 1666 | "op": "Int(4)", 1667 | "children": [], 1668 | "eclass": "split-0-split-20-function-5-Int___init__", 1669 | "cost": 2 1670 | }, 1671 | "split-0-function-10-Int___init__": { 1672 | "op": "Int(0)", 1673 | "children": [], 1674 | "eclass": "split-0-function-10-Int___init__", 1675 | "cost": 2 1676 | }, 1677 | "split-1-function-10-Int___init__": { 1678 | "op": "Int(0)", 1679 | "children": [], 1680 | "eclass": "split-1-function-10-Int___init__", 1681 | "cost": 2 1682 | }, 1683 | "split-2-function-10-Int___init__": { 1684 | "op": "Int(0)", 1685 | "children": [], 1686 | "eclass": "split-2-function-10-Int___init__", 1687 | "cost": 2 1688 | }, 1689 | "split-0-split-19-function-5-Int___init__": { 1690 | "op": "Int(4)", 1691 | "children": [], 1692 | "eclass": "split-0-split-19-function-5-Int___init__", 1693 | "cost": 2 1694 | }, 1695 | "split-0-split-0-function-1-TRUE": { 1696 | "op": "TRUE", 1697 | "children": [], 1698 | "eclass": "split-0-split-0-function-1-TRUE", 1699 | "cost": 1 1700 | }, 1701 | "split-0-split-2-function-1-TRUE": { 1702 | "op": "TRUE", 1703 | "children": [], 1704 | "eclass": "split-0-split-2-function-1-TRUE", 1705 | "cost": 1 1706 | }, 1707 | "split-0-split-22-function-0-FALSE": { 1708 | "op": "FALSE", 1709 | "children": [], 1710 | "eclass": "split-0-split-22-function-0-FALSE", 1711 | "cost": 1 1712 | }, 1713 | "split-0-split-20-function-0-FALSE": { 1714 | "op": "FALSE", 1715 | "children": [], 1716 | "eclass": "split-0-split-20-function-0-FALSE", 1717 | "cost": 1 1718 | }, 1719 | "split-0-split-23-function-5-Int___init__": { 1720 | "op": "Int(4)", 1721 | "children": [], 1722 | "eclass": "split-0-split-23-function-5-Int___init__", 1723 | "cost": 2 1724 | }, 1725 | "split-0-split-21-function-0-FALSE": { 1726 | "op": "FALSE", 1727 | "children": [], 1728 | "eclass": "split-0-split-21-function-0-FALSE", 1729 | "cost": 1 1730 | }, 1731 | "split-0-split-19-function-0-FALSE": { 1732 | "op": "FALSE", 1733 | "children": [], 1734 | "eclass": "split-0-split-19-function-0-FALSE", 1735 | "cost": 1 1736 | }, 1737 | "split-0-function-1-TRUE": { 1738 | "op": "TRUE", 1739 | "children": [], 1740 | "eclass": "split-0-function-1-TRUE", 1741 | "cost": 1 1742 | }, 1743 | "split-1-function-1-TRUE": { 1744 | "op": "TRUE", 1745 | "children": [], 1746 | "eclass": "split-1-function-1-TRUE", 1747 | "cost": 1 1748 | }, 1749 | "split-2-function-1-TRUE": { 1750 | "op": "TRUE", 1751 | "children": [], 1752 | "eclass": "split-2-function-1-TRUE", 1753 | "cost": 1 1754 | }, 1755 | "split-0-split-18-function-0-FALSE": { 1756 | "op": "FALSE", 1757 | "children": [], 1758 | "eclass": "split-0-split-18-function-0-FALSE", 1759 | "cost": 1 1760 | }, 1761 | "split-0-split-5-function-9-Int___init__": { 1762 | "op": "Int(2)", 1763 | "children": [], 1764 | "eclass": "split-0-split-5-function-9-Int___init__", 1765 | "cost": 2 1766 | }, 1767 | "split-0-split-0-function-0-FALSE": { 1768 | "op": "FALSE", 1769 | "children": [], 1770 | "eclass": "split-0-split-0-function-0-FALSE", 1771 | "cost": 1 1772 | }, 1773 | "split-0-split-0-function-5-Int___init__": { 1774 | "op": "Int(4)", 1775 | "children": [], 1776 | "eclass": "split-0-split-0-function-5-Int___init__", 1777 | "cost": 2 1778 | }, 1779 | "split-0-split-0-function-1-Int___init__": { 1780 | "op": "Int(3)", 1781 | "children": [], 1782 | "eclass": "split-0-split-0-function-1-Int___init__", 1783 | "cost": 2 1784 | }, 1785 | "split-0-split-0-function-2-Int___init__": { 1786 | "op": "Int(1)", 1787 | "children": [], 1788 | "eclass": "split-0-split-0-function-2-Int___init__", 1789 | "cost": 2 1790 | }, 1791 | "split-0-split-1-function-1-Int___init__": { 1792 | "op": "Int(3)", 1793 | "children": [], 1794 | "eclass": "split-0-split-1-function-1-Int___init__", 1795 | "cost": 2 1796 | }, 1797 | "split-0-split-1-function-2-Int___init__": { 1798 | "op": "Int(1)", 1799 | "children": [], 1800 | "eclass": "split-0-split-1-function-2-Int___init__", 1801 | "cost": 2 1802 | }, 1803 | "split-0-split-2-function-2-Int___init__": { 1804 | "op": "Int(1)", 1805 | "children": [], 1806 | "eclass": "split-0-split-2-function-2-Int___init__", 1807 | "cost": 2 1808 | }, 1809 | "split-0-split-1-function-5-Int___init__": { 1810 | "op": "Int(4)", 1811 | "children": [], 1812 | "eclass": "split-0-split-1-function-5-Int___init__", 1813 | "cost": 2 1814 | }, 1815 | "split-0-split-2-function-5-Int___init__": { 1816 | "op": "Int(4)", 1817 | "children": [], 1818 | "eclass": "split-0-split-2-function-5-Int___init__", 1819 | "cost": 2 1820 | }, 1821 | "split-0-split-0-function-9-Int___init__": { 1822 | "op": "Int(2)", 1823 | "children": [], 1824 | "eclass": "split-0-split-0-function-9-Int___init__", 1825 | "cost": 2 1826 | }, 1827 | "split-0-split-0-function-10-Int___init__": { 1828 | "op": "Int(0)", 1829 | "children": [], 1830 | "eclass": "split-0-split-0-function-10-Int___init__", 1831 | "cost": 2 1832 | }, 1833 | "split-0-split-3-function-5-Int___init__": { 1834 | "op": "Int(4)", 1835 | "children": [], 1836 | "eclass": "split-0-split-3-function-5-Int___init__", 1837 | "cost": 2 1838 | }, 1839 | "split-0-split-4-function-5-Int___init__": { 1840 | "op": "Int(4)", 1841 | "children": [], 1842 | "eclass": "split-0-split-4-function-5-Int___init__", 1843 | "cost": 2 1844 | }, 1845 | "split-0-split-5-function-5-Int___init__": { 1846 | "op": "Int(4)", 1847 | "children": [], 1848 | "eclass": "split-0-split-5-function-5-Int___init__", 1849 | "cost": 2 1850 | }, 1851 | "split-0-split-6-function-5-Int___init__": { 1852 | "op": "Int(4)", 1853 | "children": [], 1854 | "eclass": "split-0-split-6-function-5-Int___init__", 1855 | "cost": 2 1856 | }, 1857 | "split-0-split-3-function-2-Int___init__": { 1858 | "op": "Int(1)", 1859 | "children": [], 1860 | "eclass": "split-0-split-3-function-2-Int___init__", 1861 | "cost": 2 1862 | }, 1863 | "split-0-split-1-function-10-Int___init__": { 1864 | "op": "Int(0)", 1865 | "children": [], 1866 | "eclass": "split-0-split-1-function-10-Int___init__", 1867 | "cost": 2 1868 | }, 1869 | "split-0-split-1-function-0-FALSE": { 1870 | "op": "FALSE", 1871 | "children": [], 1872 | "eclass": "split-0-split-1-function-0-FALSE", 1873 | "cost": 1 1874 | }, 1875 | "split-0-split-7-function-5-Int___init__": { 1876 | "op": "Int(4)", 1877 | "children": [], 1878 | "eclass": "split-0-split-7-function-5-Int___init__", 1879 | "cost": 2 1880 | }, 1881 | "split-0-split-1-function-9-Int___init__": { 1882 | "op": "Int(2)", 1883 | "children": [], 1884 | "eclass": "split-0-split-1-function-9-Int___init__", 1885 | "cost": 2 1886 | }, 1887 | "split-0-split-4-function-2-Int___init__": { 1888 | "op": "Int(1)", 1889 | "children": [], 1890 | "eclass": "split-0-split-4-function-2-Int___init__", 1891 | "cost": 2 1892 | }, 1893 | "split-0-split-2-function-10-Int___init__": { 1894 | "op": "Int(0)", 1895 | "children": [], 1896 | "eclass": "split-0-split-2-function-10-Int___init__", 1897 | "cost": 2 1898 | }, 1899 | "split-0-split-0-function-7-Int___init__": { 1900 | "op": "Int(-1)", 1901 | "children": [], 1902 | "eclass": "split-0-split-0-function-7-Int___init__", 1903 | "cost": 2 1904 | }, 1905 | "split-0-split-8-function-5-Int___init__": { 1906 | "op": "Int(4)", 1907 | "children": [], 1908 | "eclass": "split-0-split-8-function-5-Int___init__", 1909 | "cost": 2 1910 | }, 1911 | "split-0-split-9-function-5-Int___init__": { 1912 | "op": "Int(4)", 1913 | "children": [], 1914 | "eclass": "split-0-split-9-function-5-Int___init__", 1915 | "cost": 2 1916 | }, 1917 | "split-0-split-10-function-5-Int___init__": { 1918 | "op": "Int(4)", 1919 | "children": [], 1920 | "eclass": "split-0-split-10-function-5-Int___init__", 1921 | "cost": 2 1922 | }, 1923 | "split-0-split-11-function-5-Int___init__": { 1924 | "op": "Int(4)", 1925 | "children": [], 1926 | "eclass": "split-0-split-11-function-5-Int___init__", 1927 | "cost": 2 1928 | }, 1929 | "split-0-split-2-function-0-FALSE": { 1930 | "op": "FALSE", 1931 | "children": [], 1932 | "eclass": "split-0-split-2-function-0-FALSE", 1933 | "cost": 1 1934 | }, 1935 | "split-0-split-3-function-0-FALSE": { 1936 | "op": "FALSE", 1937 | "children": [], 1938 | "eclass": "split-0-split-3-function-0-FALSE", 1939 | "cost": 1 1940 | }, 1941 | "split-0-split-4-function-0-FALSE": { 1942 | "op": "FALSE", 1943 | "children": [], 1944 | "eclass": "split-0-split-4-function-0-FALSE", 1945 | "cost": 1 1946 | }, 1947 | "split-0-split-5-function-0-FALSE": { 1948 | "op": "FALSE", 1949 | "children": [], 1950 | "eclass": "split-0-split-5-function-0-FALSE", 1951 | "cost": 1 1952 | }, 1953 | "split-0-split-6-function-0-FALSE": { 1954 | "op": "FALSE", 1955 | "children": [], 1956 | "eclass": "split-0-split-6-function-0-FALSE", 1957 | "cost": 1 1958 | }, 1959 | "split-0-split-7-function-0-FALSE": { 1960 | "op": "FALSE", 1961 | "children": [], 1962 | "eclass": "split-0-split-7-function-0-FALSE", 1963 | "cost": 1 1964 | }, 1965 | "split-0-split-8-function-0-FALSE": { 1966 | "op": "FALSE", 1967 | "children": [], 1968 | "eclass": "split-0-split-8-function-0-FALSE", 1969 | "cost": 1 1970 | }, 1971 | "split-0-split-9-function-0-FALSE": { 1972 | "op": "FALSE", 1973 | "children": [], 1974 | "eclass": "split-0-split-9-function-0-FALSE", 1975 | "cost": 1 1976 | }, 1977 | "split-0-split-10-function-0-FALSE": { 1978 | "op": "FALSE", 1979 | "children": [], 1980 | "eclass": "split-0-split-10-function-0-FALSE", 1981 | "cost": 1 1982 | }, 1983 | "split-0-split-11-function-0-FALSE": { 1984 | "op": "FALSE", 1985 | "children": [], 1986 | "eclass": "split-0-split-11-function-0-FALSE", 1987 | "cost": 1 1988 | }, 1989 | "split-0-split-12-function-0-FALSE": { 1990 | "op": "FALSE", 1991 | "children": [], 1992 | "eclass": "split-0-split-12-function-0-FALSE", 1993 | "cost": 1 1994 | }, 1995 | "split-0-split-13-function-0-FALSE": { 1996 | "op": "FALSE", 1997 | "children": [], 1998 | "eclass": "split-0-split-13-function-0-FALSE", 1999 | "cost": 1 2000 | }, 2001 | "split-0-split-14-function-0-FALSE": { 2002 | "op": "FALSE", 2003 | "children": [], 2004 | "eclass": "split-0-split-14-function-0-FALSE", 2005 | "cost": 1 2006 | }, 2007 | "split-0-split-15-function-0-FALSE": { 2008 | "op": "FALSE", 2009 | "children": [], 2010 | "eclass": "split-0-split-15-function-0-FALSE", 2011 | "cost": 1 2012 | }, 2013 | "split-0-split-16-function-0-FALSE": { 2014 | "op": "FALSE", 2015 | "children": [], 2016 | "eclass": "split-0-split-16-function-0-FALSE", 2017 | "cost": 1 2018 | }, 2019 | "split-0-split-17-function-0-FALSE": { 2020 | "op": "FALSE", 2021 | "children": [], 2022 | "eclass": "split-0-split-17-function-0-FALSE", 2023 | "cost": 1 2024 | }, 2025 | "split-0-split-2-function-9-Int___init__": { 2026 | "op": "Int(2)", 2027 | "children": [], 2028 | "eclass": "split-0-split-2-function-9-Int___init__", 2029 | "cost": 2 2030 | }, 2031 | "split-0-split-12-function-5-Int___init__": { 2032 | "op": "Int(4)", 2033 | "children": [], 2034 | "eclass": "split-0-split-12-function-5-Int___init__", 2035 | "cost": 2 2036 | }, 2037 | "split-0-split-13-function-5-Int___init__": { 2038 | "op": "Int(4)", 2039 | "children": [], 2040 | "eclass": "split-0-split-13-function-5-Int___init__", 2041 | "cost": 2 2042 | }, 2043 | "split-0-split-14-function-5-Int___init__": { 2044 | "op": "Int(4)", 2045 | "children": [], 2046 | "eclass": "split-0-split-14-function-5-Int___init__", 2047 | "cost": 2 2048 | }, 2049 | "split-0-split-15-function-5-Int___init__": { 2050 | "op": "Int(4)", 2051 | "children": [], 2052 | "eclass": "split-0-split-15-function-5-Int___init__", 2053 | "cost": 2 2054 | }, 2055 | "split-0-split-16-function-5-Int___init__": { 2056 | "op": "Int(4)", 2057 | "children": [], 2058 | "eclass": "split-0-split-16-function-5-Int___init__", 2059 | "cost": 2 2060 | }, 2061 | "split-0-split-17-function-5-Int___init__": { 2062 | "op": "Int(4)", 2063 | "children": [], 2064 | "eclass": "split-0-split-17-function-5-Int___init__", 2065 | "cost": 2 2066 | }, 2067 | "split-0-split-18-function-5-Int___init__": { 2068 | "op": "Int(4)", 2069 | "children": [], 2070 | "eclass": "split-0-split-18-function-5-Int___init__", 2071 | "cost": 2 2072 | } 2073 | }, 2074 | "root_eclasses": [], 2075 | "class_data": { 2076 | "DType-17": { 2077 | "type": "DType" 2078 | }, 2079 | "NDArray-6": { 2080 | "type": "NDArray" 2081 | }, 2082 | "split-0-split-21-function-5-Int___init__": { 2083 | "type": "Int" 2084 | }, 2085 | "Int-12": { 2086 | "type": "Int" 2087 | }, 2088 | "TupleInt-13": { 2089 | "type": "TupleInt" 2090 | }, 2091 | "Int-269": { 2092 | "type": "Int" 2093 | }, 2094 | "Boolean-460": { 2095 | "type": "Boolean" 2096 | }, 2097 | "Int-422": { 2098 | "type": "Int" 2099 | }, 2100 | "Int-227": { 2101 | "type": "Int" 2102 | }, 2103 | "bool-1": { 2104 | "type": "bool" 2105 | }, 2106 | "Boolean-297": { 2107 | "type": "Boolean" 2108 | }, 2109 | "bool-0": { 2110 | "type": "bool" 2111 | }, 2112 | "ShapeAPI-18": { 2113 | "type": "ShapeAPI" 2114 | }, 2115 | "ShapeAPI-14": { 2116 | "type": "ShapeAPI" 2117 | }, 2118 | "TupleInt-9": { 2119 | "type": "TupleInt" 2120 | }, 2121 | "ShapeAPI-15": { 2122 | "type": "ShapeAPI" 2123 | }, 2124 | "TupleInt-11": { 2125 | "type": "TupleInt" 2126 | }, 2127 | "TupleInt-19": { 2128 | "type": "TupleInt" 2129 | }, 2130 | "Int-341": { 2131 | "type": "Int" 2132 | }, 2133 | "Int-299": { 2134 | "type": "Int" 2135 | }, 2136 | "Int-69": { 2137 | "type": "Int" 2138 | }, 2139 | "Int-300": { 2140 | "type": "Int" 2141 | }, 2142 | "Vec_Int-31": { 2143 | "type": "Vec_Int" 2144 | }, 2145 | "Vec_Int-32": { 2146 | "type": "Vec_Int" 2147 | }, 2148 | "TupleInt-42": { 2149 | "type": "TupleInt" 2150 | }, 2151 | "TupleInt-84": { 2152 | "type": "TupleInt" 2153 | }, 2154 | "TupleInt-56": { 2155 | "type": "TupleInt" 2156 | }, 2157 | "TupleInt-25": { 2158 | "type": "TupleInt" 2159 | }, 2160 | "TupleInt-62": { 2161 | "type": "TupleInt" 2162 | }, 2163 | "TupleInt-28": { 2164 | "type": "TupleInt" 2165 | }, 2166 | "UnstableFn_Int_Int-2": { 2167 | "type": "UnstableFn_Int_Int" 2168 | }, 2169 | "TupleInt-24": { 2170 | "type": "TupleInt" 2171 | }, 2172 | "NDArray-10": { 2173 | "type": "NDArray" 2174 | }, 2175 | "split-0-split-24-function-5-Int___init__": { 2176 | "type": "Int" 2177 | }, 2178 | "i64-3": { 2179 | "type": "i64" 2180 | }, 2181 | "i64-1": { 2182 | "type": "i64" 2183 | }, 2184 | "i64-18446744073709551614": { 2185 | "type": "i64" 2186 | }, 2187 | "i64-4": { 2188 | "type": "i64" 2189 | }, 2190 | "i64-18446744073709551615": { 2191 | "type": "i64" 2192 | }, 2193 | "i64-2": { 2194 | "type": "i64" 2195 | }, 2196 | "i64-0": { 2197 | "type": "i64" 2198 | }, 2199 | "UnstableFn_Value_TupleInt-0": { 2200 | "type": "UnstableFn_Value_TupleInt" 2201 | }, 2202 | "UnstableFn_Boolean_Boolean_Int-8": { 2203 | "type": "UnstableFn_Boolean_Boolean_Int" 2204 | }, 2205 | "TupleInt-103": { 2206 | "type": "TupleInt" 2207 | }, 2208 | "TupleInt-134": { 2209 | "type": "TupleInt" 2210 | }, 2211 | "TupleInt-236": { 2212 | "type": "TupleInt" 2213 | }, 2214 | "TupleInt-278": { 2215 | "type": "TupleInt" 2216 | }, 2217 | "TupleInt-336": { 2218 | "type": "TupleInt" 2219 | }, 2220 | "TupleInt-388": { 2221 | "type": "TupleInt" 2222 | }, 2223 | "TupleInt-459": { 2224 | "type": "TupleInt" 2225 | }, 2226 | "TupleInt-462": { 2227 | "type": "TupleInt" 2228 | }, 2229 | "TupleInt-466": { 2230 | "type": "TupleInt" 2231 | }, 2232 | "TupleInt-470": { 2233 | "type": "TupleInt" 2234 | }, 2235 | "TupleInt-474": { 2236 | "type": "TupleInt" 2237 | }, 2238 | "TupleInt-478": { 2239 | "type": "TupleInt" 2240 | }, 2241 | "TupleInt-482": { 2242 | "type": "TupleInt" 2243 | }, 2244 | "TupleInt-450": { 2245 | "type": "TupleInt" 2246 | }, 2247 | "split-0-split-25-function-5-Int___init__": { 2248 | "type": "Int" 2249 | }, 2250 | "split-0-split-4-function-9-Int___init__": { 2251 | "type": "Int" 2252 | }, 2253 | "UnstableFn_Int_Int-9": { 2254 | "type": "UnstableFn_Int_Int" 2255 | }, 2256 | "UnstableFn_Int_Int-14": { 2257 | "type": "UnstableFn_Int_Int" 2258 | }, 2259 | "UnstableFn_Int_Int-92": { 2260 | "type": "UnstableFn_Int_Int" 2261 | }, 2262 | "UnstableFn_Int_Int-15": { 2263 | "type": "UnstableFn_Int_Int" 2264 | }, 2265 | "TupleInt-41": { 2266 | "type": "TupleInt" 2267 | }, 2268 | "TupleInt-83": { 2269 | "type": "TupleInt" 2270 | }, 2271 | "UnstableFn_Int_Int-93": { 2272 | "type": "UnstableFn_Int_Int" 2273 | }, 2274 | "UnstableFn_Int_Int-52": { 2275 | "type": "UnstableFn_Int_Int" 2276 | }, 2277 | "UnstableFn_Int_Int-4": { 2278 | "type": "UnstableFn_Int_Int" 2279 | }, 2280 | "UnstableFn_Int_Int-27": { 2281 | "type": "UnstableFn_Int_Int" 2282 | }, 2283 | "UnstableFn_Int_Int-95": { 2284 | "type": "UnstableFn_Int_Int" 2285 | }, 2286 | "UnstableFn_Int_Int-88": { 2287 | "type": "UnstableFn_Int_Int" 2288 | }, 2289 | "UnstableFn_Int_Int-35": { 2290 | "type": "UnstableFn_Int_Int" 2291 | }, 2292 | "TupleInt-57": { 2293 | "type": "TupleInt" 2294 | }, 2295 | "UnstableFn_Int_Int-3": { 2296 | "type": "UnstableFn_Int_Int" 2297 | }, 2298 | "UnstableFn_Int_Int-19": { 2299 | "type": "UnstableFn_Int_Int" 2300 | }, 2301 | "UnstableFn_Int_Int-94": { 2302 | "type": "UnstableFn_Int_Int" 2303 | }, 2304 | "UnstableFn_Boolean_Int-0": { 2305 | "type": "UnstableFn_Boolean_Int" 2306 | }, 2307 | "UnstableFn_Boolean_Int-1": { 2308 | "type": "UnstableFn_Boolean_Int" 2309 | }, 2310 | "split-0-function-0-FALSE": { 2311 | "type": "Boolean" 2312 | }, 2313 | "split-1-function-0-FALSE": { 2314 | "type": "Boolean" 2315 | }, 2316 | "split-2-function-0-FALSE": { 2317 | "type": "Boolean" 2318 | }, 2319 | "split-3-function-0-FALSE": { 2320 | "type": "Boolean" 2321 | }, 2322 | "split-4-function-0-FALSE": { 2323 | "type": "Boolean" 2324 | }, 2325 | "split-5-function-0-FALSE": { 2326 | "type": "Boolean" 2327 | }, 2328 | "split-6-function-0-FALSE": { 2329 | "type": "Boolean" 2330 | }, 2331 | "split-7-function-0-FALSE": { 2332 | "type": "Boolean" 2333 | }, 2334 | "split-8-function-0-FALSE": { 2335 | "type": "Boolean" 2336 | }, 2337 | "split-9-function-0-FALSE": { 2338 | "type": "Boolean" 2339 | }, 2340 | "split-10-function-0-FALSE": { 2341 | "type": "Boolean" 2342 | }, 2343 | "split-11-function-0-FALSE": { 2344 | "type": "Boolean" 2345 | }, 2346 | "split-12-function-0-FALSE": { 2347 | "type": "Boolean" 2348 | }, 2349 | "split-13-function-0-FALSE": { 2350 | "type": "Boolean" 2351 | }, 2352 | "split-14-function-0-FALSE": { 2353 | "type": "Boolean" 2354 | }, 2355 | "split-15-function-0-FALSE": { 2356 | "type": "Boolean" 2357 | }, 2358 | "split-16-function-0-FALSE": { 2359 | "type": "Boolean" 2360 | }, 2361 | "split-17-function-0-FALSE": { 2362 | "type": "Boolean" 2363 | }, 2364 | "split-18-function-0-FALSE": { 2365 | "type": "Boolean" 2366 | }, 2367 | "split-19-function-0-FALSE": { 2368 | "type": "Boolean" 2369 | }, 2370 | "split-20-function-0-FALSE": { 2371 | "type": "Boolean" 2372 | }, 2373 | "split-21-function-0-FALSE": { 2374 | "type": "Boolean" 2375 | }, 2376 | "split-22-function-0-FALSE": { 2377 | "type": "Boolean" 2378 | }, 2379 | "split-0-split-1-function-1-TRUE": { 2380 | "type": "Boolean" 2381 | }, 2382 | "split-0-primitive-bool-1": { 2383 | "type": "bool" 2384 | }, 2385 | "split-0-primitive-bool-0": { 2386 | "type": "bool" 2387 | }, 2388 | "split-0-function-7-Int___init__": { 2389 | "type": "Int" 2390 | }, 2391 | "split-0-split-5-function-2-Int___init__": { 2392 | "type": "Int" 2393 | }, 2394 | "split-0-function-5-Int___init__": { 2395 | "type": "Int" 2396 | }, 2397 | "split-1-function-5-Int___init__": { 2398 | "type": "Int" 2399 | }, 2400 | "split-2-function-5-Int___init__": { 2401 | "type": "Int" 2402 | }, 2403 | "split-3-function-5-Int___init__": { 2404 | "type": "Int" 2405 | }, 2406 | "split-4-function-5-Int___init__": { 2407 | "type": "Int" 2408 | }, 2409 | "split-5-function-5-Int___init__": { 2410 | "type": "Int" 2411 | }, 2412 | "split-6-function-5-Int___init__": { 2413 | "type": "Int" 2414 | }, 2415 | "split-7-function-5-Int___init__": { 2416 | "type": "Int" 2417 | }, 2418 | "split-8-function-5-Int___init__": { 2419 | "type": "Int" 2420 | }, 2421 | "split-9-function-5-Int___init__": { 2422 | "type": "Int" 2423 | }, 2424 | "split-10-function-5-Int___init__": { 2425 | "type": "Int" 2426 | }, 2427 | "split-11-function-5-Int___init__": { 2428 | "type": "Int" 2429 | }, 2430 | "split-12-function-5-Int___init__": { 2431 | "type": "Int" 2432 | }, 2433 | "split-13-function-5-Int___init__": { 2434 | "type": "Int" 2435 | }, 2436 | "split-14-function-5-Int___init__": { 2437 | "type": "Int" 2438 | }, 2439 | "split-15-function-5-Int___init__": { 2440 | "type": "Int" 2441 | }, 2442 | "split-16-function-5-Int___init__": { 2443 | "type": "Int" 2444 | }, 2445 | "split-17-function-5-Int___init__": { 2446 | "type": "Int" 2447 | }, 2448 | "split-18-function-5-Int___init__": { 2449 | "type": "Int" 2450 | }, 2451 | "split-19-function-5-Int___init__": { 2452 | "type": "Int" 2453 | }, 2454 | "split-20-function-5-Int___init__": { 2455 | "type": "Int" 2456 | }, 2457 | "split-21-function-5-Int___init__": { 2458 | "type": "Int" 2459 | }, 2460 | "split-22-function-5-Int___init__": { 2461 | "type": "Int" 2462 | }, 2463 | "split-23-function-5-Int___init__": { 2464 | "type": "Int" 2465 | }, 2466 | "split-24-function-5-Int___init__": { 2467 | "type": "Int" 2468 | }, 2469 | "split-25-function-5-Int___init__": { 2470 | "type": "Int" 2471 | }, 2472 | "split-0-split-22-function-5-Int___init__": { 2473 | "type": "Int" 2474 | }, 2475 | "split-0-function-9-Int___init__": { 2476 | "type": "Int" 2477 | }, 2478 | "split-1-function-9-Int___init__": { 2479 | "type": "Int" 2480 | }, 2481 | "split-2-function-9-Int___init__": { 2482 | "type": "Int" 2483 | }, 2484 | "split-3-function-9-Int___init__": { 2485 | "type": "Int" 2486 | }, 2487 | "split-4-function-9-Int___init__": { 2488 | "type": "Int" 2489 | }, 2490 | "split-5-function-9-Int___init__": { 2491 | "type": "Int" 2492 | }, 2493 | "split-6-function-9-Int___init__": { 2494 | "type": "Int" 2495 | }, 2496 | "split-0-split-3-function-9-Int___init__": { 2497 | "type": "Int" 2498 | }, 2499 | "split-0-function-1-Int___init__": { 2500 | "type": "Int" 2501 | }, 2502 | "split-1-function-1-Int___init__": { 2503 | "type": "Int" 2504 | }, 2505 | "split-0-split-6-function-9-Int___init__": { 2506 | "type": "Int" 2507 | }, 2508 | "split-0-function-2-Int___init__": { 2509 | "type": "Int" 2510 | }, 2511 | "split-1-function-2-Int___init__": { 2512 | "type": "Int" 2513 | }, 2514 | "split-2-function-2-Int___init__": { 2515 | "type": "Int" 2516 | }, 2517 | "split-3-function-2-Int___init__": { 2518 | "type": "Int" 2519 | }, 2520 | "split-4-function-2-Int___init__": { 2521 | "type": "Int" 2522 | }, 2523 | "split-5-function-2-Int___init__": { 2524 | "type": "Int" 2525 | }, 2526 | "split-0-split-20-function-5-Int___init__": { 2527 | "type": "Int" 2528 | }, 2529 | "split-0-function-10-Int___init__": { 2530 | "type": "Int" 2531 | }, 2532 | "split-1-function-10-Int___init__": { 2533 | "type": "Int" 2534 | }, 2535 | "split-2-function-10-Int___init__": { 2536 | "type": "Int" 2537 | }, 2538 | "split-0-split-19-function-5-Int___init__": { 2539 | "type": "Int" 2540 | }, 2541 | "split-0-split-0-function-1-TRUE": { 2542 | "type": "Boolean" 2543 | }, 2544 | "split-0-split-2-function-1-TRUE": { 2545 | "type": "Boolean" 2546 | }, 2547 | "split-0-split-22-function-0-FALSE": { 2548 | "type": "Boolean" 2549 | }, 2550 | "split-0-split-20-function-0-FALSE": { 2551 | "type": "Boolean" 2552 | }, 2553 | "split-0-split-23-function-5-Int___init__": { 2554 | "type": "Int" 2555 | }, 2556 | "split-0-split-21-function-0-FALSE": { 2557 | "type": "Boolean" 2558 | }, 2559 | "split-0-split-19-function-0-FALSE": { 2560 | "type": "Boolean" 2561 | }, 2562 | "split-0-function-1-TRUE": { 2563 | "type": "Boolean" 2564 | }, 2565 | "split-1-function-1-TRUE": { 2566 | "type": "Boolean" 2567 | }, 2568 | "split-2-function-1-TRUE": { 2569 | "type": "Boolean" 2570 | }, 2571 | "split-0-split-18-function-0-FALSE": { 2572 | "type": "Boolean" 2573 | }, 2574 | "split-0-split-5-function-9-Int___init__": { 2575 | "type": "Int" 2576 | }, 2577 | "split-0-split-0-function-0-FALSE": { 2578 | "type": "Boolean" 2579 | }, 2580 | "split-0-split-0-function-5-Int___init__": { 2581 | "type": "Int" 2582 | }, 2583 | "split-0-split-0-function-1-Int___init__": { 2584 | "type": "Int" 2585 | }, 2586 | "split-0-split-0-function-2-Int___init__": { 2587 | "type": "Int" 2588 | }, 2589 | "split-0-split-1-function-1-Int___init__": { 2590 | "type": "Int" 2591 | }, 2592 | "split-0-split-1-function-2-Int___init__": { 2593 | "type": "Int" 2594 | }, 2595 | "split-0-split-2-function-2-Int___init__": { 2596 | "type": "Int" 2597 | }, 2598 | "split-0-split-1-function-5-Int___init__": { 2599 | "type": "Int" 2600 | }, 2601 | "split-0-split-2-function-5-Int___init__": { 2602 | "type": "Int" 2603 | }, 2604 | "split-0-split-0-function-9-Int___init__": { 2605 | "type": "Int" 2606 | }, 2607 | "split-0-split-0-function-10-Int___init__": { 2608 | "type": "Int" 2609 | }, 2610 | "split-0-split-3-function-5-Int___init__": { 2611 | "type": "Int" 2612 | }, 2613 | "split-0-split-4-function-5-Int___init__": { 2614 | "type": "Int" 2615 | }, 2616 | "split-0-split-5-function-5-Int___init__": { 2617 | "type": "Int" 2618 | }, 2619 | "split-0-split-6-function-5-Int___init__": { 2620 | "type": "Int" 2621 | }, 2622 | "split-0-split-3-function-2-Int___init__": { 2623 | "type": "Int" 2624 | }, 2625 | "split-0-split-1-function-10-Int___init__": { 2626 | "type": "Int" 2627 | }, 2628 | "split-0-split-1-function-0-FALSE": { 2629 | "type": "Boolean" 2630 | }, 2631 | "split-0-split-7-function-5-Int___init__": { 2632 | "type": "Int" 2633 | }, 2634 | "split-0-split-1-function-9-Int___init__": { 2635 | "type": "Int" 2636 | }, 2637 | "split-0-split-4-function-2-Int___init__": { 2638 | "type": "Int" 2639 | }, 2640 | "split-0-split-2-function-10-Int___init__": { 2641 | "type": "Int" 2642 | }, 2643 | "split-0-split-0-function-7-Int___init__": { 2644 | "type": "Int" 2645 | }, 2646 | "split-0-split-8-function-5-Int___init__": { 2647 | "type": "Int" 2648 | }, 2649 | "split-0-split-9-function-5-Int___init__": { 2650 | "type": "Int" 2651 | }, 2652 | "split-0-split-10-function-5-Int___init__": { 2653 | "type": "Int" 2654 | }, 2655 | "split-0-split-11-function-5-Int___init__": { 2656 | "type": "Int" 2657 | }, 2658 | "split-0-split-2-function-0-FALSE": { 2659 | "type": "Boolean" 2660 | }, 2661 | "split-0-split-3-function-0-FALSE": { 2662 | "type": "Boolean" 2663 | }, 2664 | "split-0-split-4-function-0-FALSE": { 2665 | "type": "Boolean" 2666 | }, 2667 | "split-0-split-5-function-0-FALSE": { 2668 | "type": "Boolean" 2669 | }, 2670 | "split-0-split-6-function-0-FALSE": { 2671 | "type": "Boolean" 2672 | }, 2673 | "split-0-split-7-function-0-FALSE": { 2674 | "type": "Boolean" 2675 | }, 2676 | "split-0-split-8-function-0-FALSE": { 2677 | "type": "Boolean" 2678 | }, 2679 | "split-0-split-9-function-0-FALSE": { 2680 | "type": "Boolean" 2681 | }, 2682 | "split-0-split-10-function-0-FALSE": { 2683 | "type": "Boolean" 2684 | }, 2685 | "split-0-split-11-function-0-FALSE": { 2686 | "type": "Boolean" 2687 | }, 2688 | "split-0-split-12-function-0-FALSE": { 2689 | "type": "Boolean" 2690 | }, 2691 | "split-0-split-13-function-0-FALSE": { 2692 | "type": "Boolean" 2693 | }, 2694 | "split-0-split-14-function-0-FALSE": { 2695 | "type": "Boolean" 2696 | }, 2697 | "split-0-split-15-function-0-FALSE": { 2698 | "type": "Boolean" 2699 | }, 2700 | "split-0-split-16-function-0-FALSE": { 2701 | "type": "Boolean" 2702 | }, 2703 | "split-0-split-17-function-0-FALSE": { 2704 | "type": "Boolean" 2705 | }, 2706 | "split-0-split-2-function-9-Int___init__": { 2707 | "type": "Int" 2708 | }, 2709 | "split-0-split-12-function-5-Int___init__": { 2710 | "type": "Int" 2711 | }, 2712 | "split-0-split-13-function-5-Int___init__": { 2713 | "type": "Int" 2714 | }, 2715 | "split-0-split-14-function-5-Int___init__": { 2716 | "type": "Int" 2717 | }, 2718 | "split-0-split-15-function-5-Int___init__": { 2719 | "type": "Int" 2720 | }, 2721 | "split-0-split-16-function-5-Int___init__": { 2722 | "type": "Int" 2723 | }, 2724 | "split-0-split-17-function-5-Int___init__": { 2725 | "type": "Int" 2726 | }, 2727 | "split-0-split-18-function-5-Int___init__": { 2728 | "type": "Int" 2729 | } 2730 | } 2731 | } 2732 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | E-Graph Visualizer 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "egraph-visualizer", 3 | "version": "2.1.2", 4 | "repository": { 5 | "type": "git", 6 | "url": "git+https://github.com/egraphs-good/egraph-visualizer.git" 7 | }, 8 | "type": "module", 9 | "scripts": { 10 | "dev": "vite", 11 | "build": "tsc -b && vite build", 12 | "lint": "eslint .", 13 | "preview": "vite preview" 14 | }, 15 | "dependencies": { 16 | "@anywidget/types": "0.2.0", 17 | "@heroicons/react": "2.1.5", 18 | "@tailwindcss/container-queries": "0.1.1", 19 | "@tanstack/eslint-plugin-query": "5.59.7", 20 | "@tanstack/react-query": "5.59.11", 21 | "@tanstack/react-query-devtools": "5.59.11", 22 | "@xyflow/react": "12.3.2", 23 | "elkjs": "0.9.3", 24 | "monaco-editor": "0.52.0", 25 | "react": "18.3.1", 26 | "react-aria-components": "^1.4.0", 27 | "react-dom": "18.3.1", 28 | "react-monaco-editor": "0.56.2", 29 | "react-stately": "3.33.0", 30 | "tailwind-merge": "^2.5.3", 31 | "tailwindcss-animate": "1.0.7", 32 | "tailwindcss-react-aria-components": "1.1.6", 33 | "vega-scale": "7.4.1" 34 | }, 35 | "devDependencies": { 36 | "@eslint/js": "^9.9.0", 37 | "@types/node": "22.7.5", 38 | "@types/react": "^18.3.11", 39 | "@types/react-dom": "^18.3.1", 40 | "@vitejs/plugin-react": "^4.3.2", 41 | "autoprefixer": "10.4.20", 42 | "eslint": "^9.12.0", 43 | "eslint-plugin-react-hooks": "^5.1.0-rc-fb9a90fa48-20240614", 44 | "eslint-plugin-react-refresh": "^0.4.12", 45 | "globals": "^15.11.0", 46 | "postcss": "8.4.47", 47 | "tailwindcss": "3.4.13", 48 | "tailwindcss-scoped-preflight": "^3.4.5", 49 | "typescript": "^5.6.3", 50 | "typescript-eslint": "^8.8.1", 51 | "vite": "^5.4.8" 52 | }, 53 | "files": [ 54 | "dist/index.js", 55 | "dist/style.css" 56 | ], 57 | "main": "dist/index.js", 58 | "packageManager": "yarn@4.5.0" 59 | } 60 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | 'tailwindcss/nesting': {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | }, 7 | } 8 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from "react"; 2 | import Monaco from "./Monaco"; 3 | import { Visualizer } from "./Visualizer"; 4 | import { defaultCode, defaultExample, fetchExample } from "./examples"; 5 | import { keepPreviousData, useQuery } from "@tanstack/react-query"; 6 | 7 | function App() { 8 | const [example, setExample] = useState(defaultExample); 9 | const exampleQuery = useQuery({ 10 | queryKey: ["example", example], 11 | queryFn: () => fetchExample(example), 12 | staleTime: Infinity, 13 | retry: false, 14 | retryOnMount: false, 15 | placeholderData: keepPreviousData, 16 | }); 17 | const [modifications, setModifications] = useState<{ initial: string; updates: string[] }>({ initial: defaultCode, updates: [] }); 18 | 19 | const data = exampleQuery.data || defaultExample; 20 | const addModification = useCallback( 21 | (change: string) => { 22 | const updates = modifications.initial === data ? modifications.updates : []; 23 | 24 | setModifications({ 25 | initial: data, 26 | updates: [...updates, change], 27 | }); 28 | }, 29 | [data, modifications.initial, modifications.updates] 30 | ); 31 | const egraphs = [data]; 32 | const modificationsUpToDate = modifications.initial === exampleQuery.data; 33 | if (modificationsUpToDate) { 34 | egraphs.push(...modifications.updates); 35 | } 36 | // 37 | return ( 38 | <> 39 |
40 |
41 | 48 |
49 | 50 |
51 | 52 |
53 |
54 | 59 | 60 | ); 61 | } 62 | 63 | export default App; 64 | -------------------------------------------------------------------------------- /src/Loading.tsx: -------------------------------------------------------------------------------- 1 | // https://tailwindflex.com/@prajwal/loading-overlay 2 | export function Loading() { 3 | return ( 4 |
5 |
6 | Loading 7 | 8 | 9 | 14 | 15 |
16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /src/Monaco.tsx: -------------------------------------------------------------------------------- 1 | import { useCallback, useState } from "react"; 2 | import MonacoEditor from "react-monaco-editor"; 3 | import { exampleNames } from "./examples"; 4 | import { UseQueryResult } from "@tanstack/react-query"; 5 | import { Select, SelectListItem, SelectListBox, SelectButton, SelectPopover } from "./react-aria-components-tailwind-starter/src/select"; 6 | import { Key } from "react-aria-components"; 7 | import { Button } from "./react-aria-components-tailwind-starter/src/button"; 8 | import { Loading } from "./Loading"; 9 | 10 | function Monaco({ 11 | exampleQuery, 12 | addModification, 13 | initialCode, 14 | example, 15 | setExample, 16 | }: { 17 | exampleQuery: UseQueryResult; 18 | initialCode: string; 19 | addModification: (code: string) => void; 20 | example: string; 21 | 22 | setExample: (example: string) => void; 23 | }) { 24 | // locally modified code that is only saved when the user clicks "Update" 25 | const [code, setCode] = useState(null); 26 | const handlePresetChange = useCallback( 27 | (preset: Key) => { 28 | setExample(preset as string); 29 | setCode(null); 30 | }, 31 | [setExample, setCode] 32 | ); 33 | 34 | const currentValue = code || initialCode; 35 | 36 | const handleUpdate = useCallback(() => { 37 | addModification(currentValue); 38 | }, [currentValue, addModification]); 39 | 40 | return ( 41 |
42 |
43 | 61 | 64 |
65 | {exampleQuery.isFetching && } 66 | {exampleQuery.status == "error" ? ( 67 |
Error loading example: {exampleQuery.error.message}
68 | ) : ( 69 | {}} 80 | editorDidMount={() => {}} 81 | editorWillUnmount={() => {}} 82 | className={null} 83 | /> 84 | )} 85 |
86 | ); 87 | } 88 | 89 | export default Monaco; 90 | -------------------------------------------------------------------------------- /src/Visualizer.tsx: -------------------------------------------------------------------------------- 1 | import "./index.css"; 2 | import "./react-aria-components-tailwind-starter/src/theme/index.css"; 3 | import "./react-aria-components-tailwind-starter/src/theme/accent-colors.css"; 4 | import "./react-aria-components-tailwind-starter/src/theme/avatar-initial-colors.css"; 5 | import "@xyflow/react/dist/style.css"; 6 | import { 7 | ArrowLongRightIcon, 8 | ArrowUturnRightIcon, 9 | Bars2Icon, 10 | ChevronRightIcon, 11 | ClipboardDocumentListIcon, 12 | CogIcon, 13 | } from "@heroicons/react/24/outline"; 14 | 15 | import type { EdgeChange, EdgeProps, EdgeTypes, NodeChange, NodeProps } from "@xyflow/react"; 16 | 17 | import { createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; 18 | import { 19 | ReactFlow, 20 | ReactFlowProvider, 21 | NodeTypes, 22 | MarkerType, 23 | useNodesInitialized, 24 | useReactFlow, 25 | BaseEdge, 26 | Handle, 27 | Position, 28 | Controls, 29 | Panel, 30 | NodeToolbar, 31 | } from "@xyflow/react"; 32 | 33 | import "@xyflow/react/dist/style.css"; 34 | import { AnyModel } from "@anywidget/types"; 35 | import { createRoot } from "react-dom/client"; 36 | import { AccessibleIcon } from "./react-aria-components-tailwind-starter/src/accessible-icon"; 37 | import { 38 | Menu, 39 | MenuButton, 40 | MenuItem, 41 | MenuItemDescription, 42 | MenuItemLabel, 43 | MenuPopover, 44 | MenuSeparator, 45 | MenuTrigger, 46 | } from "./react-aria-components-tailwind-starter/src/menu"; 47 | import { useCopyToClipboard } from "./react-aria-components-tailwind-starter/src/hooks/use-clipboard"; 48 | import { keepPreviousData, QueryClientProvider, useQuery } from "@tanstack/react-query"; 49 | import { FlowClass, FlowEdge, FlowNode, layoutGraph, PreviousLayout, SelectedNode } from "./layout"; 50 | import { queryClient } from "./queryClient"; 51 | import { Loading } from "./Loading"; 52 | import { Slider, SliderOutput, SliderTack } from "./react-aria-components-tailwind-starter/src/slider"; 53 | 54 | export function EClassNode({ data, selected }: NodeProps) { 55 | return ( 56 |
61 | 62 | 63 | 64 |
65 | ); 66 | } 67 | 68 | export function ENode( 69 | props: Partial< 70 | NodeProps & { 71 | outerRef: React.Ref; 72 | innerRef: React.Ref; 73 | } 74 | > 75 | ) { 76 | const subsumed = props?.data?.subsumed || false; 77 | return ( 78 |
84 | {props?.outerRef ? <> : } 85 | 86 |
91 | {props?.data?.label} 92 |
93 | {/* Only show handle if we aren't rendering this to calculate size */} 94 | {props?.outerRef ? <> : } 95 |
96 | ); 97 | } 98 | 99 | export function MyNodeToolbar(node: { type: "class" | "node"; id: string }) { 100 | const selectNode = useContext(SetSelectedNodeContext); 101 | const onClick = useCallback(() => selectNode!(node), [selectNode, node]); 102 | return ( 103 | 104 | 110 | 111 | ); 112 | } 113 | 114 | export function CustomEdge({ data, ...rest }: EdgeProps) { 115 | const { points } = data!; 116 | const edgePath = points.map(({ x, y }, index) => `${index === 0 ? "M" : "L"} ${x} ${y}`).join(" "); 117 | return ; 118 | } 119 | 120 | const nodeTypes: NodeTypes = { 121 | class: memo(EClassNode), 122 | node: memo(ENode), 123 | }; 124 | 125 | const edgeTypes: EdgeTypes = { 126 | edge: memo(CustomEdge), 127 | }; 128 | 129 | // Context to store a callback to set the node so it can be accessed from the node component 130 | // without having to pass it manually 131 | const SetSelectedNodeContext = createContext void)>(null); 132 | 133 | /// Processes changes for selection, returning a new set if any of the changes are selection changes and they change the set of selections 134 | function processSelectionChanges( 135 | changes: (NodeChange | EdgeChange)[], 136 | currentlySelected: Set 137 | ): Set | null { 138 | let newSelected = null; 139 | for (const change of changes) { 140 | if (change.type !== "select") { 141 | continue; 142 | } 143 | const isSelectedNow = currentlySelected.has(change.id); 144 | if (change.selected) { 145 | if (!isSelectedNow) { 146 | if (!newSelected) { 147 | newSelected = new Set(currentlySelected); 148 | } 149 | newSelected.add(change.id); 150 | } 151 | } else { 152 | if (isSelectedNow) { 153 | if (!newSelected) { 154 | newSelected = new Set(currentlySelected); 155 | } 156 | newSelected.delete(change.id); 157 | } 158 | } 159 | } 160 | return newSelected; 161 | } 162 | 163 | const defaultEdgeOptions = { markerEnd: { type: MarkerType.ArrowClosed, color: "black" } }; 164 | // It seems like it's OK to remove attribution if we aren't making money off our usage 165 | // https://reactflow.dev/learn/troubleshooting/remove-attribution 166 | const proOptions = { hideAttribution: true }; 167 | 168 | /// Component responsible for actually rendeirng the graph after it has been laid out 169 | /// also responsible for 170 | function Rendering({ 171 | nodes: initialNodes, 172 | edges: initialEdges, 173 | selectedNode: filteredNode, 174 | nodeToEdges, 175 | edgeToNodes, 176 | elkJSON, 177 | useInteractiveLayout, 178 | setUseInteractiveLayout, 179 | mergeEdges, 180 | setMergeEdges, 181 | }: { 182 | nodes: (FlowNode | FlowClass)[]; 183 | edges: FlowEdge[]; 184 | selectedNode: SelectedNode | null; 185 | nodeToEdges: Map; 186 | edgeToNodes: Map; 187 | elkJSON: string; 188 | useInteractiveLayout: boolean; 189 | setUseInteractiveLayout: (value: boolean) => void; 190 | mergeEdges: boolean; 191 | setMergeEdges: (value: boolean) => void; 192 | }) { 193 | const [selectedEdges, setSelectedEdges] = useState>(new Set()); 194 | const [selectedNodes, setSelectedNodes] = useState>(new Set()); 195 | 196 | // Trigger this when we want to skip the next fitView, for example when we change selection 197 | const skipNextFitRef = useRef(false); 198 | 199 | const nodes = useMemo( 200 | () => initialNodes.map((node) => ({ ...node, selected: selectedNodes.has(node.id) })), 201 | [initialNodes, selectedNodes] 202 | ); 203 | const edges = useMemo( 204 | () => initialEdges.map((edge) => ({ ...edge, selected: selectedEdges.has(edge.id) })), 205 | [initialEdges, selectedEdges] 206 | ); 207 | 208 | // Handle node/edge selection 209 | const onNodesChange = useCallback( 210 | (changes: NodeChange[]) => { 211 | const newSelectedNodes = processSelectionChanges(changes, selectedNodes); 212 | if (newSelectedNodes) { 213 | const connectedEdges = [...newSelectedNodes].flatMap((node) => nodeToEdges.get(node)!); 214 | setSelectedNodes(newSelectedNodes); 215 | setSelectedEdges(new Set(connectedEdges)); 216 | skipNextFitRef.current = true; 217 | } 218 | }, 219 | [selectedNodes, setSelectedNodes, nodeToEdges, setSelectedEdges] 220 | ); 221 | const onEdgesChange = useCallback( 222 | (changes: EdgeChange[]) => { 223 | const newSelectedEdges = processSelectionChanges(changes, selectedEdges); 224 | if (newSelectedEdges) { 225 | const connectedNodes = [...newSelectedEdges].flatMap((edge) => edgeToNodes.get(edge)!); 226 | setSelectedNodes(new Set(connectedNodes)); 227 | setSelectedEdges(newSelectedEdges); 228 | skipNextFitRef.current = true; 229 | } 230 | }, 231 | [selectedEdges, setSelectedEdges, edgeToNodes, setSelectedNodes] 232 | ); 233 | 234 | const selectNode = useContext(SetSelectedNodeContext)!; 235 | const unselectNode = useCallback(() => selectNode(null), [selectNode]); 236 | 237 | // Re-fit when initial nodes/edges change, but not when selection changes 238 | const reactFlow = useReactFlow(); 239 | const nodeInitialized = useNodesInitialized(); 240 | useEffect(() => { 241 | if (nodeInitialized) { 242 | if (skipNextFitRef.current) { 243 | skipNextFitRef.current = false; 244 | } else { 245 | reactFlow.fitView({ padding: 0.1, duration: 1000 }); 246 | } 247 | } 248 | }, [nodeInitialized, reactFlow, skipNextFitRef]); 249 | 250 | const [isOpen, setOpen] = useState(false); 251 | const clipboard = useCopyToClipboard(); 252 | return ( 253 | 269 | {filteredNode ? ( 270 | 271 | 277 | 278 | ) : ( 279 | <> 280 | )} 281 | 282 | 283 | setOpen((prev) => !prev)} noIndicator variant="plain" isIconOnly> 284 | 285 | 286 | 287 | 288 | 289 | 290 | setUseInteractiveLayout(!useInteractiveLayout), 293 | [setUseInteractiveLayout, useInteractiveLayout] 294 | )} 295 | className="cursor-pointer" 296 | > 297 | {useInteractiveLayout ? : } 298 | Interactive layout 299 | 300 | {useInteractiveLayout ? "Layout independently of previous positions" : "Layout interactively based on previous positions"} 301 | 302 | 303 | setMergeEdges(!mergeEdges), [setMergeEdges, mergeEdges])} className="cursor-pointer"> 304 | {mergeEdges ? : } 305 | Merge edges 306 | {mergeEdges ? "Seperate ports for incoming edges" : "Merge all incoming edges"} 307 | 308 | 309 | clipboard.copy(elkJSON), [elkJSON, clipboard])} className="cursor-pointer"> 310 | 311 | 312 | 313 | Copy ELK 314 | 315 | {clipboard.copied 316 | ? "Copied ELK JSON to clipboard" 317 | : clipboard.error 318 | ? `Failed to copy ELK JSON to clipboard ${clipboard.error.message}` 319 | : "Copy ELK JSON to clipboard"} 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | {/* */} 328 | 329 | {/* Doesn't really show nodes when they are so small */} 330 | {/* */} 331 | 332 | ); 333 | } 334 | function LayoutFlow({ 335 | egraph, 336 | outerElem, 337 | innerElem, 338 | aspectRatio, 339 | firstEgraph, 340 | }: { 341 | egraph: string; 342 | outerElem: HTMLDivElement; 343 | innerElem: HTMLDivElement; 344 | aspectRatio: number; 345 | firstEgraph: string; 346 | }) { 347 | const [useInteractiveLayout, setUseInteractiveLayout] = useState(false); 348 | const [mergeEdges, setMergeEdges] = useState(false); 349 | const previousLayoutRef = useRef(null); 350 | // e-class ID we have currently selected, store the first egraph string as well so we know if this selection is outdated, 351 | // if our whole list of egraphs changes, but keep the selection if we have simply added a new egraph on 352 | const [selectedNodeWithEGraph, setSelectedNodeWithEGraph] = useState<(SelectedNode & { firstEgraph: string }) | null>(null); 353 | const selectedNode = useMemo(() => { 354 | if (selectedNodeWithEGraph && selectedNodeWithEGraph.firstEgraph === firstEgraph) { 355 | return selectedNodeWithEGraph; 356 | } 357 | return null; 358 | }, [selectedNodeWithEGraph, firstEgraph]); 359 | const setSelectedNode = useCallback( 360 | (node: { type: "class" | "node"; id: string } | null) => { 361 | setSelectedNodeWithEGraph(node ? { ...node, firstEgraph } : null); 362 | }, 363 | [setSelectedNodeWithEGraph, firstEgraph] 364 | ); 365 | 366 | const getNodeSize = useCallback( 367 | (contents: string) => { 368 | innerElem.innerText = contents; 369 | return outerElem.getBoundingClientRect(); 370 | }, 371 | [outerElem, innerElem] 372 | ); 373 | const previousLayout = useInteractiveLayout ? previousLayoutRef.current : null; 374 | const layoutQuery = useQuery({ 375 | queryKey: ["layout", egraph, getNodeSize, aspectRatio, selectedNode, previousLayout, mergeEdges], 376 | networkMode: "always", 377 | queryFn: ({ signal }) => layoutGraph(egraph, getNodeSize, aspectRatio, selectedNode, previousLayout, mergeEdges, signal), 378 | staleTime: Infinity, 379 | retry: false, 380 | retryOnMount: false, 381 | placeholderData: keepPreviousData, 382 | }); 383 | useEffect(() => { 384 | if (layoutQuery.status === "success") { 385 | previousLayoutRef.current = layoutQuery.data.layout; 386 | } 387 | }, [layoutQuery.status, layoutQuery.data]); 388 | 389 | if (layoutQuery.isError) { 390 | return
Error: {layoutQuery.error.message}
; 391 | } 392 | if (layoutQuery.isPending) { 393 | return ; 394 | } 395 | 396 | const { nodes, edges, elkJSON, nodeToEdges, edgeToNodes } = layoutQuery.data; 397 | 398 | return ( 399 | <> 400 | {layoutQuery.isFetching ? : <>} 401 | 402 | 403 | 415 | 416 | 417 | 418 | ); 419 | } 420 | 421 | function SelectSider({ length, onSelect, selected }: { length: number; onSelect: (index: number) => void; selected: number }) { 422 | return ( 423 |
1 ? "" : "opacity-0"}`}> 424 | 431 |
432 |
433 | 434 | {({ state }) => { 435 | return ( 436 | 437 | {state.getThumbValueLabel(0)} / {length - 1} 438 | 439 | ); 440 | }} 441 | 442 |
443 | 444 |
445 |
446 |
447 |
448 |
449 | ); 450 | } 451 | 452 | export function Visualizer({ egraphs, height = null, resize = false }: { egraphs: string[]; height?: string | null; resize?: boolean }) { 453 | const [rootElem, setRootElem] = useState(null); 454 | 455 | const [outerElem, setOuterElem] = useState(null); 456 | const [innerElem, setInnerElem] = useState(null); 457 | const aspectRatio = rootElem ? rootElem.clientWidth / rootElem.clientHeight : null; 458 | 459 | // If we are at null, then use the last item in the list 460 | // if the last selection was for a list of egraphs that no longer exists, then use the last item in the list 461 | const [selected, setSelected] = useState(null); 462 | const actualSelected = selected && selected.egraphs === egraphs ? selected.index : egraphs.length - 1; 463 | const onSelect = useCallback( 464 | (index: number) => { 465 | setSelected({ egraphs, index }); 466 | }, 467 | [setSelected, egraphs] 468 | ); 469 | 470 | return ( 471 |
472 | {/* Hidden node to measure text size */} 473 |
474 | 475 |
476 | 477 | {outerElem && innerElem && aspectRatio && ( 478 | 485 | )} 486 |
487 | ); 488 | } 489 | 490 | // Put these both in one file, so its emitted as a single chunk and anywidget doesn't have to import another file 491 | 492 | /// Render anywidget model to the given element 493 | // Must be named `render` to work as an anywidget module 494 | // https://anywidget.dev/en/afm/#lifecycle-methods 495 | // eslint-disable-next-line react-refresh/only-export-components 496 | export function render({ model, el }: { el: HTMLElement; model: AnyModel }) { 497 | // only render once with data, dont support updating widget yet 498 | const root = createRoot(el); 499 | // let callback: () => void; 500 | // const registerChangeEGraph = (setEgraph: (egraph: string) => void) => { 501 | // callback = () => setEgraph(model.get("egraph")); 502 | // model.on("change:egraph", callback); 503 | // }; 504 | root.render( 505 | 506 | 507 | 508 | ); 509 | 510 | return () => { 511 | // model.off("change:egraph", callback); 512 | root.unmount(); 513 | }; 514 | } 515 | 516 | /// Mount the visualizer to the given element 517 | /// Call `render` to render a new list of egraphs 518 | /// Call `unmount` to unmount the visualizer 519 | // eslint-disable-next-line react-refresh/only-export-components 520 | export function mount(element: HTMLElement): { render: (egraphs: string[]) => void; unmount: () => void } { 521 | const root = createRoot(element); 522 | function render(egraphs: string[]) { 523 | root.render( 524 | 525 | 526 | 527 | ); 528 | } 529 | 530 | function unmount() { 531 | root.unmount(); 532 | } 533 | return { render, unmount }; 534 | } 535 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/examples.ts: -------------------------------------------------------------------------------- 1 | const examples = { 2 | ...import.meta.glob("/examples/manual/*.json", { query: "?raw" }), 3 | ...import.meta.glob("/examples/egraph-serialize/tests/*.json", { query: "?raw" }), 4 | ...import.meta.glob("/examples/extraction-gym/data/*/*.json", { query: "?raw" }), 5 | }; 6 | 7 | export const defaultExample = "/examples/manual/homepage.json"; 8 | import DefaultCode from "/examples/manual/homepage.json?raw"; 9 | export const defaultCode = DefaultCode; 10 | 11 | export const exampleNames = Object.keys(examples); 12 | 13 | export async function fetchExample(name: string) { 14 | return ((await examples[name]()) as { default: string }).default; 15 | } 16 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | .react-flow__node { 2 | z-index: -1 !important; 3 | transition: transform 1s ease; 4 | } 5 | -------------------------------------------------------------------------------- /src/layout.ts: -------------------------------------------------------------------------------- 1 | import { scheme } from "vega-scale"; 2 | import ELK, { ElkExtendedEdge, ElkNode } from "elkjs/lib/elk-api"; 3 | 4 | import { Node, Edge } from "@xyflow/react"; 5 | // Make worker inline because if its external cannot be loaded from esm.sh due to CORS 6 | import ELKWorker from "elkjs/lib/elk-worker?worker&inline"; 7 | 8 | // Elk has a *huge* amount of options to configure. To see everything you can 9 | // tweak check out: 10 | // 11 | // - https://www.eclipse.org/elk/reference/algorithms.html 12 | // - https://www.eclipse.org/elk/reference/options.html 13 | 14 | const rootLayoutOptions = { 15 | "elk.algorithm": "layered", 16 | "elk.direction": "DOWN", 17 | // This seems to result in a more compact layout 18 | // disable to stop stack size error 19 | // https://github.com/kieler/elkjs/issues/314 20 | // "elk.layered.nodePlacement.strategy": "NETWORK_SIMPLEX", 21 | "elk.layered.mergeEdges": "true", 22 | 23 | // Can you use spline routing instead which generates non orthogonal edges 24 | // "elk.edgeRouting": "SPLINES", 25 | // "elk.layered.edgeRouting.splines.mode": "CONSERVATIVE", 26 | }; 27 | 28 | // the number of pixels of padding between nodes and between nodes and their parents 29 | const nodePadding = 5; 30 | 31 | const classLayoutOptions = { 32 | "elk.algorithm": "layered", 33 | "elk.direction": "DOWN", 34 | "elk.spacing.componentComponent": nodePadding.toString(), 35 | "elk.spacing.nodeNode": nodePadding.toString(), 36 | "elk.padding": `[top=${nodePadding},left=${nodePadding},bottom=${nodePadding},right=${nodePadding}]`, 37 | "elk.spacing.portPort": "0", 38 | // allow ports on e-class to be anywhere 39 | // TODO: they only seem to appear on top side of nodes, figure out if there is a way to allow them 40 | // to be on all sides if it would result in a better layout 41 | portConstraints: "FREE", 42 | }; 43 | 44 | // https://github.com/eclipse/elk/issues/1037#issuecomment-2122136560 45 | const interactiveOptions = { 46 | "elk.layered.cycleBreaking.strategy": "INTERACTIVE", 47 | "elk.layered.layering.strategy": "INTERACTIVE", 48 | "elk.layered.nodePlacement.strategy": "INTERACTIVE", 49 | // Had to disable or leads to weird edges 50 | // "elk.layered.crossingMinimization.semiInteractive": "true", 51 | // "elk.layered.crossingMinimization.strategy": "INTERACTIVE", 52 | }; 53 | 54 | const nodeLayoutOptions = { 55 | portConstraints: "FIXED_ORDER", 56 | }; 57 | 58 | type EGraphNodeID = string; 59 | type EGraphClassID = string; 60 | type EGraphNode = { 61 | op: string; 62 | children?: EGraphNodeID[]; 63 | eclass: EGraphClassID; 64 | cost: number; 65 | subsumed?: boolean; 66 | }; 67 | 68 | type EGraphClassData = { 69 | type?: string; 70 | }; 71 | type EGraph = { 72 | nodes: { [id: EGraphNodeID]: EGraphNode }; 73 | root_eclasses?: EGraphClassID[]; 74 | class_data?: { [id: EGraphClassID]: EGraphClassData }; 75 | }; 76 | 77 | type Color = string; 78 | // Use these color schemes for the nodes 79 | // https://vega.github.io/vega/docs/schemes/#categorical 80 | const colorScheme: Color[] = [...scheme("pastel1"), ...scheme("pastel2")]; 81 | 82 | export type FlowClass = Node< 83 | { 84 | color: string | null; 85 | id: string; 86 | // selected?: boolean 87 | }, 88 | "class" 89 | >; 90 | export type FlowNode = Node< 91 | { 92 | label: string; 93 | id: string; 94 | subsumed?: boolean; 95 | // selected?: boolean 96 | }, 97 | "node" 98 | >; 99 | export type FlowEdge = Edge<{ points: { x: number; y: number }[] }, "edge">; 100 | 101 | type MyELKEdge = ElkExtendedEdge & { sourceNode: string; targetNode: string; edgeID: string }; 102 | /// ELK Node but with additional data added to be later used when converting to react flow nodes 103 | type MyELKNode = Omit & { 104 | edges: MyELKEdge[]; 105 | children: ({ 106 | data: FlowClass["data"]; 107 | // Edges from e-node to it's own class must be in sub-graph 108 | edges: MyELKEdge[]; 109 | children: ({ 110 | width: number; 111 | height: number; 112 | data: FlowNode["data"]; 113 | } & ElkNode)[]; 114 | } & Omit)[]; 115 | }; 116 | 117 | /// ELK node but with layout information added 118 | type MyELKNodeLayedOut = Omit & { 119 | children: (Omit & { 120 | x: number; 121 | y: number; 122 | width: number; 123 | height: number; 124 | children: (Omit & { 125 | x: number; 126 | y: number; 127 | })[]; 128 | })[]; 129 | }; 130 | 131 | // Mapping of class to color, where undefined class mapps to null 132 | type Colors = Map; 133 | 134 | export type PreviousLayout = { layout: MyELKNodeLayedOut; colors: Colors }; 135 | export type SelectedNode = { type: "class" | "node"; id: string }; 136 | 137 | /** 138 | * Transform a JSON egraph into the laid out nodes. 139 | * 140 | * Also emits the ELK JSON before layout for debugging, and the internal layout details so that it can use the previous one if needed 141 | */ 142 | export async function layoutGraph( 143 | egraph: string, 144 | getNodeSize: (contents: string) => { width: number; height: number }, 145 | aspectRatio: number, 146 | selectedNode: SelectedNode | null, 147 | previousLayout: PreviousLayout | null, 148 | mergeEdges: boolean, 149 | signal: AbortSignal 150 | ): Promise<{ 151 | nodes: (FlowNode | FlowClass)[]; 152 | edges: FlowEdge[]; 153 | edgeToNodes: Map; 154 | nodeToEdges: Map; 155 | elkJSON: string; 156 | layout: PreviousLayout; 157 | }> { 158 | const parsedEGraph = JSON.parse(egraph); 159 | const { elkNode, colors } = toELKNode(parsedEGraph, getNodeSize, selectedNode, aspectRatio, previousLayout, mergeEdges); 160 | const elkJSON = JSON.stringify(elkNode, null, 2); 161 | const layout = (await layoutWithCancel(elkNode, signal)) as MyELKNodeLayedOut; 162 | const edges = toFlowEdges(layout); 163 | const nodes = toFlowNodes(layout); 164 | const nodeToEdges = new Map( 165 | [...Object.entries(Object.groupBy(edges, (edge) => edge.source)), ...Object.entries(Object.groupBy(edges, (edge) => edge.target))].map( 166 | ([nodeID, edges]) => [nodeID, (edges || []).map((edge) => edge.id)] 167 | ) 168 | ); 169 | const edgeToNodes = new Map(edges.map((edge) => [edge.id, [edge.source, edge.target]])); 170 | return { 171 | layout: { layout, colors }, 172 | elkJSON, 173 | nodes, 174 | edges, 175 | edgeToNodes, 176 | nodeToEdges, 177 | }; 178 | } 179 | 180 | // We wil convert this to a graph where the id of the nodes are class-{class_id} and node-{node_id} 181 | // the ID of the edges will be edge-{source_id}-{port-index} and the ports will be port-{source_id}-{port-index} 182 | function toELKNode( 183 | egraph: EGraph, 184 | getNodeSize: (contents: string) => { width: number; height: number }, 185 | selectedNode: SelectedNode | null, 186 | aspectRatio: number, 187 | previousLayout: PreviousLayout | null, 188 | mergeEdges: boolean 189 | ): { elkNode: MyELKNode; colors: Colors } { 190 | const nodeToClass = new Map(); 191 | const classToNodes = new Map(); 192 | for (const [id, node] of Object.entries(egraph.nodes)) { 193 | nodeToClass.set(id, node.eclass); 194 | if (!classToNodes.has(node.eclass)) { 195 | classToNodes.set(node.eclass, []); 196 | } 197 | classToNodes.get(node.eclass)!.push([id, node]); 198 | } 199 | /// filter out to descendants of the selected node 200 | if (selectedNode) { 201 | const toTraverse = new Set(); 202 | if (selectedNode.type === "class") { 203 | toTraverse.add(selectedNode.id); 204 | } else { 205 | const classID = nodeToClass.get(selectedNode.id)!; 206 | toTraverse.add(classID); 207 | // if we have selected a node, change the e-class to only include the selected node 208 | classToNodes.set(classID, [[selectedNode.id, egraph.nodes[selectedNode.id]]]); 209 | } 210 | const traversed = new Set(); 211 | while (toTraverse.size > 0) { 212 | const current: string = toTraverse.values().next().value!; 213 | toTraverse.delete(current); 214 | traversed.add(current); 215 | for (const childNode of classToNodes.get(current)!.flatMap(([, node]) => node.children || [])) { 216 | const childClass = egraph.nodes[childNode].eclass; 217 | if (!traversed.has(childClass)) { 218 | toTraverse.add(childClass); 219 | } 220 | } 221 | } 222 | for (const id of classToNodes.keys()) { 223 | if (!traversed.has(id)) { 224 | classToNodes.delete(id); 225 | } 226 | } 227 | } 228 | 229 | const incomingEdges = new Map(); 230 | // use classToNodes instead of egraph.nodes since it's already filtered and we dont want to create 231 | // export ports for nodes that are not in the graph 232 | for (const [nodeID, node] of [...classToNodes.values()].flatMap((nodes) => nodes)) { 233 | for (const [index, child] of (node.children || []).entries()) { 234 | const childClass = nodeToClass.get(child)!; 235 | if (!incomingEdges.has(childClass)) { 236 | incomingEdges.set(childClass, []); 237 | } 238 | incomingEdges.get(childClass)!.push({ nodeID, index }); 239 | } 240 | } 241 | 242 | const class_data = egraph.class_data || {}; 243 | // Sort types so that the colors are consistent 244 | const sortedTypes = [ 245 | ...new Set( 246 | Object.values(class_data) 247 | .map(({ type }) => type) 248 | .filter((type) => type) 249 | ), 250 | ].sort(); 251 | const availableColors = [...colorScheme]; 252 | const colors = new Map([[undefined, null]]) as Map; 253 | // Start colors with those in previous layout if found 254 | if (previousLayout) { 255 | for (const [type, color] of previousLayout.colors.entries()) { 256 | if (sortedTypes.includes(type) && color) { 257 | colors.set(type, color); 258 | // remove from available colors 259 | availableColors.splice(availableColors.indexOf(color), 1); 260 | sortedTypes.splice(sortedTypes.indexOf(type), 1); 261 | } 262 | } 263 | } 264 | for (const [index, type] of sortedTypes.entries()) { 265 | colors.set(type, availableColors[index % availableColors.length]); 266 | } 267 | 268 | const elkRoot: MyELKNode = { 269 | id: "--eclipse-layout-kernel-root", 270 | layoutOptions: rootLayoutOptions, 271 | children: [], 272 | edges: [], 273 | }; 274 | // aspectRatio must be number for it to work 275 | elkRoot.layoutOptions!["elk.aspectRatio"] = aspectRatio as unknown as string; 276 | for (const [classID, nodes] of classToNodes.entries()) { 277 | const elkClassID = `class-${classID}`; 278 | const elkClass: MyELKNode["children"][0] = { 279 | id: elkClassID, 280 | data: { color: colors.get(class_data[classID]?.type)!, id: classID }, 281 | layoutOptions: classLayoutOptions, 282 | children: [], 283 | ports: mergeEdges 284 | ? [] 285 | : (incomingEdges.get(classID) || []).map(({ nodeID, index }) => ({ 286 | id: `port-class-incoming-${nodeID}-${index}`, 287 | })), 288 | 289 | edges: [], 290 | }; 291 | elkRoot.children.push(elkClass); 292 | for (const [nodeID, node] of nodes) { 293 | const size = getNodeSize(node.op); 294 | const elkNodeID = `node-${nodeID}`; 295 | const elkNode: MyELKNode["children"][0]["children"][0] = { 296 | id: elkNodeID, 297 | data: { label: node.op, id: nodeID, ...(node.subsumed ? { subsumed: true } : {}) }, 298 | width: size.width, 299 | height: size.height, 300 | ports: [], 301 | labels: [{ text: node.op }], 302 | layoutOptions: nodeLayoutOptions, 303 | }; 304 | elkClass.children.push(elkNode); 305 | const nPorts = Object.keys(node.children || []).length; 306 | for (const [index, child] of (node.children || []).entries()) { 307 | const edgeID = `${nodeID}-${index}`; 308 | 309 | // In order to get the layout we want, we don't set `"elk.hierarchyHandling": "INCLUDE_CHILDREN"` 310 | // and instead have seperate layouts per e-class and globally. This means we need to make sure no edges 311 | // exit an e-node without going through a port on the e-class. 312 | 313 | // Two edges are created 314 | /// [edge-inner]: [port-node] ---> [port-class-outgoing] on this class 315 | /// [edge-outer]: [port-class-outgoing] on this class ---> [port-class-incoming] on target class 316 | 317 | // IDs for ports and edges are the [name]-[node ID]-[output index] 318 | // The [port-class-incoming] are already added, so we just need to add two edges and the other two ports 319 | 320 | // see https://github.com/eclipse/elk/issues/1068 for more details 321 | 322 | const elkTargetClassID = `class-${nodeToClass.get(child)!}`; 323 | const elkNodePortID = `port-node-${edgeID}`; 324 | const elkClassIncomingPortID = `port-class-incoming-${edgeID}`; 325 | const elkClassOutgoingPortID = `port-class-outgoing-${edgeID}`; 326 | const elkInnerEdgeID = `edge-inner-${edgeID}`; 327 | const elkOuterEdgeID = `edge-outer-${edgeID}`; 328 | 329 | elkNode.ports!.push({ 330 | id: elkNodePortID, 331 | layoutOptions: { 332 | "port.side": "SOUTH", 333 | /// index is clockwise from top right, so we need to the reverse index, so that first port is on the left 334 | "port.index": (nPorts - index - 1).toString(), 335 | }, 336 | }); 337 | elkClass.ports!.push({ id: elkClassOutgoingPortID }); 338 | elkClass.edges!.push({ 339 | id: elkInnerEdgeID, 340 | edgeID, 341 | sourceNode: elkNodeID, 342 | targetNode: elkTargetClassID, 343 | sources: [elkNodePortID], 344 | targets: [elkClassOutgoingPortID], 345 | }); 346 | elkRoot.edges!.push({ 347 | id: elkOuterEdgeID, 348 | edgeID, 349 | sourceNode: elkNodeID, 350 | targetNode: elkTargetClassID, 351 | sources: [elkClassOutgoingPortID], 352 | targets: [mergeEdges ? elkTargetClassID : elkClassIncomingPortID], 353 | }); 354 | } 355 | } 356 | } 357 | if (previousLayout) { 358 | const layout = previousLayout.layout; 359 | const previousLayoutClassIDs = new Set(layout.children.map(({ data }) => data.id)); 360 | const overlappingClasses = Object.groupBy( 361 | elkRoot.children, 362 | ({ data }) => previousLayoutClassIDs.has(data.id).toString() as "true" | "false" 363 | ); 364 | // Use interactive layout if more than half the classes already have positions as a heuristic 365 | if ((overlappingClasses.false || []).length > (overlappingClasses.true || []).length) { 366 | return { elkNode: elkRoot, colors }; 367 | } 368 | // We have some children that were already layed out. So let's update all layout options to be interactive 369 | // and preserve the positions of the nodes that were already layed out 370 | elkRoot.layoutOptions = { ...elkRoot.layoutOptions, ...interactiveOptions }; 371 | for (const elkClass of elkRoot.children) { 372 | const previousClass = layout.children.find(({ id }) => id === elkClass.id); 373 | if (!previousClass) { 374 | continue; 375 | } 376 | elkClass.layoutOptions = { ...elkClass.layoutOptions, ...interactiveOptions }; 377 | elkClass.x = previousClass.x; 378 | elkClass.y = previousClass.y; 379 | for (const elkCLassPort of elkClass.ports || []) { 380 | const previousPort = (previousClass.ports || []).find(({ id }) => id === elkCLassPort.id); 381 | if (!previousPort) { 382 | continue; 383 | } 384 | elkCLassPort.x = previousPort.x; 385 | elkCLassPort.y = previousPort.y; 386 | } 387 | 388 | for (const elkNode of elkClass.children) { 389 | const previousNode = previousClass.children.find(({ id }) => id === elkNode.id); 390 | if (!previousNode) { 391 | continue; 392 | } 393 | for (const elkNodePort of elkNode.ports || []) { 394 | const previousPort = (previousNode.ports || []).find(({ id }) => id === elkNodePort.id); 395 | if (!previousPort) { 396 | continue; 397 | } 398 | elkNodePort.x = previousPort.x; 399 | elkNodePort.y = previousPort.y; 400 | } 401 | 402 | elkNode.x = previousNode.x; 403 | elkNode.y = previousNode.y; 404 | } 405 | } 406 | } 407 | 408 | return { elkNode: elkRoot, colors }; 409 | } 410 | 411 | /** 412 | * Run an ELK layout that terminates if the signal is aborted. 413 | * 414 | * https://github.com/kieler/elkjs/issues/208#issuecomment-2407847314 415 | */ 416 | function layoutWithCancel(graph: ElkNode, signal: AbortSignal): Promise { 417 | return new Promise((resolve, reject) => { 418 | // https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal#implementing_an_abortable_api 419 | if (signal.aborted) { 420 | reject(signal.reason); 421 | } 422 | const elk = new ELK({ 423 | workerFactory: () => new ELKWorker(), 424 | workerUrl: "", 425 | }); 426 | signal.addEventListener("abort", () => { 427 | elk.terminateWorker(); 428 | reject(signal.reason); 429 | }); 430 | elk.layout(graph).then(resolve, reject); 431 | }); 432 | } 433 | 434 | // This function takes an EGraph and returns an ELK node that can be used to layout the graph. 435 | function toFlowNodes(layout: MyELKNodeLayedOut): (FlowClass | FlowNode)[] { 436 | return layout.children.flatMap(({ children, x, y, data, id: parentId, height, width }) => [ 437 | { position: { x, y }, data, id: parentId, type: "class" as const, height, width }, 438 | ...children!.map(({ x, y, height, width, data, id }) => ({ 439 | data, 440 | id, 441 | type: "node" as const, 442 | parentId, 443 | position: { x, y }, 444 | width, 445 | height, 446 | })), 447 | ]); 448 | } 449 | 450 | function toFlowEdges(layout: MyELKNodeLayedOut): FlowEdge[] { 451 | const outerEdges = Object.fromEntries(layout.edges!.map(({ edgeID, sections }) => [edgeID, sections![0]])); 452 | return layout.children.flatMap(({ x: parentX, y: parentY, edges }) => 453 | edges!.map(({ edgeID, sections, sourceNode, targetNode }) => { 454 | const [section] = sections!; 455 | const outerEdge = outerEdges[edgeID]; 456 | // Add container start to edge so that this is correct for edges nested in parents which are needed for self edges 457 | const innerPoints = [section.startPoint, ...(section.bendPoints || []), section.endPoint].map(({ x, y }) => ({ 458 | x: x + parentX, 459 | y: y + parentY, 460 | })); 461 | return { 462 | type: "edge", 463 | id: edgeID, 464 | source: sourceNode, 465 | target: targetNode!, 466 | data: { 467 | // Combien inner and outer edge show it just shows up once in the rendering and can be selected as a single unit. 468 | points: [...innerPoints, ...(outerEdge.bendPoints || []), outerEdge.endPoint], 469 | }, 470 | }; 471 | }) 472 | ); 473 | } 474 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react"; 2 | import { createRoot } from "react-dom/client"; 3 | import App from "./App.tsx"; 4 | import "./index.css"; 5 | import { QueryClientProvider } from "@tanstack/react-query"; 6 | import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; 7 | import { queryClient } from "./queryClient.ts"; 8 | 9 | createRoot(document.getElementById("root")!).render( 10 | 11 | 12 | 13 | 14 | 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /src/queryClient.ts: -------------------------------------------------------------------------------- 1 | import { QueryClient } from "@tanstack/react-query"; 2 | 3 | export const queryClient = new QueryClient(); 4 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | import { scopedPreflightStyles, isolateInsideOfContainer } from 'tailwindcss-scoped-preflight'; 2 | 3 | // https://github.com/zaichaopan/react-aria-components-tailwind-starter/blob/c15f630866480e00d7a39258db0f61b39704e00e/tailwind.config.js 4 | 5 | const defaultTheme = require('tailwindcss/defaultTheme'); 6 | 7 | /** @type {import('tailwindcss').Config} */ 8 | export default { 9 | content: [ 10 | "./index.html", 11 | "./src/**/*.{js,ts,jsx,tsx}", 12 | ], 13 | theme: { 14 | extend: { 15 | colors: { 16 | background: 'hsl(var(--background))', 17 | foreground: 'hsl(var(--foreground))', 18 | accent: 'hsl(var(--accent))', 19 | success: 'hsl(var(--success))', 20 | destructive: 'hsl(var(--destructive))', 21 | warning: 'hsl(var(--warning))', 22 | hover: 'hsl(var(--hover))', 23 | muted: 'hsl(var(--muted))', 24 | border: 'hsl(var(--border))', 25 | }, 26 | }, 27 | }, 28 | plugins: [ 29 | require('tailwindcss-react-aria-components'), 30 | require('tailwindcss-animate'), 31 | require('@tailwindcss/container-queries'), 32 | scopedPreflightStyles({ 33 | isolationStrategy: isolateInsideOfContainer('.twp', {}), 34 | }), 35 | ], 36 | important: true, 37 | } 38 | 39 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": [ 6 | "ES2020", 7 | "DOM", 8 | "DOM.Iterable", 9 | "ESNext" 10 | ], 11 | "module": "ESNext", 12 | "skipLibCheck": true, 13 | /* Bundler mode */ 14 | "moduleResolution": "bundler", 15 | "allowImportingTsExtensions": true, 16 | "isolatedModules": true, 17 | "moduleDetection": "force", 18 | "noEmit": true, 19 | "jsx": "react-jsx", 20 | /* Linting */ 21 | "strict": true, 22 | "noUnusedLocals": true, 23 | "noUnusedParameters": true, 24 | "noFallthroughCasesInSwitch": true 25 | }, 26 | "include": [ 27 | "src/*" 28 | ], 29 | } 30 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": ["node"], 4 | 5 | "target": "ES2022", 6 | "lib": ["ES2023"], 7 | "module": "ESNext", 8 | "skipLibCheck": true, 9 | 10 | /* Bundler mode */ 11 | "moduleResolution": "bundler", 12 | "allowImportingTsExtensions": true, 13 | "isolatedModules": true, 14 | "moduleDetection": "force", 15 | "noEmit": true, 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["vite.config.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from "path"; 2 | import { defineConfig } from "vite"; 3 | import react from "@vitejs/plugin-react"; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [react()], 8 | base: "./", 9 | build: { 10 | lib: { 11 | entry: [resolve(__dirname, "src/Visualizer.tsx")], 12 | formats: ["es"], 13 | }, 14 | rollupOptions: { 15 | input: { 16 | main: resolve(__dirname, "index.html"), 17 | index: resolve(__dirname, "src/Visualizer.tsx"), 18 | }, 19 | // allow extension of entry signatures so Visualizer.tsx can be outputed as index.js and not include any imports 20 | preserveEntrySignatures: "allow-extension", 21 | }, 22 | }, 23 | 24 | define: { 25 | "process.env": { 26 | NODE_ENV: JSON.stringify(process.env.NODE_ENV), 27 | }, 28 | }, 29 | }); 30 | --------------------------------------------------------------------------------