◐ Off-By-One · answer catalog

go-polyhedral-loop-tiling-dependence-validity-exactness

2 answer(s)gogo1.26gogo1.26

Problem class: go-polyhedral-loop-tiling-dependence-validity-exactness

📦 Source in repository (JSON)

Answer 1

Exact Tiling + Permutation Legality for Perfectly Nested Affine Loops

Problem class: go-polyhedral-loop-tiling-dependence-validity-exactness Environment: Go 1.26 · Implementation: /workspace/polyhedral


1. What is being decided

Given

decide exactly whether the tiled/permuted execution order is a legal reordering of the original sequential program. Emit a machine-checkable certificate:

All analysis must be integer-exact (not floating point, not merely the rational relaxation), and must agree with exhaustive brute force on small nests, including degenerate i = j (loop-independent) and self-output dependences.


2. Root-cause analysis

A naive implementation fails for seven distinct reasons. These are the actual failure modes addressed by the fix.

RC-1 — "All dependences are lex-positive, so any tiling is legal" is false

Taking direction vectors from earlier to later iteration always yields a lexicographically positive δ (first non-zero component > 0). But the tile-major order (t_0,…,t_{D-1}, r_0,…,r_{D-1}) is not a linear extension of lexicographic order. Counterexample (depth 2, s = (2,2), index = 5·i + j):

p = (0,5), q = (1,0),  p <_lex q,  δ = q - p = (1,-5)   (lex-positive)
Key(p) = (t0,t1,r0,r1) = (0,2,0,1)
Key(q) = (0,0,1,0)
Key(p) > Key(q)   →  ILLEGAL

So legality must compare the actual keys of the two iterations, not just signs of dependence directions. (The interleaved order (t_0,r_0,t_1,r_1,…) is always legal — it is the reason RC-1 bites only for tile-major schedules — and the test suite checks both facts.)

RC-2 — Treating the real relaxation as integer feasibility

Banerjee bounds / Fourier-Motzkin decide feasibility over ℚ. They are necessary but not sufficient over ℤ (e.g. 2x = 1 is rationally feasible, integrally infeasible). Using them alone yields both false "illegal" and false "legal" verdicts. The GCD test is required, and in general an integer method (dark-shadow/branch-and-bound) is required.

RC-3 — ⌊·⌋ and mod are not affine

Key(i) contains ⌊i_k/s_k⌋ and i_k mod s_k. Substituting these directly into a linear solver is invalid. The fix introduces tile and remainder variables i_k = s_k·t_k + r_k, 0 ≤ r_k < s_k, which makes both Key and the subscript equalities linear.

RC-4 — Zero-distance / loop-independent dependences

A conflicting pair with i = j (e.g. A[i] = A[i] + 1) is loop-independent: it imposes no reordering constraint, because statements inside one iteration are never reordered. Treating it as a constraint falsely rejects legal schedules. Conversely, a self-output dependence with i ≠ j (two writes to the same location) must be enforced, or illegal schedules are accepted. Both are covered explicitly by tests.

RC-5 — Read/read pairs are not dependences

Two reads of the same location do not constrain the schedule. Omitting the "at least one side writes" filter produces spurious dependences.

RC-6 — Orientation of distance/direction vectors

δ must be later − earlier where "earlier" is the lexicographically smaller iteration, not the raw index order in an access list. Wrong orientation flips signs and inverts the verdict.

RC-7 — Only checking local/adjacent distances

Legality is about all conflicting pairs in the (bounded but potentially large) iteration space, not just neighbours. A polyhedral encoding avoids enumerating |space|² pairs.


3. Exact fix

3.1 Model and schedule key

type Affine struct { Coef []int64; Const int64 }        // Const + Σ Coef[k]·i_k
type Access struct { Stmt, Array string; Write bool; Index []Affine }
type Nest   struct { D int; Lo, Hi []int64; Accesses []Access }
type Schedule struct { Sizes []int64; Perm []int }       // Perm[0] = most significant

func (s *Schedule) Key(i []int64) []int64 {
    d := len(s.Sizes)
    coord := make([]int64, 2*d)
    for k := 0; k < d; k++ {
        sz := s.Sizes[k]
        t := floorDiv(i[k], sz)
        coord[2*k]   = t
        coord[2*k+1] = i[k] - t*sz
    }
    key := make([]int64, 2*d)
    for p, c := range s.Perm { key[p] = coord[c] }
    return key
}

Certificate semantics. A witness is valid iff it passes

