wip: working copy state at jj git init
This commit is contained in:
parent
857fa6ceb4
commit
5b2fdc7d59
217 changed files with 639 additions and 7 deletions
7
compiler/lagrangia/Cargo.lock
generated
Normal file
7
compiler/lagrangia/Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "lagrangia"
|
||||
version = "0.1.0"
|
||||
13
compiler/lagrangia/Cargo.toml
Normal file
13
compiler/lagrangia/Cargo.toml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "lagrangia"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Lagrangia reducer: action functional + variational selection over Speckl candidate implementations"
|
||||
|
||||
[lib]
|
||||
name = "lagrangia"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "toggle_switch"
|
||||
path = "tests/toggle_switch.rs"
|
||||
10
compiler/lagrangia/src/lib.rs
Normal file
10
compiler/lagrangia/src/lib.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
//! Lagrangia reducer — the spec-as-Lagrangian probe.
|
||||
//!
|
||||
//! Sits between Speckl's IR and its Rust codegen. Given candidate
|
||||
//! implementations, scores them by an action functional and selects
|
||||
//! the stationary (minimum-action) one.
|
||||
//!
|
||||
//! See `~/.hermes/plans/2026-07-18-lagrangia-reducer-spec.md`.
|
||||
pub mod score;
|
||||
|
||||
pub use score::{action, byte_entropy, complexity, invariant_distance, ImplCandidate};
|
||||
154
compiler/lagrangia/src/score.rs
Normal file
154
compiler/lagrangia/src/score.rs
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
//! Action functional for the Lagrangia reducer.
|
||||
//!
|
||||
//! Spec §2.3: `S(impl) = w1·complexity + w2·invariant_distance + w3·byte_entropy`
|
||||
//! with v0 weights `w1=1.0, w2=100.0, w3=0.1`.
|
||||
//!
|
||||
//! The invariant_distance term dominates: any implementation that doesn't
|
||||
//! satisfy the spec has action ≥ 100, any that does has action < 50 (for specs
|
||||
//! under ~50 lines). This makes the "stationary" point provably the simplest
|
||||
//! correct implementation — the literal variational claim.
|
||||
|
||||
/// A candidate implementation in the search manifold.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ImplCandidate {
|
||||
pub id: u64,
|
||||
pub rust_source: String,
|
||||
/// Invariant verification result. `true` = invariants hold (distance 0),
|
||||
/// `false` = counterexample found (distance = counterexample depth).
|
||||
/// v0 proxy: depth is estimated from the source; full Z3 wiring is a
|
||||
/// follow-up (see module notes).
|
||||
pub invariant_holds: bool,
|
||||
/// Estimated counterexample depth when `invariant_holds == false`.
|
||||
/// 0 means "not yet scored"; higher = further from satisfying invariants.
|
||||
pub counterexample_depth: u32,
|
||||
}
|
||||
|
||||
/// v0 weights from spec §2.3.
|
||||
pub const W_COMPLEXITY: f64 = 1.0;
|
||||
pub const W_INVARIANT_DISTANCE: f64 = 100.0;
|
||||
pub const W_BYTE_ENTROPY: f64 = 0.1;
|
||||
|
||||
/// `complexity(impl)` — lines of generated Rust code (spec §2.3, row 1).
|
||||
///
|
||||
/// Counts non-empty, non-comment lines to avoid trivial inflation.
|
||||
pub fn complexity(source: &str) -> f64 {
|
||||
source
|
||||
.lines()
|
||||
.filter(|line| {
|
||||
let trimmed = line.trim();
|
||||
!trimmed.is_empty() && !trimmed.starts_with("//")
|
||||
})
|
||||
.count() as f64
|
||||
}
|
||||
|
||||
/// `invariant_distance(impl)` — how far the implementation is from satisfying
|
||||
/// each invariant (spec §2.3, row 2).
|
||||
///
|
||||
/// Spec calls for Z3 counterexample depth. v0 proxy: if `invariant_holds`
|
||||
/// is true, distance = 0. Otherwise, distance = `counterexample_depth`
|
||||
/// (estimated statically; full Z3 wiring is a follow-up note).
|
||||
pub fn invariant_distance(candidate: &ImplCandidate) -> f64 {
|
||||
if candidate.invariant_holds {
|
||||
0.0
|
||||
} else {
|
||||
candidate.counterexample_depth.max(1) as f64
|
||||
}
|
||||
}
|
||||
|
||||
/// `byte_entropy(impl)` — Shannon entropy of the generated source bytes
|
||||
/// (spec §2.3, row 3), in bits per byte.
|
||||
///
|
||||
/// Returns 0.0 for empty input (degenerate case, avoids div-by-zero).
|
||||
pub fn byte_entropy(source: &[u8]) -> f64 {
|
||||
if source.is_empty() {
|
||||
return 0.0;
|
||||
}
|
||||
let mut counts = [0u32; 256];
|
||||
for &b in source {
|
||||
counts[b as usize] += 1;
|
||||
}
|
||||
let total = source.len() as f64;
|
||||
let mut entropy = 0.0;
|
||||
for &c in &counts {
|
||||
if c == 0 {
|
||||
continue;
|
||||
}
|
||||
let p = c as f64 / total;
|
||||
entropy -= p * p.log2();
|
||||
}
|
||||
entropy
|
||||
}
|
||||
|
||||
/// `S(impl)` — the action functional (spec §2.3).
|
||||
///
|
||||
/// `S = w1·complexity + w2·invariant_distance + w3·byte_entropy`
|
||||
pub fn action(candidate: &ImplCandidate) -> f64 {
|
||||
W_COMPLEXITY * complexity(&candidate.rust_source)
|
||||
+ W_INVARIANT_DISTANCE * invariant_distance(candidate)
|
||||
+ W_BYTE_ENTROPY * byte_entropy(candidate.rust_source.as_bytes())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod unit_tests {
|
||||
use super::*;
|
||||
|
||||
fn candidate(source: &str, holds: bool, depth: u32) -> ImplCandidate {
|
||||
ImplCandidate {
|
||||
id: 0,
|
||||
rust_source: source.to_string(),
|
||||
invariant_holds: holds,
|
||||
counterexample_depth: depth,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complexity_counts_non_comment_non_empty_lines() {
|
||||
let src = "// a comment\nlet x = 1;\n\n// another\nlet y = 2;\n";
|
||||
assert_eq!(complexity(src), 2.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invariant_distance_zero_when_holds() {
|
||||
let c = candidate("fn main() {}", true, 0);
|
||||
assert_eq!(invariant_distance(&c), 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invariant_distance_uses_depth_when_fails() {
|
||||
let c = candidate("fn main() {}", false, 5);
|
||||
assert_eq!(invariant_distance(&c), 5.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invariant_distance_floors_to_one_when_unscored() {
|
||||
let c = candidate("fn main() {}", false, 0);
|
||||
assert_eq!(invariant_distance(&c), 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_entropy_uniform_is_eight_bits() {
|
||||
// 256 bytes, one of each value → 8 bits
|
||||
let bytes: Vec<u8> = (0u16..256).map(|b| b as u8).collect();
|
||||
let e = byte_entropy(&bytes);
|
||||
assert!((e - 8.0).abs() < 1e-9, "got {e}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn byte_entropy_zero_for_empty() {
|
||||
assert_eq!(byte_entropy(&[]), 0.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn action_dominated_by_invariant_distance() {
|
||||
// A correct impl: complexity ~5, inv dist 0, entropy ~4 → action ~5.4
|
||||
let correct = candidate("fn main() {\n let x = 1;\n let y = 2;\n}\n", true, 0);
|
||||
// An incorrect impl: complexity ~5, inv dist 10, entropy ~4 → action ~1005.4
|
||||
let incorrect = candidate("fn main() {\n let x = 1;\n let y = 2;\n}\n", false, 10);
|
||||
let a_correct = action(&correct);
|
||||
let a_incorrect = action(&incorrect);
|
||||
assert!(
|
||||
a_incorrect - a_correct > 100.0,
|
||||
"invariant_distance should dominate: correct={a_correct}, incorrect={a_incorrect}"
|
||||
);
|
||||
}
|
||||
}
|
||||
1
compiler/lagrangia/target/.rustc_info.json
Normal file
1
compiler/lagrangia/target/.rustc_info.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"rustc_fingerprint":16580640190452207998,"outputs":{"17747080675513052775":{"success":true,"status":"","code":0,"stdout":"rustc 1.91.1 (ed61e7d7e 2025-11-07) (built from a source tarball)\nbinary: rustc\ncommit-hash: ed61e7d7e242494fb7057f2657300d9e77bb4fcb\ncommit-date: 2025-11-07\nhost: x86_64-unknown-linux-gnu\nrelease: 1.91.1\nLLVM version: 21.1.7\n","stderr":""},"7971740275564407648":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/nix/store/3sgpdha064vl7i8dr7g3d5wrc082d6g5-rustc-1.91.1\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}
|
||||
3
compiler/lagrangia/target/CACHEDIR.TAG
Normal file
3
compiler/lagrangia/target/CACHEDIR.TAG
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Signature: 8a477f597d28d172789f06886806bc55
|
||||
# This file is a cache directory tag created by cargo.
|
||||
# For information about cache directory tags see https://bford.info/cachedir/
|
||||
0
compiler/lagrangia/target/debug/.cargo-lock
Normal file
0
compiler/lagrangia/target/debug/.cargo-lock
Normal file
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
This file has an mtime of when this was started.
|
||||
|
|
@ -0,0 +1 @@
|
|||
9e5b6b8388e83e02
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"rustc":8999539375451197318,"features":"[]","declared_features":"[]","target":6158130320494215290,"profile":1722584277633009122,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/lagrangia-4ac5ede15d49454c/dep-test-lib-lagrangia","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
This file has an mtime of when this was started.
|
||||
|
|
@ -0,0 +1 @@
|
|||
94465bfadc4cb201
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"rustc":8999539375451197318,"features":"[]","declared_features":"[]","target":6158130320494215290,"profile":8731458305071235362,"path":10763286916239946207,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/lagrangia-8f779a778ed86c6f/dep-lib-lagrangia","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
Binary file not shown.
|
|
@ -0,0 +1 @@
|
|||
This file has an mtime of when this was started.
|
||||
|
|
@ -0,0 +1 @@
|
|||
c7331d31e53a6e4b
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"rustc":8999539375451197318,"features":"[]","declared_features":"[]","target":5508210232129248235,"profile":1722584277633009122,"path":11149814207312358890,"deps":[[1962247874961037463,"lagrangia",false,122244651869226644]],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/lagrangia-bcf9fe144a78d857/dep-test-integration-test-toggle_switch","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
/home/sscoble/speckl/compiler/lagrangia/target/debug/deps/lagrangia-4ac5ede15d49454c.d: src/lib.rs src/score.rs
|
||||
|
||||
/home/sscoble/speckl/compiler/lagrangia/target/debug/deps/lagrangia-4ac5ede15d49454c: src/lib.rs src/score.rs
|
||||
|
||||
src/lib.rs:
|
||||
src/score.rs:
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
/home/sscoble/speckl/compiler/lagrangia/target/debug/deps/lagrangia-8f779a778ed86c6f.d: src/lib.rs src/score.rs
|
||||
|
||||
/home/sscoble/speckl/compiler/lagrangia/target/debug/deps/liblagrangia-8f779a778ed86c6f.rlib: src/lib.rs src/score.rs
|
||||
|
||||
/home/sscoble/speckl/compiler/lagrangia/target/debug/deps/liblagrangia-8f779a778ed86c6f.rmeta: src/lib.rs src/score.rs
|
||||
|
||||
src/lib.rs:
|
||||
src/score.rs:
|
||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,5 @@
|
|||
/home/sscoble/speckl/compiler/lagrangia/target/debug/deps/toggle_switch-bcf9fe144a78d857.d: tests/toggle_switch.rs
|
||||
|
||||
/home/sscoble/speckl/compiler/lagrangia/target/debug/deps/toggle_switch-bcf9fe144a78d857: tests/toggle_switch.rs
|
||||
|
||||
tests/toggle_switch.rs:
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue