What TLA+ can and can't check

(buttondown.com)

93 points | by b-man 6 hours ago

8 comments

  • singron 2 hours ago
    I love this. This is great to read if you are trying to use TLA+ for something.

    In a different vein, another thing TLA+ isn't great at is modeling atomics and in particular weak-memory semantics or anything that's not sequentially consistent. If you translate your algorithm to pcal, it will run as if it was sequentially consistent. If you need to model non-sequential-consistency, then that needs to be spelled out with explicit logic to TLA+, which is probably too complicated and error-prone to do by hand. The C/C++/Rust memory models permit a lot of wacky stuff. I imagine you need to add read caches and writeback buffers for each variable with cache-flushing instructions at appropriate points, but maybe there is a more elegant way to do it.

    If you use rust, miri and loom both have analyzers that can check some non-sequentially-consistent behavior (and loom doesn't actually implement sequential-consistency at all).

    • kccqzy 57 minutes ago
      I think the style guides I’ve seen only permit acquire/release memory orders for locks, and relaxed for simple counters. Anything more complicated including lockless hashtables or RCU, using seq_cst is required by the style guide.

      The restriction is a good thing because there are very few humans who can reason about acquire/release semantics in situations other than locks.

      • senderista 1 minute ago
        Which style guides? That makes no sense to me because 1) if you're writing a lock-free algorithm/data structure you presumably both know what you're doing and care a lot about performance, 2) many lock-free algorithms don't even require any seq_cst operations (or equivalent fences), and 3) weak memory orderings can be essential to getting acceptable performance in critical paths.

        I would also note that aside from formal methods, LLMs are absolutely not trustworthy but the top frontier models can reason to some degree about weak memory orderings, and can at least find concurrency bugs which can be later confirmed by human expert review (preferably after eliminating false positives via adversarial LLM review of the findings).

    • ahelwer 1 hour ago
      This is true, and it falls into the "possible but not ergonomic" category for modeling systems like this in TLA+. Concurrent programs reading & writing to shared variables can be reordered at two levels: the compiler, and then the CPU. Specifying this in TLA+ is possible but difficult, and your conventional TLA+ specification will assume things happen in a linear order within each thread, and are interleaved arbitrarily between threads. In other words by default PlusCal works like there is both a barrier and memory fence between each action. Even with strong memory semantics like x86-TSO, specifying something like the action of the store buffer (where a core writes a value and can read the updated value but its write is not yet visible to other cores) requires actually writing your own tiny implementation of x86-TSO; there isn't one already defined as a library you can easily use.

      I've been thinking lately about how to make this more ergonomic, as I've been getting into lock-free algorithms and would like to be able to specify them nicely in TLA+.

  • sourdecor 3 hours ago
    I discovered Quint[0] due to this comment[1] on HN. Quint is "an executable specification language [which works in JavaScript] with delightful tooling based on the temporal logic of actions (TLA)". I think it is awesome and anybody interested in TLA+ should check it out.

    [0]: https://github.com/quint-co/quint

    [1]: https://news.ycombinator.com/item?id=49865720

  • adamddev1 3 hours ago
    Great write-up. People keep saying "we can just write tests" or more recently "we can use formal verification," thinking these are sufficient safeguards we can use and then relegate all the implementation to LLMs. But the fact is that probabilistic guessing machines can't save them. People can't escape the need to actually understand the things they are building.
    • _flux 1 hour ago
      These probabilistic guessing machines are pretty great for creating these formal models, e.g. TLA+, and then guessing if the implementation aligns with the spec.. In fact, it's my go-to tool for constructing soft guardrails for the model, so the design it's going to implement is logically sound. Same as for people: it's easier to make something working when you have a spec that is working.

      Of course, it still allows the risk that you don't actually get to understand it.

    • nonethewiser 42 minutes ago
      I wonder if asking an LLM to model their implementation in TLA+ first would improve their implementations.
    • jldugger 1 hour ago
      > People can't escape the need to actually understand the things they are building.

      While on the one hand, you do need some kind of grounding in human specification for what to build and what good looks like, any particular defect humans can find should be findable via software.

  • rrook 3 hours ago
    i think part of this is a shortcoming of our programming languages. generally, languages allow for the expression of partial graphs, which makes the verification problem technically challenging. my take is that a language that only exposes closed-graph semantics could help bridge the gap between the model and the implementation, even if not absolute.
    • bunderbunder 2 hours ago
      What you say reminds me of the "Von Neumann Languages Lack Useful Mathematical Properties" section in John Backus's Turing award paper. One of his criticisms of what we would now call imperative languages is that they make it exceedingly difficult to formally prove facts about a program.

      https://dl.acm.org/doi/epdf/10.1145/359576.359579

  • westurner 2 hours ago
    From "How did software get so reliable without proof? (1996) [pdf]" (2024) https://news.ycombinator.com/item?id=42425617 :

    > From "The Future of TLA+ [pdf]" (2024) https://news.ycombinator.com/item?id=41385141 :

    >> Formal methods including TLA+ also can't/don't prevent or can only workaround side channels in hardware and firmware that is not verified. But that's a different layer.

    >> Things formal methods shouldn't be expected to find: Floating point arithmetic non-associativity, side-channels

  • ChrisArchitect 2 hours ago
    Related:

    The internet discovers TLA+. Now what?

    https://news.ycombinator.com/item?id=49863600

  • lou1306 34 minutes ago
    Uhm, I can see the desire to simplify, but the passage about "reachability" sounds odd.

    Sure, TLA+ lets you verify whether P is true in every state of every behavior by checking []P. But a _counterexample_ to that property, if it exist, is _some_ state in _some_ behaviour where P is false. Thus, if your model checker proves []P false, you have indirectly proven E<>!P (where the initial E means exactly "for some behaviour").

    Going back to the example, "proving that a game is winnable" should be achievable by model checking the invariant "the game is never winnable" and failing. Or am I missing something here?

    • ahelwer 28 minutes ago
      You are quite close! That does indeed encode a limited form of reachability property - that P is reachable from at least one start state. As the article mentioned, these kinds of reachability properties are now actually available for TLC to check without having to jump through the hoop of negating it first.

      A stronger type of reachability property is that a state is always reachable from every other state. This is useful in, for example, eventually-consistent systems where you want to know that your system always could converge to every replica having the same state, even though it never actually does converge unless all writes to the system stop. The article links to a post about how to specify & check those properties in TLA+ (it is possible!) but the way to do this is very much not ergonomic.

      Editing to add "there exists a behavior where P is true" is probably meant to mean P is an arbitrary temporal formula. So you are correct that with the limited reachability property you identified, you can express the formula "there exists a behavior satisfying <>S". However, you cannot express anything other than simple formulas like that, not general temporal formulas.

      • hwayne 21 minutes ago
        On top of what Andrew said, "failure as reachability" is a property of the implementing model checker, not the formalism itself! If you convert "we can win the game" to "it's not true that always we haven't won" and write that up as a TLA+ formula, you get `![](!won)". But that means "we win in every behavior", aka `<>won`!

        A really good paper on the difference between "possible" and "eventual" is '"Sometime" is sometimes "not never"': https://dl.acm.org/doi/10.1145/567446.567463

  • kylegalbraith 1 hour ago
    [dead]