LAWS.bend open laws/TODOs
raw source on the hub · import 0xdf198d67659100c90a58ecd6b01d034d/LAWS.bend as LAWS
14 imports
import Base import ./geom.bend as G import ./protein.bend as P import ./topology.bend as T import ./force.bend as F import ./rmsd.bend as R import ./sasa.bend as S import ./rng.bend as Rng import ./pdb.bend as Pdb import ./par.bend as Par import ./bonded.bend as B import ./pbc.bend as Pbc import ./sim.bend as Sim import ./tpl.bend as Tpl
Laws
law count_below_nil provedin PROOF.bendsource · line 23 · raw
@qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.count_below(empty_atoms, qp, c2) == 0n : Nat}Counting contacts in an empty set finds nothing, at any point and cutoff.
law has_close_nil provedin PROOF.bendsource · line 29 · raw
@qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @min2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.has_close(empty_atoms, qp, min2) == False{} : Bool}An empty set has no clash, at any point and threshold.
law sum_dist2_nil provedin PROOF.bendsource · line 38 · raw
@qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.sum_dist2(empty_atoms, qp) == 0.0 : F32}Spread of nothing is zero.
law contacts_between_nil provedin PROOF.bendsource · line 43 · raw
@ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.contacts_between(empty_atoms, ys, c2) == 0n : Nat}An empty set links nothing to anything.
law min_dist2_nil provedin PROOF.bendsource · line 49 · raw
@qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.min_dist2_to(empty_atoms, qp) == None{} : Maybe<&2, F32>}No closest approach exists from an empty set.
law complex_atoms_nil provedin PROOF.bendsource · line 54 · raw
{0xdf198d67659100c90a58ecd6b01d034d/protein.Complex.num_atoms(empty_cx) == 0n : Nat}An empty complex holds no atoms.
law lj_nil provedin PROOF.bendsource · line 58 · raw
@eps:F32 -> @sig2:F32 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.lj_total(empty_atoms, empty_atoms, eps, sig2, c2) == 0.0 : F32}LJ energy of nothing is zero, at any parameters.
law rmsd_nil provedin PROOF.bendsource · line 67 · raw
{0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd(empty_atoms, empty_atoms) == 0.0 : F32}The empty set is at zero RMSD from itself (empty case, by computation). (This says nothing about nonempty sets; see rmsd_single. Unequal lengths silently answer 0 by zip semantics; see rmsd_checked_some/none.)
law sasa_nil provedin PROOF.bendsource · line 71 · raw
@rad:F32 -> @rc2:F32 -> @area_pt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sasa.sasa_all(empty_atoms, 0xdf198d67659100c90a58ecd6b01d034d/sasa.sasa_offsets, rad, empty_atoms, rc2, area_pt) == [] : List<&2, F32>}Nothing has no surface.
law sd_fuel0 provedin PROOF.bendsource · line 78 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.minimize(0n, xs, eps, sig2, c2, dt) == xs : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>}Zero minimization steps change nothing, on any input, not just nothing.
law count_cons provedin PROOF.bendsource · line 91 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.count_below(h <> t, qp, c2) == Nat.add(0xdf198d67659100c90a58ecd6b01d034d/topology.count_below(t, qp, c2), 0xdf198d67659100c90a58ecd6b01d034d/topology.head_hit_nat(h, qp, c2)) : Nat}Counting a cons cell is the head hit plus the count of the tail.
law contacts_cons provedin PROOF.bendsource · line 99 · raw
@x:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @xt:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.contacts_between(x <> xt, ys, c2) == Nat.add(0xdf198d67659100c90a58ecd6b01d034d/topology.contacts_between(xt, ys, c2), 0xdf198d67659100c90a58ecd6b01d034d/topology.contacts_of_head(x, ys, c2)) : Nat}Interface counting peels one head the same way.
law sumd2_count_cons provedin PROOF.bendsource · line 107 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.sumd2_count(h <> t, qp) == 0xdf198d67659100c90a58ecd6b01d034d/topology.sumd2_extend(0xdf198d67659100c90a58ecd6b01d034d/topology.head_dist2(h, qp), 0xdf198d67659100c90a58ecd6b01d034d/topology.sumd2_count(t, qp)) : Pair(F32, Nat)}The fused spread/count pass extends by one head distance.
law coord_cons provedin PROOF.bendsource · line 114 · raw
@x:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @xt:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.coord_counts(x <> xt, ys, c2) == 0xdf198d67659100c90a58ecd6b01d034d/topology.contacts_of_head(x, ys, c2) <> 0xdf198d67659100c90a58ecd6b01d034d/topology.coord_counts(xt, ys, c2) : List<&2, Nat>}Coordination counts peel one head.
law min_dist2_cons provedin PROOF.bendsource · line 122 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.min_dist2_to(h <> t, qp) == 0xdf198d67659100c90a58ecd6b01d034d/topology.min_cons(h, 0xdf198d67659100c90a58ecd6b01d034d/topology.min_dist2_to(t, qp), qp) : Maybe<&2, F32>}Closest-approach folds one head into the running best.
law min_link2_cons provedin PROOF.bendsource · line 129 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/topology.min_link2(h <> t, ys) == 0xdf198d67659100c90a58ecd6b01d034d/topology.min_maybe(0xdf198d67659100c90a58ecd6b01d034d/topology.min_link2(t, ys), 0xdf198d67659100c90a58ecd6b01d034d/topology.head_link(h, ys)) : Maybe<&2, F32>}Set linkage folds one head linkage into the running best.
law lj_row_cons provedin PROOF.bendsource · line 136 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/force.lj_row(pi, eps, sig2, c2, h <> t) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.lj_row(pi, eps, sig2, c2, t), 0xdf198d67659100c90a58ecd6b01d034d/force.lj_head(pi, eps, sig2, c2, h)) : F32}An LJ row over a cons cell splits head from tail.
law lj_total_cons provedin PROOF.bendsource · line 146 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.lj_total(h <> t, ys, eps, sig2, c2) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.lj_total(t, ys, eps, sig2, c2), 0xdf198d67659100c90a58ecd6b01d034d/force.lj_self_atom(h, ys, eps, sig2, c2)) : F32}An LJ total over a cons cell splits head from tail.
law coul_row_cons provedin PROOF.bendsource · line 156 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @qi:F32 -> @ke:F32 -> @c2:F32 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qh:F32 -> @qt:List<&2, F32> -> {0xdf198d67659100c90a58ecd6b01d034d/force.coul_row(pi, qi, ke, c2, h <> t, qh <> qt) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.coul_row(pi, qi, ke, c2, t, qt), 0xdf198d67659100c90a58ecd6b01d034d/force.coul_head(pi, qi, ke, c2, h, qh)) : F32}A Coulomb row splits head charge from tail charges.
law coul_total_cons provedin PROOF.bendsource · line 168 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qh:F32 -> @qt:List<&2, F32> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qs_e:List<&2, F32> -> @ke:F32 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.coul_total(h <> t, qh <> qt, ys, qs_e, ke, c2) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.coul_total(t, qt, ys, qs_e, ke, c2), 0xdf198d67659100c90a58ecd6b01d034d/force.coul_self(h, qh, ys, qs_e, ke, c2)) : F32}A Coulomb total splits head charge from tail charges.
law sd_sweep_cons provedin PROOF.bendsource · line 180 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @f:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @ft:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3> -> @dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.sd_sweep(h <> t, f <> ft, dt) == 0xdf198d67659100c90a58ecd6b01d034d/force.sd_move(h, f, dt) <> 0xdf198d67659100c90a58ecd6b01d034d/force.sd_sweep(t, ft, dt) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>}A sweep over cons cells moves the head and sweeps the tail.
law pair_sumd2_cons provedin PROOF.bendsource · line 189 · raw
@x:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @xt:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @y:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @yt:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/rmsd.pair_sumd2(x <> xt, y <> yt) == 0xdf198d67659100c90a58ecd6b01d034d/rmsd.pair_head(x, y, 0xdf198d67659100c90a58ecd6b01d034d/rmsd.pair_sumd2(xt, yt)) : Pair(F32, Nat)}A pair-distance fold splits the head pair from the tail pairs.
law rmsd_to_all_cons provedin PROOF.bendsource · line 197 · raw
@q:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @h:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @t:List<&2, List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>> -> {0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd_to_all(q, h <> t) == 0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd_against(q, h) <> 0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd_to_all(q, t) : List<&2, F32>}Scoring against a cons ensemble scores the head and the tail.
law count_single provedin PROOF.bendsource · line 206 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.count_below([h], qp, c2) == 0xdf198d67659100c90a58ecd6b01d034d/topology.head_hit_nat(h, qp, c2) : Nat}Counting one atom is that atom's hit.
law has_close_single provedin PROOF.bendsource · line 213 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @min2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.has_close([h], qp, min2) == 0xdf198d67659100c90a58ecd6b01d034d/topology.head_is_close(h, qp, min2) : Bool}One atom is close exactly when its head test says so.
law min_single provedin PROOF.bendsource · line 220 · raw
@s:U32 -> @e:U32 -> @x:F32 -> @y:F32 -> @z:F32 -> @qx:F32 -> @qy:F32 -> @qz:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.min_dist2_to([0xdf198d67659100c90a58ecd6b01d034d/protein.Atom{s, e, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{x, y, z}}], 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{qx, qy, qz}) == Some{0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3.dist2(0xdf198d67659100c90a58ecd6b01d034d/geom.V3{x, y, z}, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{qx, qy, qz})} : Maybe<&2, F32>}The closest approach to a singleton is its one distance.
law rg_about_nil provedin PROOF.bendsource · line 232 · raw
@qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.rg_about(empty_atoms, qp) == 0.0 : F32}Spread about a point of nothing is zero through rg_of.
law rmsd_single provedin PROOF.bendsource · line 237 · raw
@s:U32 -> @e:U32 -> @x:F32 -> @y:F32 -> @z:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd([0xdf198d67659100c90a58ecd6b01d034d/protein.Atom{s, e, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{x, y, z}}], [0xdf198d67659100c90a58ecd6b01d034d/protein.Atom{s, e, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{x, y, z}}]) == F32.sqrt(F32.div(F32.add(0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3.dist2(0xdf198d67659100c90a58ecd6b01d034d/geom.V3{x, y, z}, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{x, y, z}), 0.0), F32.from_nat(1n))) : F32}A singleton is at the RMSD its one pair distance dictates.
law rng_next_0 provedin PROOF.bendsource · line 246 · raw
{0xdf198d67659100c90a58ecd6b01d034d/rng.rng_next(0) == 1684164658 : U32}splitmix32 golden values (catches mistyped mixer constants).
law rng_next_1 provedin PROOF.bendsource · line 249 · raw
{0xdf198d67659100c90a58ecd6b01d034d/rng.rng_next(1) == 1580013426 : U32}
law sasa_single provedin PROOF.bendsource · line 253 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sasa.sasa_of([0xdf198d67659100c90a58ecd6b01d034d/protein.Atom{1, 6, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{0.0, 0.0, 0.0}}], 2.0, 16.0, 1.0) == [F32.mul(1.0, F32.from_nat(6n))] : List<&2, F32>}One atom with nothing near it exposes all six sample points.
law pair_trunc_right provedin PROOF.bendsource · line 259 · raw
@x:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @xt:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/rmsd.pair_sumd2(x <> xt, empty_atoms) == (0.0, 0n) : Pair(F32, Nat)}Pair folds against an empty list answer the identity.
law coul_trunc_charges provedin PROOF.bendsource · line 265 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qs:List<&2, F32> -> @ke:F32 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.coul_total(h <> t, [], ys, qs, ke, c2) == 0.0 : F32}Coulomb with no charges answers zero, however many atoms remain.
law sd_trunc_forces provedin PROOF.bendsource · line 275 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.sd_sweep(h <> t, [], dt) == h <> t : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>}A sweep with no forces leaves the atoms in place.
law contacts_nil_right provedin PROOF.bendsource · line 284 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/topology.contacts_between(xs, empty_atoms, c2) == 0n : Nat}Nothing links to anything, however many heads are peeled.
law min_link2_nil_right provedin PROOF.bendsource · line 290 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/topology.min_link2(xs, empty_atoms) == None{} : Maybe<&2, F32>}No closest approach exists from any set held against nothing.
law rmsd_checked_some provedin PROOF.bendsource · line 297 · raw
@x:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @y:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> {0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd_checked([x], [y]) == Some{0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd([x], [y])} : Maybe<&2, F32>}Equal-length singletons check cleanly.
law rmsd_checked_none provedin PROOF.bendsource · line 303 · raw
@x:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> {0xdf198d67659100c90a58ecd6b01d034d/rmsd.rmsd_checked([x], empty_atoms) == None{} : Maybe<&2, F32>}Unequal lengths answer None{} instead of a silent zero.
law append_atoms_assoc provedin PROOF.bendsource · line 310 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @zs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/protein.append_atoms(0xdf198d67659100c90a58ecd6b01d034d/protein.append_atoms(xs, ys), zs) == 0xdf198d67659100c90a58ecd6b01d034d/protein.append_atoms(xs, 0xdf198d67659100c90a58ecd6b01d034d/protein.append_atoms(ys, zs)) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>}Appending atom lists associates.
law flatten_residues_append provedin PROOF.bendsource · line 317 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Residue> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Residue> -> {0xdf198d67659100c90a58ecd6b01d034d/protein.flatten_residues(0xdf198d67659100c90a58ecd6b01d034d/protein.append_residues(xs, ys)) == 0xdf198d67659100c90a58ecd6b01d034d/protein.append_atoms(0xdf198d67659100c90a58ecd6b01d034d/protein.flatten_residues(xs), 0xdf198d67659100c90a58ecd6b01d034d/protein.flatten_residues(ys)) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>}Flattening distributes over appending residue lists.
law add_zero_right provedin PROOF.bend
Also proved in bend-mathlib as nat.add_zero: import bend-mathlib@0.7.2.0/nat.bend as MNat, then MNat.add_zero.
@b:Nat -> {Nat.add(b, 0n) == b : Nat}Adding zero on the right changes nothing (induction seed for comm).
law add_succ_right provedin PROOF.bend
Also proved in bend-mathlib as nat.add_succ: import bend-mathlib@0.7.2.0/nat.bend as MNat, then MNat.add_succ.
@b:Nat -> @a:Nat -> {Nat.add(b, 1n+a) == 1n+Nat.add(b, a) : Nat}Adding a successor on the right pulls out front.
law add_comm provedin PROOF.bend
Also proved in bend-mathlib as nat.add_comm: import bend-mathlib@0.7.2.0/nat.bend as MNat, then MNat.add_comm.
@a:Nat -> @b:Nat -> {Nat.add(a, b) == Nat.add(b, a) : Nat}Nat addition commutes.
law count_atoms_append provedin PROOF.bendsource · line 340 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/protein.count_atoms(0xdf198d67659100c90a58ecd6b01d034d/protein.append_atoms(xs, ys)) == Nat.add(0xdf198d67659100c90a58ecd6b01d034d/protein.count_atoms(xs), 0xdf198d67659100c90a58ecd6b01d034d/protein.count_atoms(ys)) : Nat}Counting an append splits into the counts.
law count_flatten_eq provedin PROOF.bendsource · line 346 · raw
@rs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Residue> -> {0xdf198d67659100c90a58ecd6b01d034d/protein.count_atoms(0xdf198d67659100c90a58ecd6b01d034d/protein.flatten_residues(rs)) == 0xdf198d67659100c90a58ecd6b01d034d/protein.count_atoms_in(rs) : Nat}Counting a flattening agrees with counting residues in place.
law complex_flatten_eq provedin PROOF.bendsource · line 351 · raw
@chains:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Chain> -> {0xdf198d67659100c90a58ecd6b01d034d/protein.Complex.num_atoms(0xdf198d67659100c90a58ecd6b01d034d/protein.Complex{chains}) == 0xdf198d67659100c90a58ecd6b01d034d/protein.count_atoms(0xdf198d67659100c90a58ecd6b01d034d/protein.Complex.flatten(0xdf198d67659100c90a58ecd6b01d034d/protein.Complex{chains})) : Nat}A complex holds as many atoms as its flattening lists.
law pow10_3 provedin PROOF.bendsource · line 358 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.pow10(3n) == 1000 : U32}10^3 is 1000.
law elem_iron provedin PROOF.bendsource · line 362 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.elem_no("FE") == 26 : U32}Iron reads as 26.
law elem_carbon provedin PROOF.bendsource · line 366 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.elem_1('C') == 6 : U32}Carbon reads as 6.
law atom_line_yes provedin PROOF.bendsource · line 370 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.is_atom_line("ATOM 1 N ALA A 1") == True{} : Bool}ATOM records (6-column tag) pass the filter.
law atom_line_no provedin PROOF.bendsource · line 374 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.is_atom_line("HETATM 9999 O HOH A 101") == False{} : Bool}Anything else does not.
law atom_lines_nil provedin PROOF.bendsource · line 378 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.atom_lines([]) == [] : List<&2, String>}No lines in, no lines out.
law atom_lines_keep provedin PROOF.bendsource · line 382 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.atom_lines(["ATOM 1 N", "TER", "ENDMDL", "ATOM 2 CA"]) == ["ATOM 1 N"] : List<&2, String>}Non-ATOM lines drop, ENDMDL stops the file, the tail never parses.
law parse_f32_one provedin PROOF.bendsource · line 386 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_f32("12.5") == Some{F32.add(U32.to_f32(12), F32.div(U32.to_f32(5), U32.to_f32(10)))} : Maybe<&2, F32>}12.5 parses to 12 + 5/10 (stuck F32, identical both sides).
law parse_f32_neg provedin PROOF.bendsource · line 390 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_f32("-3.25") == Some{F32.sub(0.0, F32.add(U32.to_f32(3), F32.div(U32.to_f32(25), U32.to_f32(100))))} : Maybe<&2, F32>}Signs apply outside the magnitude.
law parse_f32_bad provedin PROOF.bendsource · line 394 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_f32("abc") == None{} : Maybe<&2, F32>}Non-numeric fields fail instead of answering zero.
law pdb_num_atoms provedin PROOF.bendsource · line 398 · raw
{0xdf198d67659100c90a58ecd6b01d034d/protein.Complex.num_atoms(0xdf198d67659100c90a58ecd6b01d034d/pdb.complex_of(0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_pdb(0xdf198d67659100c90a58ecd6b01d034d/pdb.demo_text))) == 2n : Nat}The two-line ALA snippet parses to two atoms ...
law pdb_num_residues provedin PROOF.bendsource · line 402 · raw
{0xdf198d67659100c90a58ecd6b01d034d/protein.Complex.num_residues(0xdf198d67659100c90a58ecd6b01d034d/pdb.complex_of(0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_pdb(0xdf198d67659100c90a58ecd6b01d034d/pdb.demo_text))) == 1n : Nat}... in one residue ...
law pdb_num_chains provedin PROOF.bendsource · line 406 · raw
{0xdf198d67659100c90a58ecd6b01d034d/protein.Complex.num_chains(0xdf198d67659100c90a58ecd6b01d034d/pdb.complex_of(0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_pdb(0xdf198d67659100c90a58ecd6b01d034d/pdb.demo_text))) == 1n : Nat}... in one chain ...
law pdb_skipped_0 provedin PROOF.bendsource · line 410 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.skipped_of(0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_pdb(0xdf198d67659100c90a58ecd6b01d034d/pdb.demo_text)) == 0n : Nat}... with nothing skipped ...
law pdb_skipped_1 provedin PROOF.bendsource · line 414 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.skipped_of(0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_pdb(0xdf198d67659100c90a58ecd6b01d034d/pdb.demo_bad_text)) == 1n : Nat}... while a bad serial skips exactly its line.
law pdb_bad_atoms provedin PROOF.bendsource · line 417 · raw
{0xdf198d67659100c90a58ecd6b01d034d/protein.Complex.num_atoms(0xdf198d67659100c90a58ecd6b01d034d/pdb.complex_of(0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_pdb(0xdf198d67659100c90a58ecd6b01d034d/pdb.demo_bad_text))) == 1n : Nat}
law pdb_first_elem provedin PROOF.bendsource · line 421 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.first_elem(0xdf198d67659100c90a58ecd6b01d034d/pdb.complex_of(0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_pdb(0xdf198d67659100c90a58ecd6b01d034d/pdb.demo_text))) == Some{7} : Maybe<&2, U32>}... and the first atom is nitrogen.
law sasa_total_cons provedin PROOF.bendsource · line 425 · raw
@h:F32 -> @t:List<&2, F32> -> {0xdf198d67659100c90a58ecd6b01d034d/sasa.sasa_total(h <> t) == F32.add(h, 0xdf198d67659100c90a58ecd6b01d034d/sasa.sasa_total(t)) : F32}Total area splits head from tail.
law count_par4_nil provedin PROOF.bendsource · line 433 · raw
@qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/par.count_par4(empty_atoms, qp, c2) == 0n : Nat}Empty input counts nothing, through the fallback arm.
law count_par4_step provedin PROOF.bendsource · line 439 · raw
@h1:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @h2:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @h3:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @h4:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/par.count_par4(h1 <> h2 <> h3 <> h4 <> t, qp, c2) == Nat.add(Nat.add(0xdf198d67659100c90a58ecd6b01d034d/topology.head_hit_nat(h1, qp, c2), 0xdf198d67659100c90a58ecd6b01d034d/topology.head_hit_nat(h2, qp, c2)), Nat.add(0xdf198d67659100c90a58ecd6b01d034d/topology.head_hit_nat(h3, qp, c2), Nat.add(0xdf198d67659100c90a58ecd6b01d034d/topology.head_hit_nat(h4, qp, c2), 0xdf198d67659100c90a58ecd6b01d034d/par.count_par4(t, qp, c2)))) : Nat}A full unrolled step splits four parallel hits plus the tail.
law count_par4_small provedin PROOF.bendsource · line 450 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @qp:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/par.count_par4([h], qp, c2) == 0xdf198d67659100c90a58ecd6b01d034d/topology.count_below([h], qp, c2) : Nat}Short inputs take the sequential fallback exactly.
law lj_row_par4_nil provedin PROOF.bendsource · line 457 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/par.lj_row_par4(pi, eps, sig2, c2, empty_atoms) == 0.0 : F32}Empty rows sum nothing, through the fallback arm.
law lj_row_par4_step provedin PROOF.bendsource · line 465 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @h1:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @h2:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @h3:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @h4:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/par.lj_row_par4(pi, eps, sig2, c2, h1 <> h2 <> h3 <> h4 <> t) == F32.add(F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.lj_head(pi, eps, sig2, c2, h1), 0xdf198d67659100c90a58ecd6b01d034d/force.lj_head(pi, eps, sig2, c2, h2)), F32.add(F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.lj_head(pi, eps, sig2, c2, h3), 0xdf198d67659100c90a58ecd6b01d034d/force.lj_head(pi, eps, sig2, c2, h4)), 0xdf198d67659100c90a58ecd6b01d034d/par.lj_row_par4(pi, eps, sig2, c2, t))) : F32}A full unrolled row splits four parallel heads plus the tail.
law lj_row_par4_small provedin PROOF.bendsource · line 478 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> {0xdf198d67659100c90a58ecd6b01d034d/par.lj_row_par4(pi, eps, sig2, c2, [h]) == 0xdf198d67659100c90a58ecd6b01d034d/force.lj_row(pi, eps, sig2, c2, [h]) : F32}Short rows take the sequential fallback exactly.
law lj_eps_c provedin PROOF.bendsource · line 489 · raw
{0xdf198d67659100c90a58ecd6b01d034d/force.lj_eps(6) == 0.066 : F32}Carbon takes illustrative OPLS-style parameters.
law lj_eps_h provedin PROOF.bendsource · line 492 · raw
{0xdf198d67659100c90a58ecd6b01d034d/force.lj_eps(1) == 0.03 : F32}
law lj_sig_o provedin PROOF.bendsource · line 495 · raw
{0xdf198d67659100c90a58ecd6b01d034d/force.lj_sig(8) == 2.96 : F32}
law lj_sig_default provedin PROOF.bendsource · line 499 · raw
{0xdf198d67659100c90a58ecd6b01d034d/force.lj_sig(99) == 3.0 : F32}Unknown elements take the generic pair.
law lj_row_elem_cons provedin PROOF.bendsource · line 503 · raw
@si:U32 -> @pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/force.lj_row_elem(si, pi, h <> t, c2) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.lj_row_elem(si, pi, t, c2), 0xdf198d67659100c90a58ecd6b01d034d/force.lj_head_elem(si, pi, c2, h)) : F32}An element row over a cons cell splits head from tail.
law lj_total_elem_cons provedin PROOF.bendsource · line 512 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.lj_total_elem(h <> t, ys, c2) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/force.lj_total_elem(t, ys, c2), 0xdf198d67659100c90a58ecd6b01d034d/force.lj_row_elem(0xdf198d67659100c90a58ecd6b01d034d/protein.Atom.elem(h), 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom.pos(h), ys, c2)) : F32}An element total over a cons cell splits head from tail.
law bond_total_nil provedin PROOF.bendsource · line 522 · raw
@k:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_total(empty_atoms, [], k) == 0.0 : F32}No bonds bind nothing.
law bond_total_cons provedin PROOF.bendsource · line 527 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @s1:U32 -> @s2:U32 -> @t:List<&1, Pair(U32, U32)> -> @k:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_total(xs, (s1, s2) <> t, k) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_cov_pair(xs, s1, s2, k), 0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_total(xs, t, k)) : F32}A bond total splits head bond from tail bonds.
law angle_total_nil provedin PROOF.bendsource · line 536 · raw
@k:F32 -> @eq:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.angle_total(empty_atoms, [], k, eq) == 0.0 : F32}No angles bend nothing.
law angle_total_cons provedin PROOF.bendsource · line 542 · raw
@xs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @sa:U32 -> @sb:U32 -> @sc:U32 -> @t:List<&1, Pair(U32, Pair(U32, U32))> -> @k:F32 -> @eq:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.angle_total(xs, (sa, sb, sc) <> t, k, eq) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/bonded.angle_triple(xs, sa, sb, sc, k, eq), 0xdf198d67659100c90a58ecd6b01d034d/bonded.angle_total(xs, t, k, eq)) : F32}An angle total splits head triple from tail triples.
law pos_of_serial_none provedin PROOF.bendsource · line 553 · raw
@s:U32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.pos_of_serial(empty_atoms, s) == None{} : Maybe<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}Nobody is found in nothing.
law pos_of_serial_some provedin PROOF.bendsource · line 558 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.pos_of_serial([0xdf198d67659100c90a58ecd6b01d034d/protein.Atom{1, 6, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{1.0, 2.0, 3.0}}], 1) == Some{0xdf198d67659100c90a58ecd6b01d034d/geom.V3{1.0, 2.0, 3.0}} : Maybe<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}A singleton finds its atom's position.
law bonded12_nil provedin PROOF.bendsource · line 562 · raw
@a:U32 -> @b:U32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.bonded12_flat([], a, b) == False{} : Bool}No bonds exclude nothing.
law bonded12_hit provedin PROOF.bendsource · line 568 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.bonded12_flat([1, 2], 1, 2) == True{} : Bool}A listed pair (either order) is 1-2 excluded.
law bonded12_miss provedin PROOF.bendsource · line 572 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.bonded12_flat([1, 2], 1, 3) == False{} : Bool}An unlisted pair is not.
law neighbors_one provedin PROOF.bendsource · line 576 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_neighbors(1, [1, 2, 2, 3]) == [2] : List<&2, U32>}Neighbors of 1 in [(1,2),(2,3)] are just [2].
law excluded13_one provedin PROOF.bendsource · line 580 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.excluded13(1, 3, [1, 2, 2, 3]) == True{} : Bool}1 and 3 share neighbor 2.
law excluded_both provedin PROOF.bendsource · line 584 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.excluded(2, 3, [1, 2, 2, 3]) == True{} : Bool}2 and 3 are directly bonded (1-2 wins over 1-3 either way).
law flatten_bonds_one provedin PROOF.bendsource · line 588 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.flatten_bonds([(1, 2)]) == [1, 2] : List<&2, U32>}Pair bonds flatten in order.
law lj_row_excl_nil provedin PROOF.bendsource · line 592 · raw
@si:U32 -> @pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @bonds:List<&2, U32> -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.lj_row_excl(si, pi, eps, sig2, c2, empty_atoms, bonds) == 0.0 : F32}Excluded rows sum nothing over nothing.
law lj_total_excl_nil provedin PROOF.bendsource · line 601 · raw
@ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @bonds:List<&2, U32> -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.lj_total_excl(empty_atoms, ys, eps, sig2, c2, bonds) == 0.0 : F32}
law coul_row_excl_nil provedin PROOF.bendsource · line 609 · raw
@si:U32 -> @pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @qi:F32 -> @ke:F32 -> @c2:F32 -> @bonds:List<&2, U32> -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.coul_row_excl(si, pi, qi, ke, c2, empty_atoms, [], bonds) == 0.0 : F32}
law coul_total_excl_nil provedin PROOF.bendsource · line 618 · raw
@ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qs_e:List<&2, F32> -> @ke:F32 -> @c2:F32 -> @bonds:List<&2, U32> -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.coul_total_excl(empty_atoms, [], ys, qs_e, ke, c2, bonds) == 0.0 : F32}
law lj_row_elem_excl_nil provedin PROOF.bendsource · line 627 · raw
@si:U32 -> @se:U32 -> @pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @c2:F32 -> @bonds:List<&2, U32> -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.lj_row_elem_excl(si, se, pi, empty_atoms, c2, bonds) == 0.0 : F32}Element-excluded rows/totals sum nothing over nothing.
law lj_total_elem_excl_nil provedin PROOF.bendsource · line 635 · raw
@ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @c2:F32 -> @bonds:List<&2, U32> -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.lj_total_elem_excl(empty_atoms, ys, c2, bonds) == 0.0 : F32}
law lj_row_elem_excl_hit provedin PROOF.bendsource · line 643 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.lj_row_elem_excl(1, 7, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{0.0, 0.0, 0.0}, [0xdf198d67659100c90a58ecd6b01d034d/protein.Atom{2, 6, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{1.0, 0.0, 0.0}}], 144.0, [1, 2]) == F32.add(0.0, 0.0) : F32}A directly bonded pair contributes exactly 0.0 (wiring pin: the row must test serials, not elements; the sum is (0.0 + 0.0) since F32.add is stuck).
law lj_row_elem_excl_link provedin PROOF.bendsource · line 647 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.lj_row_elem_excl(1, 7, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{0.0, 0.0, 0.0}, [0xdf198d67659100c90a58ecd6b01d034d/protein.Atom{3, 6, 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{2.0, 0.0, 0.0}}], 144.0, [1, 2, 2, 3]) == F32.add(0.0, 0.0) : F32}Same through a 1-3 link.
law conect_lines_nil provedin PROOF.bendsource · line 653 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.conect_lines([]) == [] : List<&2, String>}No lines in, no bonds out.
law conect_keep provedin PROOF.bendsource · line 657 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.conect_lines(["ATOM 1 N", "CONECT 20 282"]) == ["CONECT 20 282"] : List<&2, String>}CONECT lines survive, everything else drops.
law parse_conect_one provedin PROOF.bendsource · line 661 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_conect_line("CONECT 20 282") == [(20, 282)] : List<&1, Pair(U32, U32)>}One record with one partner is one bond.
law parse_conect_none provedin PROOF.bendsource · line 665 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.parse_conect_line("CONECT") == [] : List<&1, Pair(U32, U32)>}A partnerless record binds nothing.
law mass_c provedin PROOF.bendsource · line 671 · raw
{0xdf198d67659100c90a58ecd6b01d034d/force.mass(6) == 12.011 : F32}Carbon weighs 12.011 amu.
law mass_h provedin PROOF.bendsource · line 674 · raw
{0xdf198d67659100c90a58ecd6b01d034d/force.mass(1) == 1.008 : F32}
law coul_frow_cons provedin PROOF.bendsource · line 678 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @qi:F32 -> @ke:F32 -> @c2:F32 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qh:F32 -> @qt:List<&2, F32> -> {0xdf198d67659100c90a58ecd6b01d034d/force.coul_frow(pi, qi, ke, c2, h <> t, qh <> qt) == 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3.add(0xdf198d67659100c90a58ecd6b01d034d/force.coul_frow(pi, qi, ke, c2, t, qt), 0xdf198d67659100c90a58ecd6b01d034d/force.coul_fhead(pi, qi, ke, c2, h, qh)) : 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3}A Coulomb row over a cons cell splits head from tail.
law coul_forces_cons provedin PROOF.bendsource · line 690 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qh:F32 -> @qt:List<&2, F32> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @qs_e:List<&2, F32> -> @ke:F32 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.coul_forces(h <> t, qh <> qt, ys, qs_e, ke, c2) == 0xdf198d67659100c90a58ecd6b01d034d/force.coul_fself_atom(h, qh, ys, qs_e, ke, c2) <> 0xdf198d67659100c90a58ecd6b01d034d/force.coul_forces(t, qt, ys, qs_e, ke, c2) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}Coulomb forces over cons cells split head from tail.
law coul_frow_nil provedin PROOF.bendsource · line 702 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @qi:F32 -> @ke:F32 -> @c2:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/force.coul_frow(pi, qi, ke, c2, empty_atoms, []) == 0xdf198d67659100c90a58ecd6b01d034d/geom.V3{0.0, 0.0, 0.0} : 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3}No charges feel nothing.
law lj_row_pbc_cons provedin PROOF.bendsource · line 711 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @box:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_row_pbc(pi, eps, sig2, c2, box, h <> t) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_row_pbc(pi, eps, sig2, c2, box, t), 0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_head_pbc(pi, eps, sig2, c2, box, h)) : F32}
law lj_total_pbc_cons provedin PROOF.bendsource · line 721 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @box:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_total_pbc(h <> t, ys, eps, sig2, c2, box) == F32.add(0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_total_pbc(t, ys, eps, sig2, c2, box), 0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_self_atom_pbc(h, ys, eps, sig2, c2, box)) : F32}
law lj_row_pbc_nil provedin PROOF.bendsource · line 731 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @box:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_row_pbc(pi, eps, sig2, c2, box, empty_atoms) == 0.0 : F32}
law lj_frow_pbc_cons provedin PROOF.bendsource · line 739 · raw
@pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @box:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_frow_pbc(pi, eps, sig2, c2, box, h <> t) == 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3.add(0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_frow_pbc(pi, eps, sig2, c2, box, t), 0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_fhead_pbc(pi, eps, sig2, c2, box, h)) : 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3}
law lj_forces_pbc_cons provedin PROOF.bendsource · line 749 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @box:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_forces_pbc(h <> t, ys, eps, sig2, c2, box) == 0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_fself_atom_pbc(h, ys, eps, sig2, c2, box) <> 0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_forces_pbc(t, ys, eps, sig2, c2, box) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}
law lj_forces_pbc_nil provedin PROOF.bendsource · line 759 · raw
@ys:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @eps:F32 -> @sig2:F32 -> @c2:F32 -> @box:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> {0xdf198d67659100c90a58ecd6b01d034d/pbc.lj_forces_pbc(empty_atoms, ys, eps, sig2, c2, box) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}
law cov_rad_c provedin PROOF.bendsource · line 770 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.cov_rad(6) == 0.76 : F32}Carbon's covalent radius is 0.76 A.
law infer_row_nil provedin PROOF.bendsource · line 774 · raw
@si:U32 -> @pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @ei:U32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.infer_row(si, pi, ei, empty_atoms) == [] : List<&1, Pair(U32, U32)>}An inference row over nothing finds nothing.
law infer_row_cons provedin PROOF.bendsource · line 781 · raw
@si:U32 -> @pi:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @ei:U32 -> @h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.infer_row(si, pi, ei, h <> t) == 0xdf198d67659100c90a58ecd6b01d034d/bonded.append_infer(0xdf198d67659100c90a58ecd6b01d034d/bonded.infer_one(si, pi, ei, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom.serial(h), 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom.elem(h), 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom.pos(h)), 0xdf198d67659100c90a58ecd6b01d034d/bonded.infer_row(si, pi, ei, t)) : List<&1, Pair(U32, U32)>}An inference row splits head from tail.
law infer_total_nil provedin PROOF.bendsource · line 790 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.infer_total(empty_atoms) == [] : List<&1, Pair(U32, U32)>}Nothing infers from nothing.
law bond_forces_nil provedin PROOF.bendsource · line 794 · raw
@bonds:List<&2, U32> -> @k:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_forces(empty_atoms, bonds, k) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}Bond forces sum nothing over nothing.
law bond_forces_cons provedin PROOF.bendsource · line 800 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> @bonds:List<&2, U32> -> @k:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_forces(h <> t, bonds, k) == 0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_force_list(0xdf198d67659100c90a58ecd6b01d034d/protein.Atom.serial(h), bonds, h <> t, k) <> 0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_forces(t, bonds, k) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}Bond forces split head atom from tail atoms.
law dyn_of_atoms_nil provedin PROOF.bendsource · line 809 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sim.dyn_of_atoms(empty_atoms) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law dyn_of_atoms_cons provedin PROOF.bendsource · line 812 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/sim.dyn_of_atoms(h <> t) == 0xdf198d67659100c90a58ecd6b01d034d/sim.dyn_of_atom(h) <> 0xdf198d67659100c90a58ecd6b01d034d/sim.dyn_of_atoms(t) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law dyn_atoms_nil provedin PROOF.bendsource · line 817 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sim.dyn_atoms([]) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>}
law vv_scale_nil provedin PROOF.bendsource · line 820 · raw
@lam:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.vv_scale([], lam) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law vv_scale_cons provedin PROOF.bendsource · line 824 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom> -> @lam:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.vv_scale(h <> t, lam) == 0xdf198d67659100c90a58ecd6b01d034d/sim.vv_scale_head(h, lam) <> 0xdf198d67659100c90a58ecd6b01d034d/sim.vv_scale(t, lam) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law vv_half_nil provedin PROOF.bendsource · line 830 · raw
@dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.vv_half([], dt) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law vv_half_cons provedin PROOF.bendsource · line 834 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom> -> @dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.vv_half(h <> t, dt) == 0xdf198d67659100c90a58ecd6b01d034d/sim.vv_half_head(h, dt) <> 0xdf198d67659100c90a58ecd6b01d034d/sim.vv_half(t, dt) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law vv_full_nil provedin PROOF.bendsource · line 840 · raw
@dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.vv_full([], dt) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law vv_full_cons provedin PROOF.bendsource · line 844 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom> -> @dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.vv_full(h <> t, dt) == 0xdf198d67659100c90a58ecd6b01d034d/sim.vv_full_head(h, dt) <> 0xdf198d67659100c90a58ecd6b01d034d/sim.vv_full(t, dt) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law ke_sim_nil provedin PROOF.bendsource · line 850 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sim.ke_sim_of([]) == 0.0 : F32}
law md_run_zero provedin PROOF.bendsource · line 853 · raw
@ds:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom> -> @qs:List<&2, F32> -> @bonds:List<&2, U32> -> @p:0xdf198d67659100c90a58ecd6b01d034d/sim.SimParams -> @dt:F32 -> @tau:F32 -> @temp0:F32 -> @n:Nat -> {0xdf198d67659100c90a58ecd6b01d034d/sim.md_run(0n, ds, qs, bonds, p, dt, tau, temp0, n) == ds : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law min_run_zero provedin PROOF.bendsource · line 864 · raw
@ds:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom> -> @qs:List<&2, F32> -> @bonds:List<&2, U32> -> @p:0xdf198d67659100c90a58ecd6b01d034d/sim.SimParams -> @dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.min_run(0n, ds, qs, bonds, p, dt) == ds : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}
law zero_charges_nil provedin PROOF.bendsource · line 873 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sim.zero_charges(empty_atoms) == [] : List<&2, F32>}Zero charges over nothing is nothing.
law zero_charges_cons provedin PROOF.bendsource · line 877 · raw
@h:0xdf198d67659100c90a58ecd6b01d034d/protein.Atom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom> -> {0xdf198d67659100c90a58ecd6b01d034d/sim.zero_charges(h <> t) == 0.0 <> 0xdf198d67659100c90a58ecd6b01d034d/sim.zero_charges(t) : List<&2, F32>}Zero charges split head from tail.
law sd_norm_sweep_nil provedin PROOF.bendsource · line 883 · raw
@dt:F32 -> {0xdf198d67659100c90a58ecd6b01d034d/sim.sd_norm_sweep([], dt) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}Normalized sweeps move nothing over nothing.
law maxforce2_nil provedin PROOF.bendsource · line 888 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sim.maxforce2_of([]) == 0.0 : F32}No atoms carry no max force.
law dyn_set_force_nil provedin PROOF.bendsource · line 892 · raw
@fs:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3> -> {0xdf198d67659100c90a58ecd6b01d034d/sim.dyn_set_force([], fs) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/sim.DynAtom>}Setting forces over nothing is nothing.
law add_forces_nil provedin PROOF.bendsource · line 897 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sim.add_forces([], []) == [] : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}Adding empties is empty.
law add_forces_cons provedin PROOF.bendsource · line 901 · raw
@x:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @xt:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3> -> @y:0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3 -> @yt:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3> -> {0xdf198d67659100c90a58ecd6b01d034d/sim.add_forces(x <> xt, y <> yt) == 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3.add(x, y) <> 0xdf198d67659100c90a58ecd6b01d034d/sim.add_forces(xt, yt) : List<&2, 0xdf198d67659100c90a58ecd6b01d034d/geom.Vec3>}Force addition splits head pair from tail pairs.
law pairs_of_flat_nil provedin PROOF.bendsource · line 909 · raw
{0xdf198d67659100c90a58ecd6b01d034d/sim.pairs_of_flat([]) == [] : List<&1, Pair(U32, U32)>}No flats pair to nothing.
law pairs_of_flat_cons provedin PROOF.bendsource · line 913 · raw
@x:U32 -> @y:U32 -> @t:List<&2, U32> -> {0xdf198d67659100c90a58ecd6b01d034d/sim.pairs_of_flat(x <> y <> t) == (x, y) <> 0xdf198d67659100c90a58ecd6b01d034d/sim.pairs_of_flat(t) : List<&1, Pair(U32, U32)>}Flat pairs split head pair from tail pairs.
law pad_left_golden provedin PROOF.bendsource · line 920 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.pad_left("AB", 5n) == " AB" : String}Padding and symbols print as written.
law pad_right_golden provedin PROOF.bendsource · line 923 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.pad_right("AB", 5n) == "AB " : String}
law fmt_u32_golden provedin PROOF.bendsource · line 926 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.fmt_u32(5n, 42) == " 42" : String}
law elem_sym_golden provedin PROOF.bendsource · line 929 · raw
{0xdf198d67659100c90a58ecd6b01d034d/pdb.elem_sym(26) == "FE" : String}
law tpl_has_bond_ala provedin PROOF.bendsource · line 935 · raw
{0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_has_bond("ALA", "N", "CA") == True{} : Bool}ALA links N-CA in the template.
law tpl_has_bond_miss provedin PROOF.bendsource · line 939 · raw
{0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_has_bond("ALA", "N", "O") == False{} : Bool}... but not N-O.
law tpl_has_bond_unknown provedin PROOF.bendsource · line 943 · raw
{0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_has_bond("ZZZ", "N", "CA") == False{} : Bool}Unknown residues link nothing.
law tpl_has_bond_his provedin PROOF.bendsource · line 947 · raw
{0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_has_bond("HID", "N", "CA") == True{} : Bool}HIS variants share heavy topology.
law tpl_row_nil provedin PROOF.bendsource · line 951 · raw
@a:0xdf198d67659100c90a58ecd6b01d034d/tpl.TplAtom -> {0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_row(a, []) == [] : List<&1, Pair(U32, U32)>}Template rows split head from tail.
law tpl_row_cons provedin PROOF.bendsource · line 955 · raw
@a:0xdf198d67659100c90a58ecd6b01d034d/tpl.TplAtom -> @h:0xdf198d67659100c90a58ecd6b01d034d/tpl.TplAtom -> @t:List<&2, 0xdf198d67659100c90a58ecd6b01d034d/tpl.TplAtom> -> {0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_row(a, h <> t) == 0xdf198d67659100c90a58ecd6b01d034d/tpl.append_tpl(0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_one(a, h), 0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_row(a, t)) : List<&1, Pair(U32, U32)>}
law tpl_total_nil provedin PROOF.bendsource · line 961 · raw
{0xdf198d67659100c90a58ecd6b01d034d/tpl.tpl_total([]) == [] : List<&1, Pair(U32, U32)>}
law parse_tpl_golden provedin PROOF.bendsource · line 965 · raw
{0xdf198d67659100c90a58ecd6b01d034d/tpl.parse_tpl_line("ATOM 1 N ALA A 1 11.104 13.207 2.100 1.00 13.79 N ") == Some{0xdf198d67659100c90a58ecd6b01d034d/tpl.TA{1, 65, 1n, "ALA", "N"}} : Maybe<&2, 0xdf198d67659100c90a58ecd6b01d034d/tpl.TplAtom>}The snippet's first atom parses with identity intact.
law neighbors_except_golden provedin PROOF.bendsource · line 971 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.bond_neighbors_except(2, 1, [1, 2, 2, 3]) == [3] : List<&2, U32>}Neighbors of 2 excluding 1 in [(1,2),(2,3)] are just [3].
law fan_triples_golden provedin PROOF.bendsource · line 975 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.fan_triples(1, 2, [3, 4]) == [(1, 2, 3), (1, 2, 4)] : List<&1, Pair(U32, Pair(U32, U32))>}A fan over [3, 4] from (1, 2) lists both triples.
law angle_triples_auto_golden provedin PROOF.bendsource · line 979 · raw
{0xdf198d67659100c90a58ecd6b01d034d/bonded.angle_triples_auto([1, 2, 2, 3]) == [(1, 2, 3), (3, 2, 1)] : List<&1, Pair(U32, Pair(U32, U32))>}A two-bond chain auto-derives both directed angles.
Definitions
def empty_atoms source · line 19 · raw
List<&2, 0xdf198d67659100c90a58ecd6b01d034d/protein.Atom>
def empty_cx source · line 34 · raw
0xdf198d67659100c90a58ecd6b01d034d/protein.Complex