← LabAlgorithm Reasoning · vertical slice

Binary Search Contract Lab

정답 코드를 외우는 화면이 아닙니다. specification을 고르고, 결과와 반례를 예측하고, comparison/update/return만 bounded patch한 뒤, 작은 입력을 전수 검사합니다. 각 source semantic step을 후보 영역·불변식·종료 measure와 함께 replay하고 다른 monotone predicate로 옮깁니다.

EXECUTION
browser-local semantic interpreter
EVIDENCE
linear oracle + invariant + progress
NOT CLAIMED
arbitrary source execution or learner mastery
Code versions

같은 코드를 universal label로 평가하지 않는다

half-open [lo, hi)non-termination
function boundarySearch(a, target) {
  let lo = 0;
  let hi = a.length;
  while (lo < hi) {
    const mid = lo + Math.floor((hi - lo) / 2);
    if (a[mid] < target) {
      lo = mid;
    } else {
      hi = mid;
    }
  }
  return lo;
}
specification

It returns the lower_bound only on paths that never need to discard mid from the left; it is not a total lower_bound implementation.

minimum counterexample / boundary

a = [1], target = 2: lo = 0, hi = 1, mid = 0, then lo = mid leaves the measure 1 -> 1.

loop invariant

The answer boundary may remain inside [lo, hi], so partial correctness alone does not prove termination.

why it terminates

Not established. The true branch can preserve hi - lo, and the lab stops with non-termination evidence immediately.

comparison + space

No finite comparison bound on the counterexample; auxiliary algorithm state is O(1).

reuse that is earned

No new reuse is created by retaining mid; the update contradicts the half-open progress contract.

micro-step 1 / 7

Non-shrinking half-open update · deterministic counterexample replay

array is sorted ascending

lo
1
0
hi
sentinel
1
candidate eliminated mid
source semantic · precondition
Precondition: array is sorted ascending
interval = [0, 1) · lo=0 · mid=— · hi=1
current predicate / result
No predicate at this semantic step.
returned result = not yet
loop invariant
HOLDS · boundary b stays inside 0 <= b <= 1; eliminated left is false and eliminated right is true
bounds=true, b=1 contained=true, left=true, right=true
termination measure
hi - lo · 1 → 1
current measure = 1 · predicate comparisons so far = 0
run evidence · status=non-termination · result=null · linear-oracle=1 · comparisons=1/1 bound

Inclusive [lo, hi]

initial
lo = 0, hi = n - 1
guard
lo <= hi
discard
lo = mid + 1 / hi = mid - 1
empty
lo > hi
measure
hi - lo + 1

Half-open [lo, hi)

initial
lo = 0, hi = n
guard
lo < hi
discard
lo = mid + 1 / hi = mid
empty
lo === hi
measure
hi - lo
Arithmetic contract

작은 배열 테스트가 숨기는 integer midpoint overflow

(lo + hi) / 2 · Java int32 model
-397,483,648
lo + (hi - lo) / 2
1,750,000,000

EXACT operands: lo=1,500,000,000, hi=2,000,000,000. Java의 signed 32-bit addition을 별도로 모델링했습니다. 이 숫자는 배열을 실제 할당하거나 wall-time을 측정한 결과가 아닙니다.

Learning loop · 01

Specification을 먼저 잠근다

precondition

a is sorted ascending; duplicates are allowed.

postcondition

Return the smallest i in [0, n] such that i === n or a[i] >= target.

reference linear oracle

A linear scan stops at the first value that is not below target; n is the sentinel result.

boundary predicate

P(i) := a[i] >= target.

Learning loop · 02

결과와 failure mode를 보기 전에 예측한다

Learning loop · 03

comparison / update / return만 bounded patch한다

이 editor는 JavaScript executor가 아닙니다. 전체 13줄 skeleton을 검사한 뒤 네 finite semantic token만 pure interpreter에 전달합니다. source는 browser 밖으로 보내거나 compile하지 않습니다.

prediction receipt를 잠그면 patch editor가 열립니다.

MATCHED · array · value-lt-target · lo-mid-plus-one · hi-mid · lo
Learning loop · 04

작은 입력 전수 검사로 최소 반례를 찾는다

예측 receipt를 먼저 잠가야 합니다.

Learning loop · 05

counterexample 또는 representative trace를 끝까지 replay한다

🔒 전수 검사를 실행하면 첫 반례를, 모두 통과하면 현재 입력 trace를 공개합니다.
Learning loop · 06

partial correctness와 termination을 따로 방어한다

🔒 전수 검사에서 반례 0개인 patch가 필요합니다. 작은 범위 통과는 proof 연습의 입력일 뿐 보편적 정답 인증이 아닙니다.
Learning loop · 07

같은 boundary proof를 다른 monotone predicate로 옮긴다

🔒 proof defense 3/3 뒤에 transfer가 열립니다.