Zulip Chat Archive

Stream: new members

Topic: Problem proving statements about graphs


Leo Shine (Nov 27 2025 at 20:22):

Hi, I'm trying to prove a theorem saying that if a graph is acyclic then it is not 2-edge connected, (at least if there are at least 2 vertices...)

I would have thought this would be quite easy, all you have to do in informal maths, is suppose it was edge connected and acyclic take a path from one node to another, delete the first edge from that path from the graph, the 2-edge-connectedness implies there's still a path from one node to the other, so we get a second path, these paths can't be the same because they don't share a first edge, also its a mathlib theorem that paths between two nodes in an acyclic graphs are unique, so therefore we have a contradiction.

I'm sure I'm just interacting with lean in a horrible way, but the thing that I seem to be really strugglign to prove is that the two paths are not equal, this seems like it ought to be the simple part of the proof. In general how do people go about trying to deal with challenges like this, where a seemingly trivial step is difficult? And does anyone have any advice on ensuring you don't get really messy formalizations like the one below seems to be.

import Mathlib.Combinatorics.SimpleGraph.Acyclic
namespace SimpleGraph
variable {V V' : Type*} (G : SimpleGraph V) (G' : SimpleGraph V')
open Walk
def IsEdgeReachable (k : ) (u v : V) : Prop :=
   s : Set (Sym2 V)⦄, s.encard < k  (G.deleteEdges s).Reachable u v

def IsEdgeConnected (k : ) : Prop :=  u v, G.IsEdgeReachable k u v


theorem IsAcyclic.not_twoConnected (h : G.IsAcyclic) (u : V) (v : V) (hunev : u  v)
    : ¬ G.IsEdgeConnected 2 := by
  by_contra hconn
  specialize hconn u v
  by_cases h2 : G.Reachable u v
  · obtain  p1: G.Walk u v, hp1  := (Reachable.exists_isPath h2)
    match hp1eq : p1 with
    | nil => contradiction
    | cons' _ w vvv huw p =>
      let s1 := ({s(u,w)} : Set (Sym2 V))
      have hv : v = vvv:= by assumption
      subst hv
      have hsletwo : s1.encard < 2 := by
        unfold s1
        simp
      have hdeladj: ¬(G.deleteEdges s1).Adj u w :=by
            unfold s1
            unfold deleteEdges
            unfold Adj
            simp
            intro h3 h4
            rw [h4] at h3
            apply G.loopless w h3
      specialize hconn hsletwo
      obtain  p2: (G.deleteEdges s1).Walk u v, hp2  := (Reachable.exists_isPath hconn)
      -- use isAcyclic_iff_path_unique paths then show path having removed an edge in the first path
      -- from the graph is not equal
      match hp2eq : p2 with
      | nil => contradiction
      | cons' _ w' vv huw' prst =>
        have wne : w'  w:= by
          by_contra hweq
          rw[ hweq] at hdeladj
          contradiction
        let p3 := p2.mapLe (deleteEdges_le s1)
        have hv : v = vv:= by assumption
        subst hv
        have hp2eq:  p2 = cons huw' prst := by
          cases hp2eq
          simp
        have hp1eq:  p1 = cons huw p := by
          cases hp1eq
          simp
        have hp1: p1.IsPath := by
          unfold cons' at hp1
          rw[hp1eq]
          assumption
        have hp3 : p3.IsPath := by
          refine (mapLe_isPath (deleteEdges_le s1)).mpr ?_
          unfold cons' at hp2
          rw[hp2eq]
          assumption
        rw[isAcyclic_iff_path_unique] at h
        specialize h p3, hp3 p1, hp1
        -- Now prove not the same
        have h: p3 = p1 := by simpa using h
        rw[ h] at hp1eq
        unfold p3 at hp1eq
        rw[hp2eq] at hp1eq
        unfold mapLe at hp1eq
        unfold Walk.map at hp1eq
        sorry
  · have hempt: ( : Set (Sym2 V)).encard < 2 := by
      simp
    specialize hconn  hempt
    rw[deleteEdges_empty] at hconn
    contradiction

Vlad Tsyrklevich (Nov 28 2025 at 09:10):

import Mathlib.Combinatorics.SimpleGraph.Acyclic
namespace SimpleGraph
variable {V V' : Type*} (G : SimpleGraph V) (G' : SimpleGraph V')
open Walk
def IsEdgeReachable (k : ) (u v : V) : Prop :=
   s : Set (Sym2 V)⦄, s.encard < k  (G.deleteEdges s).Reachable u v

def IsEdgeConnected (k : ) : Prop :=  u v, G.IsEdgeReachable k u v

theorem IsAcyclic.not_twoConnected (h : G.IsAcyclic) (u : V) (v : V) (hunev : u  v)
    : ¬ G.IsEdgeConnected 2 := by
  simp [IsEdgeConnected, IsEdgeReachable]
  by_cases h' :  w : V, G.Adj u w
  · obtain w, hadj := h'
    have := SimpleGraph.isAcyclic_iff_forall_adj_isBridge.mp h hadj
    have : ¬(G.deleteEdges {s(u, w)}).Reachable u w := this.2
    exact u, w, {s(u, w)}, by simp, this
  · refine u, v, , by simp, ?_⟩
    simp at  h'
    by_contra hh
    obtain w := hh
    exact h' w.snd (w.adj_snd (not_nil_of_ne hunev))

Vlad Tsyrklevich (Nov 28 2025 at 09:12):

The IsBridge API already provides what you wanted, so it was easier to just use it rather than trying to re-derive its basic properties on the spot. I was reminded that isBridge existed by loogling for lemmas about acyclicity

Vlad Tsyrklevich (Nov 28 2025 at 09:13):

also JFYI the canonical spelling of (u : V) (v : V) (hunev : u ≠ v) is Nontrivial V

Vlad Tsyrklevich (Nov 28 2025 at 09:26):

Leo Shine said:

In general how do people go about trying to deal with challenges like this, where a seemingly trivial step is difficult?

The approach you take on pen-and-paper is not always what makes the most sense in formalization. Searching the library for what's available to you should inform how you approach the proof.

When something is painful it often means you want some more basic piece of API. That might mean proving more basic facts about IsEdgeReachable/Connected, or in this case you want some basic API about deleting edges disconnecting a graph. In this case it happened to already exist, but often times it helps to step back and ask yourself "What is the general statement that would solve the problem I am having right now?" and often times it can be easier and cleaner to prove the more general statement rather than your specific instance.

Kevin Buzzard (Nov 28 2025 at 09:28):

i.e. "seek the right abstraction".

Leo Shine (Nov 28 2025 at 12:09):

Thanks ill look at this this evening

Leo Shine (Nov 28 2025 at 20:02):

Okay had a look at this, and this is really helpful thank you for the help


Last updated: Dec 20 2025 at 21:32 UTC