Skip to content

Cost and Factorization Analysis Utility#577

Open
ajay-mk wants to merge 10 commits into
masterfrom
ajay/cost-analysis-utility
Open

Cost and Factorization Analysis Utility#577
ajay-mk wants to merge 10 commits into
masterfrom
ajay/cost-analysis-utility

Conversation

@ajay-mk

@ajay-mk ajay-mk commented Jul 9, 2026

Copy link
Copy Markdown
Member

Cost and Factorization Analysis Utility

Adds utilities/cost_analysis, a standalone tool that estimates the cost of evaluating a tensor equation without running it. It reads a serialized equation, optimizes and binarizes it, then writes a Markdown report on the largest intermediates, the most expensive contractions, peak storage, operation counts, and cache reuse.
Inspiration is from MPQC's SeQuantEngine class and the several knobs it exposes.

What it does

  • Input: a JSON driver pointing at one or more equation files (<head> = <rhs> in SeQuant serialization V1), plus context (spin basis, field, index-space sizes, factorization spaces).
  • Pipeline (per equation): deserialize → strip leading (anti)symmetrizer → flattenoptimize + binarize → catalog the tree's internal nodes → cache simulation across all results.
  • Output: per-result summary, Largest intermediates, Most expensive
    contractions
    , a Shape census by O/V/X signature, and a Cache table.

Usage

cost_analysis --driver examples/ccsd_r2.json

All driver knobs and their defaults are documented in the utility's README.md.

Tests

Two reference tests (ctest -R cost_analysis_) run the tool on examples/ and diff against frozen *.md.expected.

Not supported right now

  • CSV/PNO expressions: AsyCost is not proto-index aware; this utility should work once AsyCost is extended.

Example report:

EOM-CCSD(2h2p) R2 (53 terms; i=10, a=38)

Terms: 53; distinct intermediates: 94; reused: 9; largest: 8.3728 MB; peak storage: 40.1953 MB.

Total operations (symbolic): 4i^2a^4 + 18i^3a^3 + 26i^4a^2 + 2ia^4 + 30i^2a^3 + 104i^3a^2 + 26i^4a + 4ia^3 + 55i^2a^2 + 4i^3a + 10*i^2a

Largest intermediates

Rank Result Spaces Memory (MB) Uses Construction Local ops
1 I(a_2,a_1,i_2,a_3) VVOV 8.3728 1 ((g(i_3,i_4,a_3,a_4) * t(a_4,i_2)) * t(a_1,a_2,i_3,i_4)) 2*i^3a^3
2 I(a_2,a_1,i_2,a_3) VVOV 8.3728 1 (g(a_1,a_2,a_3,a_4) * t(a_4,i_2)) 2*ia^4
3 I(a_1,a_2,i_2,a_3) VVOV 8.3728 1 (g(i_3,a_1,a_3,a_4) * t(a_2,a_4,i_2,i_3)) 2*i^2a^4
4 I(a_2,a_1,i_2,a_3) VVOV 8.3728 1 (g(i_3,i_4,i_2,a_3) * t(a_1,a_2,i_3,i_4)) 2*i^3a^3
5 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 (((R(a_3,a_4,i_1,i_2) * g(i_3,i_4,a_3,a_4)) * t(a_1,i_3)) * t(a_2,i_4)) 2*i^3a^2
6 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 (((R(a_3,i_1) * g(i_3,i_4,i_2,a_3)) * t(a_1,i_3)) * t(a_2,i_4)) 2*i^3a^2
7 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 ((R(a_1,a_3,i_1,i_2) * (g(i_3,i_4,a_3,a_4) * t(a_4,i_4))) * t(a_2,i_3)) 2*i^3a^2
8 I(a_1,a_2,i_2,i_1) VVOO 2.2034 1 ((R(a_1,a_3,i_1,i_2) * f(i_3,a_3)) * t(a_2,i_3)) 2*i^3a^2
9 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 ((R(a_1,a_3,i_1,i_3) * (g(i_3,i_4,a_3,a_4) * t(a_4,i_2))) * t(a_2,i_4)) 2*i^3a^2
10 I(a_1,a_2,i_2,i_1) VVOO 2.2034 1 ((R(a_1,a_3,i_1,i_3) * g(i_3,i_4,i_2,a_3)) * t(a_2,i_4)) 2*i^3a^2
11 I(a_1,a_2,i_2,i_1) VVOO 2.2034 1 ((R(a_1,a_3,i_3,i_4) * g(i_3,i_4,a_3,a_4)) * t(a_2,a_4,i_1,i_2)) 2*i^2a^3
12 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 ((R(a_3,a_4,i_1,i_2) * g(i_3,i_4,a_3,a_4)) * t(a_1,a_2,i_3,i_4)) 2*i^4a^2
13 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 ((R(a_3,a_4,i_1,i_3) * g(i_3,i_4,a_3,a_4)) * t(a_1,a_2,i_2,i_4)) 2*i^3a^2
14 I(a_1,a_2,i_2,i_1) VVOO 2.2034 1 ((R(a_3,i_1) * (g(i_3,a_1,a_3,a_4) * t(a_4,i_2))) * t(a_2,i_3)) 2*i^3a^2
15 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 ((R(a_3,i_1) * (g(i_3,i_4,a_3,a_4) * t(a_2,a_4,i_2,i_4))) * t(a_1,i_3)) 2*i^3a^2
16 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 ((R(a_3,i_1) * (g(i_3,i_4,a_3,a_4) * t(a_4,i_3))) * t(a_1,a_2,i_2,i_4)) 2*i^3a^2
17 I(a_1,a_2,i_2,i_1) VVOO 2.2034 1 ((R(a_3,i_1) * g(i_3,a_1,i_2,a_3)) * t(a_2,i_3)) 2*i^3a^2
18 I(a_1,a_2,i_2,i_1) VVOO 2.2034 1 ((R(a_3,i_3) * g(i_3,a_1,a_3,a_4)) * t(a_2,a_4,i_1,i_2)) 2*i^2a^3
19 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 ((R(a_3,i_3) * g(i_3,i_4,i_1,a_3)) * t(a_1,a_2,i_2,i_4)) 2*i^3a^2
20 I(a_2,a_1,i_2,i_1) VVOO 2.2034 1 (R(a_1,a_2,i_1,i_3) * ((g(i_3,i_4,a_3,a_4) * t(a_3,i_4)) * t(a_4,i_2))) 2*i^3a^2

Most expensive contractions

Rank Result Spaces Uses Construction Operations
1 I(a_2,a_1,i_2,i_1) VVOO 1 (R(a_3,a_4,i_1,i_2) * g(a_1,a_2,a_3,a_4)) 2*i^2a^4
2 I(a_1,a_2,i_2,a_3) VVOV 1 (g(i_3,a_1,a_3,a_4) * t(a_2,a_4,i_2,i_3)) 2*i^2a^4
3 I(a_2,a_1,i_2,a_3) VVOV 1 ((g(i_3,i_4,a_3,a_4) * t(a_4,i_2)) * t(a_1,a_2,i_3,i_4)) 2*i^3a^3
4 I(a_2,a_1,i_1,i_2) VVOO 1 (R(a_1,a_3,i_1,i_3) * (g(i_3,a_2,a_3,a_4) * t(a_4,i_2))) 2*i^3a^3
5 I(a_1,a_2,i_2,i_1) VVOO 1 (R(a_1,a_3,i_1,i_3) * (g(i_3,i_4,a_3,a_4) * t(a_2,a_4,i_2,i_4))) 2*i^3a^3
6 I(a_2,a_1,i_2,i_1) VVOO 1 (R(a_1,a_3,i_1,i_3) * g(i_3,a_2,i_2,a_3)) 2*i^3a^3
7 I(i_3,a_1,i_2,i_1) OVOO 1 (R(a_3,a_4,i_1,i_2) * g(i_3,a_1,a_3,a_4)) 2*i^3a^3
8 I(i_3,a_2,i_2,i_1) OVOO 1 (g(i_3,a_2,a_3,a_4) * t(a_3,a_4,i_1,i_2)) 2*i^3a^3
9 I(i_3,a_2,i_2,a_3) OVOV 2 (g(i_3,i_4,a_3,a_4) * t(a_2,a_4,i_2,i_4)) 2*i^3a^3
10 I(a_2,a_1,i_2,a_3) VVOV 1 (g(i_3,i_4,i_2,a_3) * t(a_1,a_2,i_3,i_4)) 2*i^3a^3
11 I(a_2,a_1,i_2,a_3) VVOV 1 (g(a_1,a_2,a_3,a_4) * t(a_4,i_2)) 2*ia^4
12 I(a_2,a_1,i_2,i_1) VVOO 1 ((R(a_3,a_4,i_1,i_2) * g(i_3,i_4,a_3,a_4)) * t(a_1,a_2,i_3,i_4)) 2*i^4a^2
13 I(i_3,a_2,i_2,i_1) OVOO 1 ((g(i_3,i_4,a_3,a_4) * t(a_3,i_1)) * t(a_2,a_4,i_2,i_4)) 2*i^4a^2
14 I(a_2,a_1,i_2,i_1) VVOO 1 (R(a_1,a_2,i_3,i_4) * ((g(i_3,i_4,a_3,a_4) * t(a_3,i_1)) * t(a_4,i_2))) 2*i^4a^2
15 I(a_2,a_1,i_2,i_1) VVOO 1 (R(a_1,a_2,i_3,i_4) * (g(i_3,i_4,a_3,a_4) * t(a_3,a_4,i_1,i_2))) 2*i^4a^2
16 I(a_2,a_1,i_2,i_1) VVOO 1 (R(a_1,a_2,i_3,i_4) * g(i_3,i_4,i_1,i_2)) 2*i^4a^2
17 I(i_4,a_1,i_1,i_2) OVOO 1 (R(a_1,a_3,i_1,i_3) * (g(i_3,i_4,a_3,a_4) * t(a_4,i_2))) 2*i^4a^2
18 I(i_4,a_1,i_2,i_1) OVOO 1 (R(a_1,a_3,i_1,i_3) * g(i_3,i_4,i_2,a_3)) 2*i^4a^2
19 I(i_4,i_3,i_2,i_1) OOOO 2 (R(a_3,a_4,i_1,i_2) * g(i_3,i_4,a_3,a_4)) 2*i^4a^2
20 I(i_4,i_3,i_2,i_1) OOOO 2 (g(i_3,i_4,a_3,a_4) * t(a_3,a_4,i_1,i_2)) 2*i^4a^2

