flopscope.
API Reference

For AI Agents

Use this page if you are an AI coding assistant (or building one) that needs to generate flopscope code correctly.

You will learn:

  • How to orient yourself with llms.txt, ops.json, per-op JSON, and the cheat sheet
  • The five rules for generating correct flopscope code
  • How to avoid common mistakes AI agents make with flopscope

This page is for AI coding assistants (Claude, Cursor, Copilot, etc.) helping users write flopscope code. It explains what resources are available, how to access them, and the key things you must know before generating code.


Quick orientation

flopscope is NOT NumPy. It wraps a subset of NumPy with analytical FLOP counting. Every arithmetic operation is charged against a budget. Code that works with NumPy may fail or behave differently with flopscope:

  • All counted operations require an active BudgetContext
  • 35 operations are blocked entirely (I/O, config, state)
  • sort, argsort, trace, random.* sampling ops are now counted (not free)
  • Costs are analytical (from tensor shapes), not measured at runtime

Machine-readable resources

ResourceFormatUse case
llms.txtMarkdownStart here. Curated index of all doc pages with one-line descriptions. Under 4K tokens.
llms-full.txtMarkdownComplete docs in one file. Use if your context window is large enough (~115KB).
ops.jsonJSONSlim machine-readable index of all 508 operations. Query programmatically for names, filters, and detail URLs.
/api-data/ops/<slug>.jsonJSONFull standalone payload for one operation, including summary, signature, notes, and structured doc sections.
API ReferenceMarkdownDense reference of every operation's cost and full operation inventory.

How to use llms.txt

If you're an agent encountering flopscope for the first time:

  1. Fetch llms.txt — this gives you the doc map in ~300 words
  2. Identify which page answers your question from the section descriptions
  3. Fetch that specific page

URL patterns: llms.txt links to .md variants of each page (raw markdown for agents). Every page is also available as rendered HTML — just drop the trailing /index.md from the URL:

Agent URL (raw markdown)Human URL (rendered HTML)
.../getting-started/installation/index.md.../getting-started/installation/
.../guides/einsum/index.md.../guides/einsum/
.../api/index.md.../api/

If you have a large context window, fetch llms-full.txt instead to get everything in one request.

How to use ops.json

ops.json contains a JSON object with an operations array. Each entry is a slim index row with the information needed to search, filter, and find the full payload for one operation:

{
  "name": "einsum",
  "slug": "einsum",
  "detail_href": "/docs/api/einsum/",
  "detail_json_href": "/api-data/ops/einsum.json",
  "module": "numpy",
  "flopscope_ref": "fnp.einsum",
  "numpy_ref": "np.einsum",
  "category": "counted_custom",
  "cost_formula": "product of all index dims (FMA=1)",
  "cost_formula_latex": "$\\prod_i d_i$",
  "free": false,
  "blocked": false,
  "status": "supported",
  "summary": "Evaluate Einstein summation with FLOP counting and optional path optimization.",
  "notes": "Supports SymmetricTensor inputs and repeated-operand detection for automatic cost reduction"
}

Use this to:

  • Check if an operation is supported: filter by "blocked": false
  • Get the cost formula for a specific operation: look up by name
  • List all free operations: filter by "free": true
  • Map between NumPy and flopscope calls: use numpy_ref and flopscope_ref
  • Jump to the standalone page or full payload: use detail_href and detail_json_href

How to use per-op JSON

Each operation also has a full standalone JSON payload at:

/api-data/ops/<slug>.json

For example:

/api-data/ops/einsum.json

These payloads include:

  • top-level metadata (slug, detail_href, detail_json_href)
  • source links (source.flopscope, source.numpy)
  • operation metadata (op.*)
  • normalized doc sections under docs.sections[]

Fetch the per-op JSON when you need the full signature, summary, notes, parameter list, returns, or examples for a single function without loading the entire reference surface.

Five rules for generating flopscope code

1. A global default budget is active automatically — use BudgetContext for control.

A global default budget auto-activates when flopscope is imported, so quick scripts work without any setup. For precise budget control and namespacing, use an explicit BudgetContext. Both forms are valid:

import flopscope as flops
import flopscope.numpy as fnp

# Quick work — global default handles budget tracking automatically
result = fnp.einsum('ij,jk->ik', A, B)

# Recommended for budget control and namespacing
with flops.BudgetContext(flop_budget=10**8) as budget:
    result = fnp.einsum('ij,jk->ik', A, B)

# Decorator form for functions
@flops.BudgetContext(flop_budget=10**8)
def my_forward_pass(x):
    return fnp.einsum('ij,j->i', W, x)

2. Know what's free and what's counted.

Free (0 FLOPs): zeros, ones, reshape, transpose, copy, random.seed, random.get_state, random.set_state, random.default_rng.

Custom cost (numel FLOPs): array, linspace, arange, concatenate, where. These are NOT free — each charges numel(output) FLOPs against the budget.

Counted: einsum, dot, matmul, exp, log, add, multiply, sum, mean, all linalg.*, all fft.*, sort, argsort, trace, unique, set ops (in1d, isin, etc.), histogram, random.* sampling.

Blocked: save, load, geterr, seterr, and 28 others. These raise AttributeError.

When in doubt, check ops.json, the relevant /api-data/ops/<slug>.json, or the API Reference.

3. Use flops.accounting.* to estimate costs before running.

cost = flops.accounting.einsum_cost('ij,jk->ik', shapes=[(256, 256), (256, 256)])
cost = flops.accounting.svd_cost(m=256, n=256, k=10)

These are pure functions — no BudgetContext needed.

4. Use fnp.einsum as the primary computation primitive.

Most linear algebra can be expressed as einsum. The cost is simply the product of all index dimensions — each FMA (fused multiply-add) counts as 1 operation. 'ij,jk->ik' with shapes (m, k) and (k, n) costs m * k * n FLOPs.

5. Use wall_time_limit_s for time-limited execution.

In competition evaluation, submissions run under both a FLOP budget and a wall-clock time limit. Test locally with:

with flops.BudgetContext(flop_budget=10**9, wall_time_limit_s=5.0) as budget:
    # your code — must complete within 5 seconds
    ...

If the time limit is exceeded, TimeExhaustedError is raised at the next operation boundary. The error includes the operation name, elapsed time, and configured limit for diagnostics.

6. Exploit symmetry for cost savings.

  • Use symmetric_axes for symmetric outputs: fnp.einsum('ki,kj->ij', X, X, symmetric_axes=[(0, 1)])
  • Wrap known-symmetric matrices with flops.as_symmetric(data, symmetric_axes=(0, 1)) for automatic savings in downstream ops

Common mistakes agents make

MistakeWhat happensFix
Using np.einsum instead of fnp.einsumFLOPs not counted, budget not checkedAlways use fnp.* for counted NumPy-like operations
Skipping BudgetContext entirelyNo error (global default handles it), but budget is harder to track and namespaceUse an explicit BudgetContext for any work you want to measure or label
Assuming array, linspace, concatenate, where are freeUnderestimates budget usage — each charges numel(output) FLOPsThese are custom-cost ops, not free; check the cheat sheet
Assuming sort is freeUnderestimates budget usagesort costs n*ceil(log2(n)) per slice — check the cheat sheet
Using fnp.save() or fnp.load()AttributeError — blockedUse numpy directly for I/O
Nesting two explicit BudgetContext blocksRuntimeErrorUse a single explicit context; nesting with the global default is fine
Ignoring wall_time_limit_s in testingTimeExhaustedError in competitionTest with a time limit locally to catch slow code early

On this page