Files
simul/learning/M0+.md
Myeongseon Choi dffa67d505 docs: reorder M0+ — lattice canary first, trait fix after decision gate
trait 정렬 fix 가 후속의 base 라는 직관적 의존성은 실제로는 약함:
1D random walker 는 simul-core trait 만 사용하므로 simul-euclidean
ForceInteraction 부정합과 독립이다. 반면 trait fix 의 *최종 모양*
(Handle 을 simul-core 로 lift 할지, EuclideanInteraction sub-trait
으로 둘지) 은 두 데이터 포인트 (Euclidean MD + Lattice) 가 있어야
근거 있게 결정됨.

따라서 M0+ 단위 순서를 1↔2 swap + 결정 게이트 신규 §2 추가:

  (구) 1. Trait fix → 2. canary → 3-7. forces/wrappers
  (신) 1. canary → 2. 추상 재설계 결정 → 3. Trait fix → 4-8.

PROGRESS.md §1 M0+ 표 행 재배치, §6 다음 한 단위 갱신.
learning/M0+.md 섹션 순서 물리 재배치 + 새 §2 결정 게이트 추가.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 00:05:58 +09:00

15 KiB
Raw Permalink Blame History

M0+ 컨텍스트 패키지 — 즉시 시작 가능한 6 단위

마일스톤 정의: ROADMAP §8.1 의 M0+. 학습자가 지금 당장 시작 가능한 6 단위 + Tier-1 wrapper 14건. 추정 기간: 23주 (단위 6개) + 며칠 (wrapper 14건) = 34주. DoD: PROGRESS.md §1 의 M0+ DoD.


추천 순서

단위 시간 의존
1 simul-lattice canary (1D random walker) 1주 — (simul-core 만 사용, trait fix 와 독립)
2 추상 재설계 결정 한나절 (1) — canary 결과로 Handle을 simul-core lift할지 결정
3 Trait 정렬 fix 한나절~1일 (2) — 결정된 모양으로 실행
4 RMSD / RG / OrientationRestraint 45일 (3)
5 AndersenThermostat → Thermostat trait 1일 (3)
6 Tier-1 wrapper 14건 며칠 (3)~(5)

(1)(3) 은 아키텍처 작업이다 — 추상이 lattice + euclidean 두 데이터 포인트로 결정된 후 trait fix 실행. (4)(6) 은 구현 작업. canary 가 trait fix 에 의존하지 않는 이유: 1D random walker 는 Dynamics<Lattice<1>> + StateSpace 만 사용하며 simul-euclidean 의 ForceInteraction 과 무관 — 부정합과 독립.


1. simul-lattice canary (1D random walker)

배경

ROADMAP §11.6-(a). simul-core trait 가 MD-specific 으로 부풀어 오르는 것을 잡기 위한 살아있는 가드레일.

단계

  1. crate skeleton:
    simul-lattice/
    ├── Cargo.toml          # depends on simul-core only
    └── src/
        ├── lib.rs
        ├── space.rs        # Lattice<const D: usize> : StateSpace
        ├── dynamics.rs     # RandomWalk1D : Dynamics<Lattice<1>>
        └── prelude.rs
    
  2. simul/Cargo.toml workspace memberssimul-lattice 추가
  3. Lattice<D>: StateSpace 구현:
    pub struct Lattice<const D: usize>;
    impl<const D: usize> StateSpace for Lattice<D> {
        const DIM: usize = D;
        type Point = SVector<i64, D>;
        type Momentum = ();
        fn is_continuous() -> bool { false }
        fn name() -> &'static str { "Lattice" }
    }
    
  4. RandomWalk1D: Dynamics<Lattice<1>> 구현:
    impl Dynamics<Lattice<1>> for RandomWalk1D {
        fn step<R: Rng>(&self, state: &mut SystemState<Lattice<1>>, rng: &mut R) -> f64 {
            for p in state.positions.iter_mut() {
                p[0] += if rng.random_bool(0.5) { 1 } else { -1 };
            }
            1.0  // discrete step
        }
        fn time_type(&self) -> TimeType { TimeType::Discrete }
        fn is_deterministic(&self) -> bool { false }
        fn name(&self) -> &'static str { "RandomWalk1D" }
    }
    
  5. example: simul-lattice/examples/random_walk_1d.rs — 1000 step 후 평균/분산 출력
  6. canary 테스트: simul-lattice/tests/canary.rs — N=1000 walker, t=1000 step 후 <x²> ≈ t (diffusion 1)