Shape census

Shape Size (MB) # Distinct Total uses
VVOV 8.3728 4 4
OVOV 2.2034 2 5
VVOO 2.2034 43 43
OOOV 0.5798 1 6
OVOO 0.5798 23 23
OOOO 0.1526 6 10
VV 0.0220 4 4
OV 0.0058 2 6
OO 0.0015 9 9

Cache (gated, volatile leaf = "R", min_repeats = 2)

Metric Value
Cached 30
Persistent 28
Persistent footprint (MB) 45.3697
Total cached footprint (MB) 45.5281

ajay-mk added 2 commits July 9, 2026 10:54
A standalone utility that estimates the cost of evaluating a serialized
tensor equation. Reads a JSON driver (space sizes + equation files), strips
the (anti)symmetrizer, flattens, then per summand optimizes and binarizes
once, reusing that tree for the intermediate catalog, cache simulation, and
--dump_tree, mirroring MPQC's SeQuantEngine. Emits a Markdown report on
largest intermediates, most expensive contractions, shape census, peak
storage, FLOPs, and a gated cache simulation. Includes a README and CCSD/DF
example drivers.
Diff generated reports against frozen *.md.expected via run_tests.cmake
(volatile lines stripped): a spin-orbital CCSD R2 (a Sum of terms, with a
--dump_tree check) and a single density-fitted product (the non-Sum path).
Comment thread utilities/cost_analysis/examples/df_r1.md.expected Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new standalone cost_analysis utility under utilities/ that reads a JSON driver, optimizes/binarizes SeQuant equations, and emits a Markdown report (plus optional tree dumps) along with reference-style CTest coverage.

Changes:

  • Added the cost_analysis executable with JSON-driven configuration, equation parsing, optimization/binarization, cataloging, and optional cache simulation.
  • Added Markdown report generation and accompanying documentation/examples with frozen *.md.expected fixtures.
  • Integrated the tool into the build and added CTest-based golden-file regression tests.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
utilities/cost_analysis/run_tests.cmake CMake script to run the utility and compare generated reports to expected fixtures (with volatile lines stripped).
utilities/cost_analysis/report.hpp Declares report-writing and tree-string serialization helpers.
utilities/cost_analysis/report.cpp Implements Markdown report formatting, table generation, and tree stringification.
utilities/cost_analysis/README.md Documents the driver schema, workflow, report contents, and tests.
utilities/cost_analysis/examples/df_r1.md.expected Golden expected report output for DF R1 example.
utilities/cost_analysis/examples/df_r1.json JSON driver for DF R1 example.
utilities/cost_analysis/examples/df_r1.inp Serialized equation input for DF R1 example.
utilities/cost_analysis/examples/ccsd_r2.md.expected Golden expected report output for CCSD R2 example.
utilities/cost_analysis/examples/ccsd_r2.json JSON driver for CCSD R2 example (includes dump_tree).
utilities/cost_analysis/examples/ccsd_r2.inp Serialized equation input for CCSD R2 example.
utilities/cost_analysis/examples/.gitignore Ignores generated reports, filtered files, and dump-tree outputs.
utilities/cost_analysis/cost_analysis.hpp Defines shared config/result data structures between analysis and reporting.
utilities/cost_analysis/cost_analysis.cpp Implements the CLI entrypoint, JSON parsing, context setup, analysis pipeline, cache simulation, and report emission.
utilities/cost_analysis/CMakeLists.txt Adds build target and CTest registrations for the new utility.
utilities/CMakeLists.txt Wires utilities/cost_analysis into the utilities build.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread utilities/cost_analysis/report.cpp Outdated
Comment thread utilities/cost_analysis/CMakeLists.txt Outdated
Comment thread utilities/cost_analysis/run_tests.cmake Outdated
Comment thread utilities/cost_analysis/run_tests.cmake Outdated
Comment thread utilities/cost_analysis/run_tests.cmake Outdated
Comment thread utilities/cost_analysis/cost_analysis.cpp Outdated
ajay-mk added 8 commits July 9, 2026 13:48
The generated timestamp changed every run; only the volatile-line stripping
in run_tests.cmake kept the reference tests deterministic. Remove it (and the
now-unused <chrono> include). Keep the SeQuant version/hash line, still
stripped before diffing. Reference fixtures now carry a <version> placeholder
instead of a frozen timestamp+hash.
@ajay-mk ajay-mk marked this pull request as ready for review July 10, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants