Skip to content

feat: Linear Temporal Logic#413

Open
mell-o-tron wants to merge 5 commits intoleanprover:mainfrom
mell-o-tron:main
Open

feat: Linear Temporal Logic#413
mell-o-tron wants to merge 5 commits intoleanprover:mainfrom
mell-o-tron:main

Conversation

@mell-o-tron
Copy link

Hi! Here is my first attempt at formalizing LTL, by providing a semantics on omega-sequences and a few simple rules. I think this could be quite easily adapted to obtain a semantics on paths of transition systems.

I hope you'll forgive my naive proof style, I'm fairly new to Lean, and I hope we can work on this together to make it up to standards :)


/-- Satisfaction relation for ω-sequences of atom valuations. -/
@[simp, scoped grind =]
def Satisfies (ls : ωSequence (Set T)) (φ : Proposition T) := match φ with
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def Satisfies (ls : ωSequence (Set T)) : Proposition T) := match φ with
def Satisfies (ls : ωSequence (Set T)) : Proposition TProp

| .or φ₁ φ₂ => Satisfies ls φ₁ ∨ Satisfies ls φ₂
| .atom (p) => p ∈ ls 0
| .not φ => ¬ (Satisfies ls φ)
| .next φ => Satisfies (ωSequence.drop 1 ls) φ
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
| .next φ => Satisfies (ωSequence.drop 1 ls) φ
| .next φ => Satisfies (ls.drop 1) φ

etc


/-- Equivalence of LTL propositions on ω-sequences. -/
@[simp, scoped grind =]
def Proposition.equiv (φ₁ : Proposition T) (φ₂ : Proposition T) :=
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def Proposition.equiv (φ₁ : Proposition T) (φ₂ : Proposition T) :=
def Proposition.equiv (φ₁ : Proposition T) (φ₂ : Proposition T) : Prop :=

Comment on lines +79 to +80
theorem next_self_dual {T} : ∀ (φ : Proposition T), φ.next.not ≈ φ.not.next :=
by simp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style should be

Suggested change
theorem next_self_dual {T} : ∀ (φ : Proposition T), φ.next.not ≈ φ.not.next :=
by simp
theorem next_self_dual {T} : ∀ (φ : Proposition T), φ.next.not ≈ φ.not.next := by
simp

(throughout)

Comment on lines +93 to +96
theorem expansion_until {T} : ∀ (φ : Proposition T) (ψ : Proposition T) ,
Proposition.until_op φ ψ ≈ Proposition.or ψ (Proposition.and φ ((Proposition.until_op φ ψ).next)) :=
by
intros
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
theorem expansion_until {T} : ∀ (φ : Proposition T) (ψ : Proposition T) ,
Proposition.until_op φ ψ ≈ Proposition.or ψ (Proposition.and φ ((Proposition.until_op φ ψ).next)) :=
by
intros
theorem expansion_until {T} (φ : Proposition T) (ψ : Proposition T) :
φ.until_op ψ ≈ ψ.or (φ.and ((φ.until_op ψ).next)) := by

namespace Cslib.Logic.LTL

/-- Propositions, where `T` is the type of atoms. -/
inductive Proposition (T : Type) : Type u where
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
inductive Proposition (T : Type) : Type u where
inductive Proposition (T : Type u) : Type u where

Copy link
Contributor

@ctchou ctchou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are my specific comments. I will give my general comments on Zulip:
#CSLib > LTL?

@@ -0,0 +1,167 @@
/-
Copyright (c) 2026 Fabrizio Montesi. All rights reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put your name here.

/-! # Linear Temporal Logic

Linear Temporal Logic (LTL) is a logic for reasoning about the validity of propositional atoms
in non-branching time.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non-branching -> linear.

namespace Cslib.Logic.LTL

/-- Propositions, where `T` is the type of atoms. -/
inductive Proposition (T : Type) : Type u where
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason implies and leads_to are not among the operators? Alternatively, can we take seriously the idea that (for example) always and eventuallycan be defined as derived operators and reduce this inductive definition to a minimal set of operators?

/-- Equivalence of LTL propositions on ω-sequences. -/
@[simp, scoped grind =]
def Proposition.equiv (φ₁ : Proposition T) (φ₂ : Proposition T) :=
∀ (ls : ωSequence (Set T)) , (ls ⊧ φ₁) ↔ ls ⊧ φ₂
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to give \models a higher precedence than \iff, so that we can get rid of the parentheses on the LHS of \iff?


