Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add model for vstd Set and prove its axioms #1426

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

matthias-brun
Copy link
Collaborator

@matthias-brun matthias-brun commented Feb 1, 2025

This PR proves the set axioms and adds a fold function for finite sets (which is used to define cardinality) with associated lemmas.

The way things are bootstrapped is as follows:

  • Sets are defined as functions from key to boolean
  • A set is finite if there exists a surjective mapping into the natural numbers up to some upper bound
  • This allows us to define most set operations except for cardinality
  • We then define fold on finite sets by porting Isabelle/HOL's definitions and lemmas for it
    • Because of the inductive predicate-style encoding, we don't need a decreasing measure for induction proofs (We could use e.g. the finiteness upper bound but it's very annoying to do)
  • Finally, we define set cardinality as self.fold(|a, b: nat| b + 1, 0)

I'm not sure about where the fold module should go. The current place (inline in set.rs) probably isn't it. But it needs to be a submodule of set to see the bodies of closed functions and the non-public items. We could move set.rs to set/mod.rs and then have set/fold.rs, which wouldn't break any imports of vstd::set. But arguably set_lib.rs should then also live in the set directory, which would be a breaking change. How should I best handle this?

Some miscellaneous notes:

  • Isabelle uses a 3-clause BSD license, which is compatible with Verus' MIT license
  • Isabelle's fold lemmas only require the function to be commutative on the set to be folded. I decided to require fully commutative functions
    • Triggering is tricky enough with these higher-order predicates, adding another set into the mix that might be defined with a closure doesn't help.
  • There was an existing definition of fold for sets, which I replaced with the new one
    • It was based on the recursive encoding with self.choose() which makes reasoning about it very hard
    • That's presumably the reason why there weren't any associated lemmas for it
    • Maybe some of the admitted proofs in tokens.rs can now be proved (I didn't try)
    • I changed the argument order to the standard one. This is technically a breaking change but I suspect not many (any?) people have been using the current fold.
  • Aside: The obvious recursive fold (if s == set![] { z } else { f(s.choose(), fold(s.remove(s.choose())), f, z) }) is hard to reason about because the induction hypothesis is useless. The elements of s.remove(s.choose()) might be folded in a completely different order than those of s.

@tjhance I added you as a reviewer since tokens.rs seems to be the only current user of fold (within Verus/vstd)

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

@matthias-brun matthias-brun requested a review from tjhance February 3, 2025 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant