Zulip Chat Archive
Stream: mathlib4
Topic: FOL logic with unary predicates
Yury G. Kudryashov (May 25 2023 at 04:22):
Are there effective algorithms to prove statements in FOL if only one-variable predicates are involved? I tried to golf docs4#isPreconnected_closed_iff and after
rw [IsPreconnected, compl_surjective.forall]
refine forall_congr' fun u ↦ compl_surjective.forall.trans <| forall_congr' fun v ↦ ?_
simp only [isOpen_compl_iff]
refine forall_congr' fun hu ↦ forall_congr' fun hv ↦ ?_
I've got the goal
s ⊆ uᶜ ∪ vᶜ → Set.Nonempty (s ∩ uᶜ) → Set.Nonempty (s ∩ vᶜ) → Set.Nonempty (s ∩ (uᶜ ∩ vᶜ)) ↔
s ⊆ u ∪ v → Set.Nonempty (s ∩ u) → Set.Nonempty (s ∩ v) → Set.Nonempty (s ∩ (u ∩ v))
This is a statement that is true for any three sets s
, u
, v
. It would be nice to have a tactic that closes this goal automatically.
Yury G. Kudryashov (May 25 2023 at 04:25):
I guess, in this case one can reformulate each atom like s ⊆ u ∪ v
as a statement about parts of the corresponding Venn diagram being (non)empty, then get a statement in propositional logic.
Mario Carneiro (May 25 2023 at 04:25):
there was a tactic along those lines
Yury G. Kudryashov (May 25 2023 at 04:26):
There was or there is?
Mario Carneiro (May 25 2023 at 04:26):
it was a zulip discussion
Mario Carneiro (May 25 2023 at 04:26):
I forget how far along it actually got, it did not land in mathlib
Mario Carneiro (May 25 2023 at 04:26):
the simple version is to introduce x, simp everything to propositional logic and call tauto
Yury G. Kudryashov (May 25 2023 at 04:27):
What do you mean by "introduce x"?
Mario Carneiro (May 25 2023 at 04:28):
well I guess your goal is more complicated because you have multiple existential quantifiers
Yury G. Kudryashov (May 25 2023 at 04:28):
simp [subset_def, Set.Nonempty]
tauto
Mario Carneiro (May 25 2023 at 04:28):
the version that was in the discussion only handled universal quantifiers IIRC
Mario Carneiro (May 25 2023 at 04:28):
for stuff like subset masquerading as implication
Yury G. Kudryashov (May 25 2023 at 04:29):
Leaves many goals like
case mp.inl.h.right.right
α : Type u
β : Type v
ι : Type ?u.23250
π : ι → Type ?u.23255
inst : TopologicalSpace α
s t u v s u v : Set α
hu : IsClosed u
hv : IsClosed v
em : (a : Prop) → Decidable a
h : ¬∀ (x : α), x ∈ s → ¬x ∈ u ∨ ¬x ∈ v
a⁴ : ∀ (x : α), x ∈ s → x ∈ u ∨ x ∈ v
x¹ : α
a³ : x¹ ∈ s
a² : x¹ ∈ u
x : α
a¹ : x ∈ s
a : x ∈ v
⊢ x¹ ∈ v
Yury G. Kudryashov (May 25 2023 at 04:29):
(deleted)
Mario Carneiro (May 25 2023 at 04:31):
yeah I think we need a FOL tactic to prove this
Mario Carneiro (May 25 2023 at 04:31):
if you instantiate the quantifiers manually it can probably be done with the existing tools
Yury G. Kudryashov (May 25 2023 at 04:34):
What means instantiate the quantifiers manually?
Mario Carneiro (May 25 2023 at 04:35):
have := a⁴ _ a¹; have := a⁴ _ a³; tauto
Mario Carneiro (May 25 2023 at 04:35):
something like that
Yury G. Kudryashov (May 25 2023 at 04:35):
(a) my goal is to avoid intervention; (b) those a^k only appear after the call to tauto
.
Mario Carneiro (May 25 2023 at 04:36):
(a) yes I'm aware
Mario Carneiro (May 25 2023 at 04:36):
the tactic doesn't exist
Mario Carneiro (May 25 2023 at 04:36):
at least not until the likes of duper
make it to mathlib
Yury G. Kudryashov (May 25 2023 at 04:36):
What is duper
?
Yury G. Kudryashov (May 25 2023 at 04:37):
Should I open a github issue?
Mario Carneiro (May 25 2023 at 04:37):
https://github.com/leanprover-community/duper, WIP superposition prover in lean 4
Mario Carneiro (May 25 2023 at 04:38):
For FOL proving? This is a long standing issue, we've known about it since the beginning of lean 3
Yury G. Kudryashov (May 25 2023 at 04:38):
No README... Probably, a clear sign of "WIP"
Mario Carneiro (May 25 2023 at 04:39):
making a good FOL prover is really challenging, especially when you mix it with all the higher order stuff in lean
Yury G. Kudryashov (May 25 2023 at 04:40):
Do I understand correctly that FOL with unary predicates is doable, FOL with binary predicates is undecidable? Is it undecidable in practice or there is an algorithm that works for reasonably sized formulas provided that they're true?
Mario Carneiro (May 25 2023 at 04:41):
It's not undecidable in practice, but it is heuristic
Mario Carneiro (May 25 2023 at 04:41):
The success rate depends quite strongly on the complexity of the goal
Yury G. Kudryashov (May 25 2023 at 04:42):
BTW, are there any prover-independent solutions to this? Like an external tool or a C/C++ library that can take an input formula and give you a proof in some machine-readable format?
Mario Carneiro (May 25 2023 at 04:42):
Z3 (leo's project before lean) is an SMT solver (aka FOL plus theories like linear arithmetic)
Yury G. Kudryashov (May 25 2023 at 04:43):
Can we somehow call it (or another similar tool) from Lean 4?
Mario Carneiro (May 25 2023 at 04:43):
there are other SMT solvers as well like vampire (which had an open PR to mathlib for a long time)
Mario Carneiro (May 25 2023 at 04:44):
the other problem with calling such tools is that you often don't get a proof back, just an assertion "it's true"
Mario Carneiro (May 25 2023 at 04:44):
or at least not something which can be externally checked, much less reconstructed into a lean proof
Mario Carneiro (May 25 2023 at 04:45):
many of these properties disqualify them from being used in mathlib proofs
Yury G. Kudryashov (May 25 2023 at 04:46):
Of course, "it's true" is not enough.
Mario Carneiro (May 25 2023 at 04:46):
As for unary predicates... it's plausible to me that this fragment is decidable (at least, assuming the term language isn't too fancy), but I assume you want to include equality, and that's a binary predicate
Mario Carneiro (May 25 2023 at 04:46):
I'm not sure how useful that fragment is in practice
Yury G. Kudryashov (May 25 2023 at 04:46):
In this example I don't need equality.
Mario Carneiro (May 25 2023 at 04:47):
you are using a binary predicate though (actually, probably a 4-ary predicate since lean has implicits everywhere) so writing a tactic that knows what to ignore is quite a tricky part of this goal
Mario Carneiro (May 25 2023 at 04:48):
I think it would be more useful to just have a general FOL instantiation tactic rather than a decision procedure for unary predicate FOL
Yury G. Kudryashov (May 25 2023 at 04:49):
OK, I'll just leave the proof we had.
Mario Carneiro (May 25 2023 at 04:49):
I mean, in this case you can just instantiate all quantifiers at all ground terms and get a proof by propositional logic
Yury G. Kudryashov (May 25 2023 at 04:50):
There are many statements in Topology/Connected
that are repeated for open and closed sets
Yury G. Kudryashov (May 25 2023 at 04:51):
And in most cases one can go from one statement to another by something I wrote in the first few lines: replace all open sets by their complements which are closed.
Mario Carneiro (May 25 2023 at 04:51):
the fact that your theorem is not quantified over u and v makes it a lot less obvious to me
Yury G. Kudryashov (May 25 2023 at 04:52):
It is quantified. The first 2 lines get rid of that.
Mario Carneiro (May 25 2023 at 04:53):
I mean that while
(\forall u v, s ⊆ uᶜ ∪ vᶜ → Set.Nonempty (s ∩ uᶜ) → Set.Nonempty (s ∩ vᶜ) → Set.Nonempty (s ∩ (uᶜ ∩ vᶜ))) ↔
(\forall u v, s ⊆ u ∪ v → Set.Nonempty (s ∩ u) → Set.Nonempty (s ∩ v) → Set.Nonempty (s ∩ (u ∩ v)))
looks obviously true to me,
(s ⊆ uᶜ ∪ vᶜ → Set.Nonempty (s ∩ uᶜ) → Set.Nonempty (s ∩ vᶜ) → Set.Nonempty (s ∩ (uᶜ ∩ vᶜ))) ↔
(s ⊆ u ∪ v → Set.Nonempty (s ∩ u) → Set.Nonempty (s ∩ v) → Set.Nonempty (s ∩ (u ∩ v)))
looks a lot harder and possibly false
Mario Carneiro (May 25 2023 at 04:54):
If you were to keep the quantifiers and substitute u |-> uᶜ
and v |-> vᶜ
then simp could probably do this proof
Yury G. Kudryashov (May 25 2023 at 04:55):
Let me try
Yury G. Kudryashov (May 25 2023 at 04:56):
rw [IsPreconnected, compl_surjective.forall]
refine forall_congr' fun u ↦ compl_surjective.forall.trans ?_
revert u
simp [subset_def, Set.Nonempty]
fails
Mario Carneiro (May 25 2023 at 04:56):
what's the goal?
Mario Carneiro (May 25 2023 at 04:56):
you don't need to unfold subset_def
or Set.Nonempty
for this proof
Yury G. Kudryashov (May 25 2023 at 04:56):
⊢ ∀ (u : Set α),
(∀ (x : Set α),
IsClosed u →
IsClosed x →
(∀ (x_1 : α), x_1 ∈ s → ¬x_1 ∈ u ∨ ¬x_1 ∈ x) →
∀ (x_1 : α), x_1 ∈ s → ¬x_1 ∈ u → ∀ (x_2 : α), x_2 ∈ s → ¬x_2 ∈ x → ∃ x_3, x_3 ∈ s ∧ ¬x_3 ∈ u ∧ ¬x_3 ∈ x) ↔
∀ (t' : Set α),
IsClosed u →
IsClosed t' →
(∀ (x : α), x ∈ s → x ∈ u ∨ x ∈ t') →
∀ (x : α), x ∈ s → x ∈ u → ∀ (x : α), x ∈ s → x ∈ t' → ∃ x, x ∈ s ∧ x ∈ u ∧ x ∈ t'
Mario Carneiro (May 25 2023 at 04:57):
I guess I don't understand what the original goal was and how you want to prove it
Yury G. Kudryashov (May 25 2023 at 04:58):
Here is the original proof from mathlib4:
⟨by
rintro h t t' ht ht' htt' ⟨x, xs, xt⟩ ⟨y, ys, yt'⟩
rw [← not_disjoint_iff_nonempty_inter, ← subset_compl_iff_disjoint_right, compl_inter]
intro h'
have xt' : x ∉ t' := (h' xs).resolve_left (absurd xt)
have yt : y ∉ t := (h' ys).resolve_right (absurd yt')
have := h _ _ ht.isOpen_compl ht'.isOpen_compl h' ⟨y, ys, yt⟩ ⟨x, xs, xt'⟩
rw [← compl_union] at this
exact this.ne_empty htt'.disjoint_compl_right.inter_eq,
by
rintro h u v hu hv huv ⟨x, xs, xu⟩ ⟨y, ys, yv⟩
rw [← not_disjoint_iff_nonempty_inter, ← subset_compl_iff_disjoint_right, compl_inter]
intro h'
have xv : x ∉ v := (h' xs).elim (absurd xu) id
have yu : y ∉ u := (h' ys).elim id (absurd yv)
have := h _ _ hu.isClosed_compl hv.isClosed_compl h' ⟨y, ys, yu⟩ ⟨x, xs, xv⟩
rw [← compl_union] at this
exact this.ne_empty huv.disjoint_compl_right.inter_eq⟩
Mario Carneiro (May 25 2023 at 04:59):
ah yeah that can be golfed
Mario Carneiro (May 25 2023 at 04:59):
and your replacement?
Yury G. Kudryashov (May 25 2023 at 04:59):
The problem is that while the formulas are equivalent (in FOL, after the cleanup I made), it is not "obvious": the terms in the implications do not correspond to each other.
Yury G. Kudryashov (May 25 2023 at 05:01):
The replacement I tried to write starts with
rw [IsPreconnected, compl_surjective.forall]
refine forall_congr' fun u ↦ compl_surjective.forall.trans ?_
simp only [isOpen_compl_iff]
and leaves a goal that is true in FOL.
Yury G. Kudryashov (May 25 2023 at 05:01):
(at least if you unfold definitions of subset and nonempty)
Mario Carneiro (May 25 2023 at 05:01):
what happened to t
and t'
?
Mario Carneiro (May 25 2023 at 05:01):
from the original theorem
Yury G. Kudryashov (May 25 2023 at 05:02):
I used compl_surjective.forall.trans _
to unify sets in LHS and RHS.
Yury G. Kudryashov (May 25 2023 at 05:03):
As you can see, the original proof calls h
with the complements of the available sets.
Yury G. Kudryashov (May 25 2023 at 05:18):
Anyway, this is a low priority question (at least, for me and now). Sorry for taking so much of your time.
Yury G. Kudryashov (May 25 2023 at 05:18):
I mean, there is no theorem I can't prove without it, it's only about hiding technical details of some proofs.
Mario Carneiro (May 25 2023 at 05:43):
Here's my golf of the proof:
rw [IsPreconnected, compl_surjective.forall]
let P u u' := s ⊆ u ∪ u' → (s ∩ u).Nonempty → (s ∩ u').Nonempty → (s ∩ (u ∩ u')).Nonempty
suffices ∀ {u u'}, P u u' → P (uᶜ) (u'ᶜ) by
refine forall_congr' fun u ↦ compl_surjective.forall.trans ?_
simp only [isOpen_compl_iff]
constructor <;> exact fun H v hu hv ↦ by simpa using this (H v hu hv)
simp only [← not_disjoint_iff_nonempty_inter, ← subset_compl_iff_disjoint_right, compl_inter,
compl_compl] at *
refine fun h huv hu hv huv' ↦ h huv' ?_ ?_ huv
· exact fun h' ↦ hv fun x hx ↦ (huv' hx).resolve_left (h' hx)
· exact fun h' ↦ hu fun x hx ↦ (huv' hx).resolve_right (h' hx)
Mario Carneiro (May 25 2023 at 05:46):
it could be golfed a bit more with the lemma a ⊆ b ∪ c → a ⊆ bᶜ → a ⊆ c
(i.e. resolve_left
for subsets)
Yury G. Kudryashov (May 25 2023 at 06:22):
Thanks!
Last updated: Dec 20 2023 at 11:08 UTC