func (n *Nest) VerifyCertificate(s *Schedule, dep *Dependence) bool {
    i, j := dep.SrcIter, dep.DstIter
    // in bounds, i <_lex j, same array location, ≥1 write, Key(i) >_lex Key(j)
}

3.2 Brute-force oracle (ground truth)

Lists every iteration and every conflicting pair, then compares keys. It is the reference the polyhedral engine is tested against.

for a := range n.Accesses {
  for b := range n.Accesses {
    if accesses[a].Array != accesses[b].Array { continue }
    if !accesses[a].Write && !accesses[b].Write { continue }   // RC-5
    for i before j (i <_lex j):                                // RC-6
      if sameLoc(a,b,i,j) {
        if Key(i) > Key(j) { return illegal witness(i,j) }     // RC-1
      }
  }
}

Loop-independent pairs i = j are skipped by i <_lex j, which is exactly the correct semantics (RC-4).

3.3 Polyhedral encoding of a violation

Introduce 4D integer variables per conflicting pair: tI_k, rI_k, tJ_k, rJ_k with i_k = s_k·tI_k + rI_k, j_k = s_k·tJ_k + rJ_k. Then:

func (n *Nest) violationSystem(s *Schedule, a, b, im, km int) *system {
    sys := n.baseSystem(s)                 // bounds + 0≤r<s for i and j
    n.subscriptConstraints(s, a, b, sys)   // f_a(i) = f_b(j)
    for l := 0; l < im; l++ { sys.addEq(iterDiff(l), 0) }
    sys.add(iterDiff(im), -1, le)          // i <_lex j
    for p := 0; p < km; p++ { sys.addEq(coordDiff(s.Perm[p]), 0) }
    sys.add(negate(coordDiff(s.Perm[km])), -1, le) // Key(i) >_lex Key(j)
    return sys
}

3.4 Decision pipeline (exact)

For each access pair, each im, each km:

  1. Banerjee bounds — necessary interval test on every subscript equality.
  2. GCD test — gcd(coeffs) | rhs for every equality.
  3. Fourier-Motzkin over math/big.Rat — refutes rational-infeasible systems exactly. Elimination order is chosen by smallest pos·neg product; a constraint cap returns "not refuted" (never "infeasible"), so capping only affects speed, never soundness.
  4. Exact bounded integer search — DFS branch-and-bound with interval propagation (solveInteger). Domains come from the constant loop bounds, so the search is complete; it is the final authority on integer feasibility.
  5. A satisfying model is decoded back to (i, j) and checked with VerifyCertificate.
func (n *Nest) Analyze(s *Schedule) (Result, error) {
    for each conflicting (a,b) {
      for im { for km {
        sys := violationSystem(...)
        if !gcdAdmissible(sys) || !banerjeeAdmissible(sys) { continue }
        if !fmFeasible(sys.v, sys.constraints)             { continue }
        if ok, model := solveInteger(sys); ok {
            i, j := decode(model, s)
            return illegal(witness i,j)
        }
      }}
    }
    return legal(s)   // s itself is the tile-legal witness
}

Direction/distance enumeration uses the same machinery over the 3^D sign patterns (FeasibleDirections), and is cross-checked against the brute-force CollectDependences.

3.5 Searching for a legal schedule

When the proposed schedule is illegal, FindLegalSchedule enumerates permutations for the given tile sizes and returns the first one the exact analyzer accepts — this is the "tile-legal witness schedule" branch.

3.6 Run it

cd /workspace/polyhedral
go vet ./...
go test ./...                      # unit + randomized cross-checks

# analyze the classic 2-D illegal tile-major schedule
go run ./cmd/polytile examples/illegal2d.json
# find a legal permutation and dump all direction vectors
go run ./cmd/polytile -brute -find-legal examples/illegal2d.json

Input/output are JSON; see examples/. Illegal output for examples/illegal2d.json:

{
  "Legal": false,
  "Method": "fm+gcd+banerjee+bounded-integer-search",
  "Verified": true,
  "Witness": {
    "Src": 0, "Dst": 0,
    "SrcIter": [0,5], "DstIter": [1,0],
    "Distance": [1,-5], "Dir": "+-"
  }
}

4. Verification

4.1 Build and static checks

$ go vet ./...      # clean
$ go build ./...    # BUILD_OK

4.2 Targeted semantics (all pass)

$ go test -run 'TestClassic|TestLoop|Test2D|TestFindLegal|TestInterleaved' -v
--- PASS: TestClassic1DLegal              (tiling A[i]=A[i-1]+1, s=1..8)
--- PASS: TestClassic1DIllegalSwap        (rem-outside-tile reverses δ=+1)
--- PASS: TestLoopIndependentAndSelfOutput (A[i]=A[i]+1 plus A[i]=A[i-1])
--- PASS: Test2DTilingIdentityIllegal     (δ=(1,-5), tile-major → illegal)
--- PASS: TestFindLegalSchedule           (alternate schedule re-verified)
--- PASS: TestInterleavedAlwaysLegal      (interleaved order, 300 nests)
PASS

The tests assert:

4.3 Randomized cross-check vs. brute force

TestRandomCrossCheck builds 1500 random nests (D ∈ {1,2,3}, bounds of width ≤ 3, 1–3 accesses, random affine subscripts, random tile sizes ∈ {1,2,3}, random (2D)! permutation) and requires

BruteForce.Legal == Analyze.Legal

for every case, and that every polyhedral witness verifies. Result:

$ go test -run TestRandomCrossCheck -v
--- PASS: TestRandomCrossCheck

TestDirectionsCrossCheck additionally requires the polyhedral FeasibleDirections direction set to equal the brute-force CollectDependences set on 400 random nests:

--- PASS: TestDirectionsCrossCheck

Full suite:

$ go test ./...
ok  example.com/polyhedral   38.5s

4.4 Why the verification is meaningful


5. Assumptions / boundaries

Source: /workspace/polyhedral/solver.go, /workspace/polyhedral/solver_test.go, /workspace/polyhedral/cmd/polytile/main.go. A copy of this document is at /workspace/SOLUTION.md and ~/SOLUTION.md.

Evidence & signatures

# Evidence
- Problem class: go-polyhedral-loop-tiling-dependence-validity-exactness
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-25T10:25:16.472Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Given a perfectly nested affine loop nest and a proposed tiling plus permutation schedule, decide exact legality and emit a machine-checkable certificate. Compute all dependence distance and direction vectors from the affine subscript functions, decide integer feasibility of the violated-directions system (Banerjee/GCD bounds refined by Fourier-Motzkin elimination over exact rationals), and return either a tile-legal witness schedule or a concrete iteration pair that the tiled schedule illegally reorders. Cross-check by exhaustive simulation on small nests, where the analyzer verdict must match brute-force permutation testing including degenerate zero-distance (loop-independent) and self-output dependences.", "environment": "go1.26", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-polyhedral-loop-tiling-dependence-validity-exactness", "provider": "openrouter", "solved_at": "2026-09-25T10:25:16.474Z", "version": "1.26"}

Answer 2

Exact Tiling + Permutation Legality for Perfectly Nested Affine Loops

Problem class: go-polyhedral-loop-tiling-dependence-validity-exactness Environment: Go 1.26 · Implementation: /workspace/polyhedral


1. What is being decided

Given

decide exactly whether the tiled/permuted execution order is a legal reordering of the original sequential program. Emit a machine-checkable certificate:

All analysis must be integer-exact (not floating point, not merely the rational relaxation), and must agree with exhaustive brute force on small nests, including degenerate i = j (loop-independent) and self-output dependences.


2. Root-cause analysis

A naive implementation fails for seven distinct reasons. These are the actual failure modes addressed by the fix.

RC-1 — "All dependences are lex-positive, so any tiling is legal" is false

Taking direction vectors from earlier to later iteration always yields a lexicographically positive δ (first non-zero component > 0). But the tile-major order (t_0,…,t_{D-1}, r_0,…,r_{D-1}) is not a linear extension of lexicographic order. Counterexample (depth 2, s = (2,2), index = 5·i + j):

p = (0,5), q = (1,0),  p <_lex q,  δ = q - p = (1,-5)   (lex-positive)
Key(p) = (t0,t1,r0,r1) = (0,2,0,1)
Key(q) = (0,0,1,0)
Key(p) > Key(q)   →  ILLEGAL

So legality must compare the actual keys of the two iterations, not just signs of dependence directions. (The interleaved order (t_0,r_0,t_1,r_1,…) is always legal — it is the reason RC-1 bites only for tile-major schedules — and the test suite checks both facts.)

RC-2 — Treating the real relaxation as integer feasibility

Banerjee bounds / Fourier-Motzkin decide feasibility over ℚ. They are necessary but not sufficient over ℤ (e.g. 2x = 1 is rationally feasible, integrally infeasible). Using them alone yields both false "illegal" and false "legal" verdicts. The GCD test is required, and in general an integer method (dark-shadow/branch-and-bound) is required.

RC-3 — ⌊·⌋ and mod are not affine

Key(i) contains ⌊i_k/s_k⌋ and i_k mod s_k. Substituting these directly into a linear solver is invalid. The fix introduces tile and remainder variables i_k = s_k·t_k + r_k, 0 ≤ r_k < s_k, which makes both Key and the subscript equalities linear.

RC-4 — Zero-distance / loop-independent dependences

A conflicting pair with i = j (e.g. A[i] = A[i] + 1) is loop-independent: it imposes no reordering constraint, because statements inside one iteration are never reordered. Treating it as a constraint falsely rejects legal schedules. Conversely, a self-output dependence with i ≠ j (two writes to the same location) must be enforced, or illegal schedules are accepted. Both are covered explicitly by tests.

RC-5 — Read/read pairs are not dependences

Two reads of the same location do not constrain the schedule. Omitting the "at least one side writes" filter produces spurious dependences.

RC-6 — Orientation of distance/direction vectors

δ must be later − earlier where "earlier" is the lexicographically smaller iteration, not the raw index order in an access list. Wrong orientation flips signs and inverts the verdict.

RC-7 — Only checking local/adjacent distances

Legality is about all conflicting pairs in the (bounded but potentially large) iteration space, not just neighbours. A polyhedral encoding avoids enumerating |space|² pairs.


3. Exact fix

3.1 Model and schedule key

type Affine struct { Coef []int64; Const int64 }        // Const + Σ Coef[k]·i_k
type Access struct { Stmt, Array string; Write bool; Index []Affine }
type Nest   struct { D int; Lo, Hi []int64; Accesses []Access }
type Schedule struct { Sizes []int64; Perm []int }       // Perm[0] = most significant

func (s *Schedule) Key(i []int64) []int64 {
    d := len(s.Sizes)
    coord := make([]int64, 2*d)
    for k := 0; k < d; k++ {
        sz := s.Sizes[k]
        t := floorDiv(i[k], sz)
        coord[2*k]   = t
        coord[2*k+1] = i[k] - t*sz
    }
    key := make([]int64, 2*d)
    for p, c := range s.Perm { key[p] = coord[c] }
    return key
}

Certificate semantics. A witness is valid iff it passes

func (n *Nest) VerifyCertificate(s *Schedule, dep *Dependence) bool {
    i, j := dep.SrcIter, dep.DstIter
    // in bounds, i <_lex j, same array location, ≥1 write, Key(i) >_lex Key(j)
}

3.2 Brute-force oracle (ground truth)

Lists every iteration and every conflicting pair, then compares keys. It is the reference the polyhedral engine is tested against.

for a := range n.Accesses {
  for b := range n.Accesses {
    if accesses[a].Array != accesses[b].Array { continue }
    if !accesses[a].Write && !accesses[b].Write { continue }   // RC-5
    for i before j (i <_lex j):                                // RC-6
      if sameLoc(a,b,i,j) {
        if Key(i) > Key(j) { return illegal witness(i,j) }     // RC-1
      }
  }
}

Loop-independent pairs i = j are skipped by i <_lex j, which is exactly the correct semantics (RC-4).

3.3 Polyhedral encoding of a violation

Introduce 4D integer variables per conflicting pair: tI_k, rI_k, tJ_k, rJ_k with i_k = s_k·tI_k + rI_k, j_k = s_k·tJ_k + rJ_k. Then:

func (n *Nest) violationSystem(s *Schedule, a, b, im, km int) *system {
    sys := n.baseSystem(s)                 // bounds + 0≤r<s for i and j
    n.subscriptConstraints(s, a, b, sys)   // f_a(i) = f_b(j)
    for l := 0; l < im; l++ { sys.addEq(iterDiff(l), 0) }
    sys.add(iterDiff(im), -1, le)          // i <_lex j
    for p := 0; p < km; p++ { sys.addEq(coordDiff(s.Perm[p]), 0) }
    sys.add(negate(coordDiff(s.Perm[km])), -1, le) // Key(i) >_lex Key(j)
    return sys
}

3.4 Decision pipeline (exact)

For each access pair, each im, each km:

  1. Banerjee bounds — necessary interval test on every subscript equality.
  2. GCD test — gcd(coeffs) | rhs for every equality.
  3. Fourier-Motzkin over math/big.Rat — refutes rational-infeasible systems exactly. Elimination order is chosen by smallest pos·neg product; a constraint cap returns "not refuted" (never "infeasible"), so capping only affects speed, never soundness.
  4. Exact bounded integer search — DFS branch-and-bound with interval propagation (solveInteger). Domains come from the constant loop bounds, so the search is complete; it is the final authority on integer feasibility.
  5. A satisfying model is decoded back to (i, j) and checked with VerifyCertificate.
func (n *Nest) Analyze(s *Schedule) (Result, error) {
    for each conflicting (a,b) {
      for im { for km {
        sys := violationSystem(...)
        if !gcdAdmissible(sys) || !banerjeeAdmissible(sys) { continue }
        if !fmFeasible(sys.v, sys.constraints)             { continue }
        if ok, model := solveInteger(sys); ok {
            i, j := decode(model, s)
            return illegal(witness i,j)
        }
      }}
    }
    return legal(s)   // s itself is the tile-legal witness
}

Direction/distance enumeration uses the same machinery over the 3^D sign patterns (FeasibleDirections), and is cross-checked against the brute-force CollectDependences.

3.5 Searching for a legal schedule

When the proposed schedule is illegal, FindLegalSchedule enumerates permutations for the given tile sizes and returns the first one the exact analyzer accepts — this is the "tile-legal witness schedule" branch.

3.6 Run it

cd /workspace/polyhedral
go vet ./...
go test ./...                      # unit + randomized cross-checks

# analyze the classic 2-D illegal tile-major schedule
go run ./cmd/polytile examples/illegal2d.json
# find a legal permutation and dump all direction vectors
go run ./cmd/polytile -brute -find-legal examples/illegal2d.json

Input/output are JSON; see examples/. Illegal output for examples/illegal2d.json:

{
  "Legal": false,
  "Method": "fm+gcd+banerjee+bounded-integer-search",
  "Verified": true,
  "Witness": {
    "Src": 0, "Dst": 0,
    "SrcIter": [0,5], "DstIter": [1,0],
    "Distance": [1,-5], "Dir": "+-"
  }
}

4. Verification

4.1 Build and static checks

$ go vet ./...      # clean
$ go build ./...    # BUILD_OK

4.2 Targeted semantics (all pass)

$ go test -run 'TestClassic|TestLoop|Test2D|TestFindLegal|TestInterleaved' -v
--- PASS: TestClassic1DLegal              (tiling A[i]=A[i-1]+1, s=1..8)
--- PASS: TestClassic1DIllegalSwap        (rem-outside-tile reverses δ=+1)
--- PASS: TestLoopIndependentAndSelfOutput (A[i]=A[i]+1 plus A[i]=A[i-1])
--- PASS: Test2DTilingIdentityIllegal     (δ=(1,-5), tile-major → illegal)
--- PASS: TestFindLegalSchedule           (alternate schedule re-verified)
--- PASS: TestInterleavedAlwaysLegal      (interleaved order, 300 nests)
PASS

The tests assert:

4.3 Randomized cross-check vs. brute force

TestRandomCrossCheck builds 1500 random nests (D ∈ {1,2,3}, bounds of width ≤ 3, 1–3 accesses, random affine subscripts, random tile sizes ∈ {1,2,3}, random (2D)! permutation) and requires

BruteForce.Legal == Analyze.Legal

for every case, and that every polyhedral witness verifies. Result:

$ go test -run TestRandomCrossCheck -v
--- PASS: TestRandomCrossCheck

TestDirectionsCrossCheck additionally requires the polyhedral FeasibleDirections direction set to equal the brute-force CollectDependences set on 400 random nests:

--- PASS: TestDirectionsCrossCheck

Full suite:

$ go test ./...
ok  example.com/polyhedral   38.5s

4.4 Why the verification is meaningful


5. Assumptions / boundaries

Source: /workspace/polyhedral/solver.go, /workspace/polyhedral/solver_test.go, /workspace/polyhedral/cmd/polytile/main.go. A copy of this document is at /workspace/SOLUTION.md and ~/SOLUTION.md.

Evidence & signatures

# Evidence
- Problem class: go-polyhedral-loop-tiling-dependence-validity-exactness
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-25T10:25:16.472Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Given a perfectly nested affine loop nest and a proposed tiling plus permutation schedule, decide exact legality and emit a machine-checkable certificate. Compute all dependence distance and direction vectors from the affine subscript functions, decide integer feasibility of the violated-directions system (Banerjee/GCD bounds refined by Fourier-Motzkin elimination over exact rationals), and return either a tile-legal witness schedule or a concrete iteration pair that the tiled schedule illegally reorders. Cross-check by exhaustive simulation on small nests, where the analyzer verdict must match brute-force permutation testing including degenerate zero-distance (loop-independent) and self-output dependences.", "environment": "go1.26", "language": "go", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "go-polyhedral-loop-tiling-dependence-validity-exactness", "provider": "openrouter", "solved_at": "2026-09-25T10:25:16.474Z", "version": "1.26"}
Generated from the verified corpus · MIT licensedBack to the catalog