Definition of Done

  • cargo test -p simul-lattice 통과
  • cargo run -p simul-lattice --example random_walk_1d 출력이 <x²> ≈ 1000 ± 100
  • PROGRESS.md §4 의 (a) Lattice canary 🔴 미설치
  • DESIGN.md §"Workspace Structure" 의 simul-lattice 항목 갱신 (canary 만 active)

함정

  • SystemState<Lattice<1>>positions: Vec<SVector<i64, 1>>, momenta: Vec<()>, masses: Vec<f64> 를 들고 있음. masses 는 lattice 에서 무의미 — Default 로 zero. 향후 SystemState 에 lattice-incompatible 필드 추가 시 여기서 컴파일 깨짐. 이게 canary 의 작동 방식.
  • simul-lattice/Cargo.toml 의 dependency 는 simul-core 만 (simul-euclidean 의존 절대 금지 — 그러면 canary 가 의미 없음).

학습 가치

. 추상화 검증의 살아있는 코드 기법. const generic + StateSpace + Dynamics 의 모든 trait 가 진짜 일반적인지 확인. 200 LOC 로 trait drift 영구 가드.

참고

  • ROADMAP §11.6, §12
  • .team-output/T6-rust-architect.md §"DESIGN 에 없지만 OpenMM 에 있는 기능" — lattice 자체는 OpenMM 에 없지만 추상은 호환
  • DESIGN.md §"Lattice"

2. 추상 재설계 결정

배경

canary 구현이 끝난 시점의 결정 게이트. simul-core::Interaction 에 device handle 개념을 lift 할지, simul-euclidean 에만 sub-trait 으로 둘지를 두 데이터 포인트 (Euclidean MD + Lattice random walker) 기반으로 결정. 추상을 예측 이 아니라 발견 으로 정의.

결정 트리

  • canary 가 host Vec<i64> 만으로 충분 (기대 시나리오) → Handle 을 simul-core 에 올리지 않음. EuclideanInteraction: Interaction<Euclidean<D>, Output = ForceOutput<D>> sub-trait 이 device path 를 보유. §3 Trait 정렬 fix 는 sub-trait 추가만 (한나절).
  • canary 가 어떤 형태든 buffer/storage 추상을 자연스럽게 요구StateSpace::Buffer associated type 을 simul-core 에 도입. SystemState 리팩터 동반 → 한나절 스코프 초과 → 별도 마일스톤으로 격상.
  • 결정 보류 (1D random walker 가 너무 trivial 해서 데이터가 부족) → "현재로서 lift 할 근거 없음, M3 (lattice MC 본격) 시 재평가" 로 결정. 결정 자체도 결정.

Definition of Done

  • 결정 문서 learning/decisions/abstraction-after-canary.md 작성 (1페이지)
  • DESIGN.md "Core Abstractions" 의 trait 다이어그램에 결정 반영
  • §3 Trait 정렬 fix 의 구체 시그니처 (이름: EuclideanInteraction 권장) 가 결정됨

함정

  • 아키텍처를 예쁘게 만들려고 lattice 가 필요로 하지 않는 추상을 simul-core 에 끌어오지 말 것. YAGNI.
  • 반대로, canary 에서 명백히 device-like 추상이 필요한데 simul-euclidean 에만 두면 다음 lattice 작업 (M3) 에서 또 trait drift 가 생긴다. 두 방향 모두 위험.
  • 결정 문서를 만들지 않으면 "왜 이 모양이지?" 가 6개월 후 잊힘 → 반드시 짧게라도 기록.

학습 가치

. 추상을 예측 이 아니라 발견 으로 정의하는 절차 자체. 결정 문서화 패턴 ADR (Architecture Decision Record).

참고

  • 본 M0+.md §1 (canary 결과)
  • ROADMAP §6 P1, §11.6
  • .team-output/T6-rust-architect.md §3.1 (현 trait 부정합 진단)
  • .team-output/T7-rust-architect.md §P1

3. Trait 정렬 fix

배경 (T6 §3.1)

현재:

// simul-core/src/interaction.rs
pub trait Interaction<S: StateSpace>: Send + Sync + Debug {
    type Output;
    fn compute(&self, state: &SystemState<S>) -> Self::Output;
    fn name(&self) -> &'static str;
}

// simul-euclidean/src/interaction/mod.rs
pub trait ForceInteraction<const D: usize> {
    fn compute_forces(
        &self,
        client: &Client,
        positions: &Handle,
        forces: &mut Handle,
        n: usize,
    ) -> f64;
}

ForceInteractionInteraction 을 구현하지 않는다. 두 trait 가 평행 — Interaction::Output associated type 이 lattice 까지 수용 가능한 추상인데 ForceInteraction 이 그 추상을 우회 한다.

권고 (T7 P1, §2 결정 결과 반영)

§2 의 결정에 따라 두 가지 모양 중 하나:

(a) sub-trait (Handle simul-core 에 lift 안 함):

// simul-euclidean
pub trait EuclideanInteraction<const D: usize>:
    Interaction<Euclidean<D>, Output = (DeviceForces, f64)>
{
    fn compute_forces(...);  // 기존 시그니처 유지
}

(b) Buffer associated type (Handle 을 simul-core 로 lift):

// simul-core
pub trait StateSpace {
    type Point;
    type Momentum;
    type Buffer;  // Handle for Euclidean, Vec for Lattice
    ...
}

(b) 채택 시 SystemState 리팩터 동반 → 별도 마일스톤. (a) 가 한나절 스코프 기본값.

또는 간단하게: Interaction::compute()ForceInteraction::compute_forces 의 wrapper 로 자동 구현하는 default impl 추가 — (a) 의 변형.

Definition of Done

  • simul-core::InteractionEuclideanInteraction (구 ForceInteraction) 의 super-trait
  • cargo test --workspace 통과 (nonbonded_openmm.rs / harmonic_bond_openmm.rs 무수정)
  • _template_openmm.rs 상단의 "trait 부정합 (T6 §3.1) 때문에 일시적" 주석 갱신 또는 제거
  • DESIGN.md §"Core Abstractions" 의 trait 다이어그램 갱신

함정

  • Interaction::OutputForceInteraction::compute_forces 의 반환 타입이 다르면 super-trait 관계가 안 됨 → associated type 으로 통합
  • Send + Sync + Debug + 'static bound 일관성

학습 가치

. Rust trait 의 sub-trait + associated type 조합. where Self: SuperTrait<...> ergonomic.

참고 자료

  • ROADMAP §6 P1
  • .team-output/T6-rust-architect.md §3.1
  • .team-output/T7-rust-architect.md §P1

4. RMSDForce → RmsdInteraction<D>

배경

OpenMM RMSDForce: 두 입자 set 사이의 root-mean-square deviation. 보통 reference 분자와 정렬 후 RMSD 계산. TheobaldLiu (quaternion-based) 알고리즘이 표준.

simul 측

  • 위치: simul-euclidean/src/interaction/restraint.rs 신설
  • 타입: pub struct RmsdInteraction<const D: usize> { reference: Vec<SVector<f64, D>>, k: f64 }
  • ForceInteraction<D> 구현 (trait fix 후)

Definition of Done

  • 5 원자 시스템에서 reference 와 동일한 좌표 → RMSD = 0, force = 0
  • 균일 회전 → RMSD = 0 (rotation-invariant)
  • 균일 이동 → RMSD = 0 (translation-invariant)
  • Tier-1 테스트 simul-euclidean/tests/rmsd_openmm.rs 작성 (_template_openmm.rs 복사 후 채움)
  • reference Python 스크립트 tests/reference/openmm_rmsd.py

함정

  • D=3 만 의미 있음 (회전이 정의되는 차원). const generic 으로 두지만 D=3 만 구현, 다른 D 에서는 unimplemented!() 또는 compile_error!().
  • Quaternion 의 부호 모호성 (q ↔ q 는 같은 회전).
  • 미분 가능 — Theobald 알고리즘은 dRMSD/dr_i 가 closed-form.

학습 가치

. 회전 불변, 최소제곱 정렬, 사원수 — 분자 시뮬의 표준 도구.

참고

  • ROADMAP §7.1 #3 (Top 10)
  • T2 §2-A 코어 표준 Force #13
  • T7 P1
  • Theobald, D. L. (2005). Acta Cryst A. doi:10.1107/S0108767305015266

5. RGForce → RgInteraction<D>

배경

Radius of gyration: R_g² = Σᵢ |rᵢ r_cm|² / N. 또는 mass-weighted: Σᵢ mᵢ |rᵢ r_cm|² / Σᵢ mᵢ.

simul 측

  • 위치: simul-euclidean/src/interaction/restraint.rs (RMSD 옆)
  • 타입: pub struct RgInteraction<const D: usize> { target_rg: f64, k: f64, mass_weighted: bool }
  • 단순: 미분도 명시적

Definition of Done

  • 단일 입자 → R_g = 0
  • 두 입자 거리 d → R_g = d/2
  • Tier-1 테스트 simul-euclidean/tests/rg_openmm.rs
  • reference tests/reference/openmm_rg.py

함정

  • mass_weighted = true 면 simul SystemState::masses 를 사용. 학습자는 state.masses 의 길이가 state.positions 와 일치하는지 unit test.

학습 가치

중-하. 단순한 수식이지만 RMSD 와 묶어서 "결합 가능한 관측량" 패턴.

참고

  • ROADMAP §7.1 #3
  • T2 §2-A #14

6. OrientationRestraintForce

배경

참조 분자에 대한 회전 제약. E = k · (1 cos²(θ)) 또는 quaternion 기반.

simul 측

  • 위치: simul-euclidean/src/interaction/restraint.rs
  • 타입: pub struct OrientationRestraintInteraction<const D: usize> { reference: ..., k: f64 }
  • D=3 만 구현

Definition of Done

  • reference 와 동일 회전 → energy = 0
  • 90° 회전 → energy = k
  • Tier-1 테스트 orientation_restraint_openmm.rs
  • reference tests/reference/openmm_orientation.py

함정

  • 회전 행렬 vs quaternion 표현 선택. 미분 ergonomic 은 quaternion.
  • 부호 모호성.

학습 가치

. 강체 회전 + restraint. M8 의 VirtualSite 에서 재사용.

참고

  • ROADMAP §7.1 #3
  • T2 §2-A #15
  • T7 P5 (VirtualSite — 회전 표현 공유)

7. AndersenThermostat → Thermostat trait

배경

일정 확률 ν · dt 로 입자의 속도를 MaxwellBoltzmann 분포에서 새로 추첨. 캐노니컬 앙상블 (NVT) 의 단순 구현.

simul 측

  • 위치: simul-euclidean/src/dynamics/thermostat.rs 신설
  • 새 trait: Thermostat: VelocityModifier (T7 P12 의 일부)
  • 기존 Dynamics 와 합성 가능 (Compound 패턴, M3 에서 본격화)
  • 단발 구현: AndersenThermostat { temperature, frequency, dt }step 마다 일부 입자 속도 재추첨