/-- Equivalence of LTL propositions on ω-sequences. -/
@[simp, scoped grind =]
def Proposition.equiv (φ₁ : Proposition T) (φ₂ : Proposition T) :=
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of Proposition.equiv φ₁ φ₂, I think you should define Proposition.valid φ to mean that φ is true over all models ls. This is more general, because Proposition.equiv φ₁ φ₂ is simply Proposition.valid (φ₁.iff φ₂). (You didn't define Proposition.iff, but there is no reason why you shouldn't.). Also, Proposition.equiv φ₁ φ₂ biases you toward equational reasoning. But sometimes it is more natural to reason about implications.

Comment on lines +87 to +94
/-- The `eventually` operator distributes on disjunction. -/
@[scoped grind .]
theorem distrib_eventually_or {T} :
∀ (φ : Proposition T) (ψ : Proposition T) ,
Proposition.eventually (φ.or ψ) ≈ (Proposition.or (φ.eventually) (ψ.eventually))
:= by
simp
grind
Copy link
Collaborator

@eric-wieser eric-wieser Mar 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the indents here and throughout

Comment on lines +83 to +85
@[scoped grind .]
theorem next_self_dual {T} : ∀ (φ : Proposition T), φ.next.not ≈ φ.not.next := by
simp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@[scoped grind .]
theorem next_self_dual {T} : ∀ (φ : Proposition T), φ.next.not ≈ φ.not.next := by
simp
@[scoped grind .]
theorem next_self_dual {T} : ∀ (φ : Proposition T), φ.next.not ≈ φ.not.next := by
simp


/-- Validity of LTL propositions on ω-sequences. -/
@[simp, scoped grind =]
def Proposition.valid (φ₁ : Proposition T) : Prop :=
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def Proposition.valid (φ₁ : Proposition T) : Prop :=
def Proposition.Valid (φ₁ : Proposition T) : Prop :=

or perhaps

Suggested change
def Proposition.valid (φ₁ : Proposition T) : Prop :=
def Proposition.IsValid (φ₁ : Proposition T) : Prop :=

Comment on lines +39 to +51
inductive Proposition (T : Type u) : Type u where
| true
| false
| not (φ₁ : Proposition T)
| and (φ₁ φ₂ : Proposition T)
| or (φ₁ φ₂ : Proposition T)
| implies (φ₁ φ₂ : Proposition T)
| iff (φ₁ φ₂ : Proposition T)
| next (φ : Proposition T)
| eventually (φ : Proposition T)
| always (φ : Proposition T)
| until_op (φ : Proposition T) (φ : Proposition T)
| atom (p : T)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of trying to anticipate and enumerate all propositional operators you will ever need, I wonder if it is better to limit yourself to a minimal set of operators in terms of which other operators can be defined. For example, even with the expanded set of operators given above, you still miss one important operator:

def Proposition.leadsTo (φ₁ φ₂ : Proposition T) : Proposition T :=
  (φ₁.implies φ₂.eventually).always

variable (φ₁ φ₂ : Proposition T)
#check (φ₁.leadsTo φ₂)

As you can see, the dot-notation enables the new operator to be written and used pretty much like those in the original inductive definition. By limiting yourself to a minimal set of core operators which will likely stay stable, you will have fewer operators to deal with if you ever want to develop any proof theory for LTL.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes a lot of sense. On it 👍

| next (φ : Proposition T)
| eventually (φ : Proposition T)
| always (φ : Proposition T)
| until_op (φ : Proposition T) (φ : Proposition T)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure until doesn't work here? I played with it a little bit and it seems to work. These operators are never used "nakedly" and always appears as part of dot-notations.

@ctchou
Copy link
Contributor

ctchou commented Mar 17, 2026

One more comment: I wonder if it is possible to change the type of a model from ωSequence (Set T) to ωSequence State, where State : Type* is a "state space". This of course requires a corresponding change in the notion of an "atomic proposition", which will need to take an object p of type State -> Prop or Set State and assert either p (ls 0) or ls 0 \in p. This way a user of the LTL does not need to define a different type T for each specific application, which can be rather tedious. (Of course, he still need to define a specific State, but that's unavoidable.)

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.

3 participants