Zulip Chat Archive
Stream: new members
Topic: Some problem with rewriting
Ilmārs Cīrulis (Jan 11 2026 at 04:01):
See the line before the last sorry that I have commented out. The attempt to rewrite keeps going with no end, until heartbeats are exhausted.
I tried to use set_option trace.Meta.isDefEq true in, but it didn't help.
set_option pp.all true just made my eyes hurt with no gain (but I will try again).
import Mathlib.Combinatorics.SimpleGraph.Finite
import Mathlib.Data.Fin.VecNotation
import Mathlib.Tactic.DepRewrite
set_option linter.flexible false
set_option linter.unusedDecidableInType false
def add_vertex {n} (G : SimpleGraph (Fin n)) (vertices : Finset (Fin n)) :
SimpleGraph (Fin (n + 1)) :=
⟨fun (x y : Fin (n + 1)) =>
if h₁ : x = Fin.last n
then if h₂ : y = Fin.last n
then False
else (⟨y.val, by grind⟩ : Fin n) ∈ vertices
else if h₂ : y = Fin.last n
then (⟨x.val, by grind⟩ : Fin n) ∈ vertices
else G.Adj ⟨x.val, by grind⟩ ⟨y.val, by grind⟩,
by intros x y h; split_ifs at * <;> try grind
exact G.symm h,
by intros x h; simp at h; grind⟩
def remove_last_vertex {n} (G : SimpleGraph (Fin (n + 1))) [DecidableRel G.Adj] :
SimpleGraph (Fin n) :=
⟨fun x y => G.Adj x.castSucc y.castSucc,
fun _ _ h => G.symm h,
fun _ h => G.irrefl h⟩
lemma add_vertex_remove_last_vertex_eq_self {n} (G : SimpleGraph (Fin (n + 1)))
[DecidableRel G.Adj] :
add_vertex (remove_last_vertex G) {x : Fin n | G.Adj (Fin.last n) x.castSucc} = G := by
ext x y; simp [add_vertex, remove_last_vertex]; split_ifs
· rename_i h; subst h; simp; intros h h₀; subst h₀; exact G.irrefl h
· rename_i h₁ h₂; subst h₂; constructor <;> exact fun h => G.symm h
· rfl
instance add_vertex_decidable_adj :
∀ {n} (G : SimpleGraph (Fin n)) (vs : Finset (Fin n)) [DecidableRel G.Adj]
[∀ x, Decidable (x ∈ vs)], DecidableRel (add_vertex G vs).Adj := by
intros n G vs h₁ h₂
intros x y; simp [add_vertex]
split_ifs <;> rename_i h₃
· by_cases h₄ : y = Fin.last n <;> simp [h₄]
· exact instDecidableFalse
· apply h₂
· apply h₂
· apply h₁
lemma add_vertex_edgeFinset_card {n} (G : SimpleGraph (Fin n)) (vs : Finset (Fin n))
[DecidableRel G.Adj] [∀ x, Decidable (x ∈ vs)] :
(add_vertex G vs).edgeFinset.card = G.edgeFinset.card + vs.card := by sorry
lemma remove_last_vertex_of_complete_graph n :
remove_last_vertex (⊤ : SimpleGraph (Fin (n + 1))) = (⊤ : SimpleGraph (Fin n)) := by
ext x y; simp [remove_last_vertex]
lemma edgeset_card_of_complete_graph n :
(⊤ : SimpleGraph (Fin n)).edgeFinset.card = n.choose 2 := by
induction n with
| zero => simp [Sym2.diagSet]
| succ n iH =>
have h := add_vertex_remove_last_vertex_eq_self (⊤ : SimpleGraph (Fin (n + 1)))
rw [remove_last_vertex_of_complete_graph] at h
rw! (castMode := .all) [← h] -- bad sign, probably
-- rw [add_vertex_edgeFinset_card] -- keeps going until heartbeats end
sorry
Ilmārs Cīrulis (Jan 11 2026 at 04:05):
(It's just me reproving very basic result from graph theory, using Mathlib as little as reasonably possible. After I'm done, I will definitely take a look at Mathlib's proof.)
Aaron Liu (Jan 11 2026 at 04:06):
you probably have a mismatched implicit argument somewhere
Ilmārs Cīrulis (Jan 11 2026 at 04:07):
Okay, will take a look at them right now.
Aaron Liu (Jan 11 2026 at 04:08):
aha
Aaron Liu (Jan 11 2026 at 04:09):
it's the decidability instance which rw! (castMode := .all) has inserted a cast into
Aaron Liu (Jan 11 2026 at 04:11):
I discovered this by replacing your last few lines with
rw! (castMode := .all) [← h] -- bad sign, probably
have := add_vertex_edgeFinset_card ⊤ {x | (⊤ : SimpleGraph (Fin (n + 1))).Adj (Fin.last n) x.castSucc}
/-
Type mismatch
Eq.mpr (congrArg (fun x => x = ?m.73 x) this) ?m.76
has type
(@SimpleGraph.edgeFinset (Fin (n + 1)) (add_vertex ⊤ {x | ⊤.Adj (Fin.last n) x.castSucc})
(@SimpleGraph.fintypeEdgeSet (Fin (n + 1)) (add_vertex ⊤ {x | ⊤.Adj (Fin.last n) x.castSucc}) Sym2.instFintype
fun a b => add_vertex_decidable_adj ⊤ {x | ⊤.Adj (Fin.last n) x.castSucc} a b)).card =
?m.73 (add_vertex ⊤ {x | ⊤.Adj (Fin.last n) x.castSucc}).edgeFinset.card
but is expected to have type
(@SimpleGraph.edgeFinset (Fin (n + 1)) (add_vertex ⊤ {x | ⊤.Adj (Fin.last n) x.castSucc})
(@SimpleGraph.fintypeEdgeSet (Fin (n + 1)) (add_vertex ⊤ {x | ⊤.Adj (Fin.last n) x.castSucc}) Sym2.instFintype
(⋯ ▸ fun a b => SimpleGraph.Top.adjDecidable (Fin (n + 1)) a b))).card =
(n + 1).choose 2
-/
refine (congrArg (· = _) this).mpr ?_
-- rw [add_vertex_edgeFinset_card] -- keeps going until heartbeats end
sorry
Ilmārs Cīrulis (Jan 11 2026 at 04:11):
Thanks, I just wanted to ask how did you find it out.
Ilmārs Cīrulis (Jan 11 2026 at 04:13):
Such problem is the sign of bad approach/design, right?
Aaron Liu (Jan 11 2026 at 04:14):
maybe there should be a tactic that re-synthesizes all these instances
Aaron Liu (Jan 11 2026 at 04:15):
well I wouldn't say it's bad design really
Aaron Liu (Jan 11 2026 at 04:16):
though perhaps this could've been avoided by using a classical decidability instance within the proof and changing to the arbitrary decidability instance afterwards
Ilmārs Cīrulis (Jan 11 2026 at 05:16):
Okay, I solved it this way (removed the definition of instance and added additional Instance parameter to theorem).
import Mathlib.Combinatorics.SimpleGraph.Finite
import Mathlib.Data.Fin.VecNotation
import Mathlib.Tactic.DepRewrite
set_option linter.flexible false
set_option linter.unusedDecidableInType false
def add_vertex {n} (G : SimpleGraph (Fin n)) (vertices : Finset (Fin n)) :
SimpleGraph (Fin (n + 1)) :=
⟨fun (x y : Fin (n + 1)) =>
if h₁ : x = Fin.last n
then if h₂ : y = Fin.last n
then False
else (⟨y.val, by grind⟩ : Fin n) ∈ vertices
else if h₂ : y = Fin.last n
then (⟨x.val, by grind⟩ : Fin n) ∈ vertices
else G.Adj ⟨x.val, by grind⟩ ⟨y.val, by grind⟩,
by intros x y h; split_ifs at * <;> try grind
exact G.symm h,
by intros x h; simp at h; grind⟩
def remove_last_vertex {n} (G : SimpleGraph (Fin (n + 1))) [DecidableRel G.Adj] :
SimpleGraph (Fin n) :=
⟨fun x y => G.Adj x.castSucc y.castSucc,
fun _ _ h => G.symm h,
fun _ h => G.irrefl h⟩
lemma add_vertex_remove_last_vertex_eq_self {n} (G : SimpleGraph (Fin (n + 1)))
[DecidableRel G.Adj] :
add_vertex (remove_last_vertex G) {x : Fin n | G.Adj (Fin.last n) x.castSucc} = G := by
ext x y; simp [add_vertex, remove_last_vertex]; split_ifs
· rename_i h; subst h; simp; intros h h₀; subst h₀; exact G.irrefl h
· rename_i h₁ h₂; subst h₂; constructor <;> exact fun h => G.symm h
· rfl
-- removed the instance
-- added additional instance parameeter to this lemma
lemma add_vertex_edgeFinset_card {n} (G : SimpleGraph (Fin n)) (vs : Finset (Fin n))
[DecidableRel G.Adj] [∀ x, Decidable (x ∈ vs)] [DecidableRel (add_vertex G vs).Adj] :
(add_vertex G vs).edgeFinset.card = G.edgeFinset.card + vs.card := by sorry
lemma remove_last_vertex_of_complete_graph n :
remove_last_vertex (⊤ : SimpleGraph (Fin (n + 1))) = (⊤ : SimpleGraph (Fin n)) := by
ext x y; simp [remove_last_vertex]
lemma edgeset_card_of_complete_graph n :
(⊤ : SimpleGraph (Fin n)).edgeFinset.card = n.choose 2 := by
induction n with
| zero => simp [Sym2.diagSet]
| succ n iH =>
have h := add_vertex_remove_last_vertex_eq_self (⊤ : SimpleGraph (Fin (n + 1)))
rw [remove_last_vertex_of_complete_graph] at h
rw! (castMode := .all) [← h] -- bad sign, probably
rw [add_vertex_edgeFinset_card]
rw [iH]; simp
have h₀ : ({x : Fin n | ¬ Fin.last n = x.castSucc} : Finset _) = Finset.univ := by
ext x; simp; grind
rw [h₀]
simp [Nat.choose_succ_left, add_comm]
Last updated: Feb 28 2026 at 14:05 UTC