Definition of Done

  • Thermostat trait 정의 + 문서
  • AndersenThermostat: Thermostat 구현
  • Tier-1 단발 테스트: 단일 step 에서 reseed 된 입자의 속도 분포가 MaxwellBoltzmann
  • (선택) Tier-2 통계 테스트: 1000 step 평균 KE = 3/2 N k_B T (4σ 비교)

함정

  • frequency 가 너무 크면 deterministic 동역학 손상. 0.1 / ps 가 표준.
  • ThermostatForce 가 아님. T7 P12 의 권고대로 별도 trait.
  • 추후 NoseHoover (M7) 도 같은 trait 구현 → 다형성 검증.

학습 가치

. NVT 앙상블, stochastic vs deterministic 의 구분, trait 다형성 (Thermostat).

참고

  • ROADMAP §7.1 #5 (Top 10)
  • T2 §2-C (Force-derived 보조 #1)
  • T7 P12

8. Tier-1 wrapper 14건

배경

tests/UPSTREAM_TESTS.md §2 의 "현재 시점 ~14개" 게이팅. 새 force/integrator 구현 이 아니라 기존 simul 의 등가성 검증 을 추가.

리스트 (출처: T5 addendum §3)

  1. harmonic_angle_openmm.rs (M1 후)
  2. periodic_torsion_openmm.rs (M1 후)
  3. rb_torsion_openmm.rs (M1 후)
  4. cmap_torsion_openmm.rs (M1 후)
  5. gbsaobc_openmm.rs (M0+ 가능)
  6. lcpo_openmm.rs (M0+ 가능)
  7. rmsd_openmm.rs (#3 와 함께)
  8. rg_openmm.rs (#4 와 함께)
  9. orientation_restraint_openmm.rs (#5 와 함께)
  10. gay_berne_openmm.rs (M2 후)
  11. andersen_openmm.rs (#6 와 함께)
  12. verlet_single_step_openmm.rs (단발)
  13. langevin_middle_single_step_openmm.rs (단발)
  14. brownian_single_step_openmm.rs (단발)

#1~#4, #10 은 M1/M2 후로 게이팅. M0+ 에서 즉시 작성 가능한 것은 #5~#9, #11~#14 = 9건.

작성 패턴 (모든 14건 동일)

  1. _template_openmm.rs 복사 → <name>_openmm.rs
  2. #![cfg(any())] 첫 줄 삭제
  3. FILL IN 12군데 채움
  4. tests/reference/openmm_<name>.py 작성 (PDB SHA = 46376ea3...)
  5. Python 출력 → 15 자리 reference 값 hard-code
  6. cargo test --test <name>_openmm 통과 확인

Definition of Done

  • 9건 (M0+ 가능 분) 작성 완료
  • PROGRESS.md §0 의 "현재 Tier-1" = 2 → 11 (existing 2 + new 9)
  • 5건 (M1/M2 게이팅) 은 해당 마일스톤 종료 시 추가

함정

  • 단위 테스트 (#[test]) 가 너무 많아 cargo build 시간 증가. tests/common/mod.rs 추출 권고 (T5 §3).
  • 5/8/11 은 simul 측 구현이 부분적이라 Tier-1 일부만 가능.

학습 가치

. 14 회 반복으로 패턴 fluency. 매 작업 12시간 (작성 30분 + Python reference 30분 + 검증 30분).

참고

  • tests/UPSTREAM_TESTS.md §2 game 표
  • T5 본문 §3 작성 컨벤션
  • _template_openmm.rs 자체

M0+ 종료 후 (M1 진입 시)

  1. PROGRESS.md §1 M0+ 모든 항목 확인
  2. learning/canary-check.md 의 prompt 로 4중 방어선 게이트 점검
  3. 통과 시 learning/todo-generator.md 로 M1 컨텍스트 패키지 생성 → learning/M1.md 저장
  4. ROADMAP §8.1 의 M0+ 누적 LOC / Tier-1 실측치를 기재 → 추정과 ±20% 이상 차이나면 M1+ 시간 추정 재조정