Zulip Chat Archive
Stream: graph theory
Topic: matchings
Alena Gusakov (Dec 02 2020 at 22:05):
Is there anything else I need to do to get #5156 approved? There were two suggestions that I put aside for later, should I just implement them now?
Alena Gusakov (Dec 03 2020 at 23:24):
Don't know where to ask this - do people typically keep working from a branch after a PR from it has been approved?
Mario Carneiro (Dec 03 2020 at 23:34):
github prefers that you don't
Alena Gusakov (Dec 03 2020 at 23:34):
gotcha
Mario Carneiro (Dec 03 2020 at 23:34):
the UI gets a little wonky if you try to reopen a PR or reuse a PR branch
Alena Gusakov (Dec 03 2020 at 23:35):
i was just thinking that it feels a bit wasteful to keep making new branches for PRs
Mario Carneiro (Dec 03 2020 at 23:35):
you can delete the old ones, you know
Alena Gusakov (Dec 03 2020 at 23:35):
this is true, but does that delete the comment history?
Mario Carneiro (Dec 03 2020 at 23:35):
no
Alena Gusakov (Dec 03 2020 at 23:35):
ah okay, then that works lol
Alena Gusakov (Dec 03 2020 at 23:36):
thanks
Mario Carneiro (Dec 03 2020 at 23:36):
although it may make it harder to track down the commits they are attached to
Mario Carneiro (Dec 03 2020 at 23:36):
but if they have been squash merged in it's not particularly important to retain them
Alena Gusakov (Dec 03 2020 at 23:36):
gotcha
Eric Wieser (Dec 03 2020 at 23:38):
Bors deletes merged branches anyway, doesn't it?
Alena Gusakov (Dec 03 2020 at 23:39):
https://github.com/leanprover-community/mathlib/tree/simple_graph_matching
Alena Gusakov (Dec 03 2020 at 23:39):
this one's still up
Mario Carneiro (Dec 03 2020 at 23:39):
what's the PR?
Alena Gusakov (Dec 03 2020 at 23:40):
without realizing it i committed Eric's suggestion at the bottom, and that seems to have done something weird
Eric Wieser (Dec 03 2020 at 23:40):
You sure you didn't put it back up after bors deleted it?
Alena Gusakov (Dec 03 2020 at 23:40):
I honestly have no clue
Mario Carneiro (Dec 03 2020 at 23:40):
20 commits ahead and 25 behind master sounds like a bad sign
Alena Gusakov (Dec 03 2020 at 23:40):
Maybe I did some weird branching or something
Alena Gusakov (Dec 03 2020 at 23:41):
the original commit is still good
Alena Gusakov (Dec 03 2020 at 23:42):
https://github.com/leanprover-community/mathlib/pull/5156
Alena Gusakov (Dec 03 2020 at 23:42):
here's the PR
Eric Wieser (Dec 03 2020 at 23:43):
I find the bors way of rebasing all PRs at merge time makes it really hard to work with branches that build on top of multiple open PRs, as you then have no easy way to merge in master when the PRs you depend on get in
Alena Gusakov (Dec 03 2020 at 23:43):
Nevermind, it wasn't the commit. I genuinely have no idea what happened there
Alena Gusakov (Dec 03 2020 at 23:43):
I might've just done something wrong accidentally because I was jumping back and forth between the two PRs I had open
Alena Gusakov (Dec 03 2020 at 23:44):
I can delete the branch maybe?
Mario Carneiro (Dec 03 2020 at 23:45):
you can delete it, but make sure you have everything you want to keep from it first
Alena Gusakov (Dec 03 2020 at 23:46):
Actually I think it's okay - it looks like the PR keeps the comment history
Alena Gusakov (Dec 03 2020 at 23:47):
To delete I mean
Kyle Miller (Jun 22 2021 at 17:26):
There's some stuff about matchings here: https://github.com/leanprover-community/mathlib/blob/simple_graph_matching/src/combinatorics/simple_graph/matching.lean
For a perfect matching, it occurred to me that it might be useful to have an equivalence with this type:
{ g : V → V // (∀ v, G.adj v (g v)) ∧ involutive g }
(or rather, given a perfect matching, have a definition for the V → V
function and a lemma for the property it satisfies).
I think there are some partial versions of this in there already.
Tutte's theorem might be a good to prove to develop the matchings part of the library, if someone wants a graph theory project.
Alena Gusakov (Jun 22 2021 at 17:26):
oh true, i forgot about tutte's theorem
Alena Gusakov (Jun 22 2021 at 17:27):
that was gonna be my next goal
Kyle Miller (Jun 22 2021 at 17:28):
I've stated it at https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/some.20newbie.20questions.20about.20following.20progress/near/243549319 but it needs the "right" definitions of connected components in terms of walks, I think.
Alena Gusakov (Jun 22 2021 at 17:28):
oh neat, okay
Kyle Miller (Jun 22 2021 at 17:28):
Ok, I hereby declare that @Alena Gusakov has claimed the theorem
Yaël Dillies (Jun 22 2021 at 18:01):
Is there any generalisation of matchings we might want to consider?
Eric Rodriguez (Jun 22 2021 at 18:05):
Alena, there's an ancient PR of yours I reviewed (what feels like) centuries ago. Are you still interested in that or should I just fix it up ^^
Mario Krenn (Jun 22 2021 at 18:39):
I am very interested in understanding and playing with perfect matchings - mainly because I want to see how a proof like this (https://mathoverflow.net/questions/267002/graphs-with-only-disjoint-perfect-matchings) would be formalized.
The reason behind is, that a generalization of this statement to weighted graph is an open question, and has important relevance in quantum mechanics (and it looks simple enough to be a good starting point to Lean). Do you think it is a reasonably simple project as a beginner of Lean? Curious about your thoughts. Thanks :)
Kyle Miller (Jun 22 2021 at 18:49):
@Yaël Dillies I'm not sure of any real uses of it, but there's a weakened version of a perfect matching that you might call a function carried by a graph. It's a subgraph of the graph that contains every vertex and which has been given an orientation such that each vertex has exactly one outgoing edge. You can represent it by this type:
{ g : V → V // (∀ v, G.adj v (g v)) ∧ injective (λ v, ⟦(v, g v)⟧) }
Here it is formalized for current mathlib:
import data.finset
import data.fintype.basic
import combinatorics.simple_graph.basic
import combinatorics.hall
open function
open simple_graph
/-- A necessary and sufficient condition for there to be a "function carried by a graph" is that
the set of edges incident to each finite subset of k vertices has at least k edges, for each k. -/
theorem exists_carried_fun_iff {V : Type*} [fintype V] [decidable_eq V]
(G : simple_graph V) [decidable_rel G.adj] :
(∀ (U : finset V), U.card ≤ (U.bUnion (λ u, G.incidence_finset u)).card)
↔ (∃ (g : V → V), (∀ v, G.adj v (g v)) ∧ injective (λ v, ⟦(v, g v)⟧)) :=
begin
convert finset.all_card_le_bUnion_card_iff_exists_injective (λ v, G.incidence_finset v) using 1,
ext,
split,
{ rintro ⟨g, ha, hinj⟩,
use λ v, ⟦(v, g v)⟧,
use hinj,
simpa using ha, },
{ rintro ⟨f, hinj, hi⟩,
simp only [mem_incidence_finset] at hi,
use λ v, (hi v).2.other,
split,
{ intro v,
have h := (hi v).1,
rw ←sym2.mem_other_spec (hi v).2 at h,
rwa mem_edge_set at h, },
{ simp only [hinj, sym2.mem_other_spec] }, },
end
Kyle Miller (Jun 22 2021 at 18:54):
This also works for infinite graphs so long as the graph is locally finite, using the infinite version of Hall's theorem (infinite Hall is currently in a PR)
Yaël Dillies (Jun 22 2021 at 18:58):
Oh nice!
Yaël Dillies (Jun 22 2021 at 18:59):
Note that Bhavik and Alena's paper is a bit unclear about whether it's true for all functions or whether we choose it.
Yaël Dillies (Jun 22 2021 at 19:00):
Also I think this is exactly stating that G has a 2-factor. A perfect matching is a 1-factor.
Kyle Miller (Jun 22 2021 at 19:04):
Mario Krenn said:
I want to see how a proof like this (https://mathoverflow.net/questions/267002/graphs-with-only-disjoint-perfect-matchings) would be formalized. [...] Do you think it is a reasonably simple project as a beginner of Lean?
I think the usual advice is that beginners should prove things involving objects that are already defined -- making good definitions for formalization is tricky. Also, combinatorics seems to be particularly tricky to formalize because proofs tend to appeal to intuition.
Right now the simple graph library lacks walks, paths, cycles, and Hamiltonian cycles (and their supporting lemmas). If you feel up to it, you can try your hand at these things and get help along the way here on Zulip. In a way it shouldn't be hard, but I'm not sure it'll be a simple project.
Kyle Miller (Jun 22 2021 at 19:10):
Yaël Dillies said:
unclear about whether it's true for all functions or whether we choose it.
It should have also said "a graph carries a function if there exists a function that the graph carries." This is my fault.
I don't think a graph carrying a function is equivalent to it having a 2-factor. It's whether there's a spanning subgraph such that each component has exactly one cycle. So, cycles with trees growing out of them.
Yaël Dillies (Jun 22 2021 at 19:10):
Ah I see
Yaël Dillies (Jun 22 2021 at 19:11):
Mario Krenn said:
Do you think it is a reasonably simple project as a beginner of Lean? Curious about your thoughts. Thanks :)
My advice for you is to not work alone. Get someone to help you along the way. Stick yourself to an existing project you already understand mathematically.
Kyle Miller (Jun 22 2021 at 20:14):
@Mario Krenn By the way, in case it's useful, here's a potential formalization of the theorem statement:
import combinatorics.simple_graph.basic
import combinatorics.simple_graph.matching
open_locale classical
noncomputable theory
open fintype
-- https://mathoverflow.net/questions/267002/graphs-with-only-disjoint-perfect-matchings
lemma k4_if_three_disjoint_perfect_matchings {V : Type*} [fintype V]
(G : simple_graph V)
(m₁ m₂ m₃ : G.matching)
(h₁ : m₁.is_perfect) (h₂ : m₂.is_perfect) (h₃ : m₃.is_perfect)
(d₁₂ : disjoint m₁.edges m₂.edges) (d₁₃ : disjoint m₁.edges m₃.edges) (d₂₃ : disjoint m₂.edges m₃.edges) :
card V = 4 ∧ G = complete_graph V :=
sorry
Kyle Miller (Jun 22 2021 at 20:31):
I must not have understood the theorem, because this is a counterexample to the formalized statement:
image.png
You can get such a counterexample from any face 3-coloring of a 3-regular graph cellularly embedded on a surface. (In this case, a cube graph on a plane/sphere.)
Kyle Miller (Jun 22 2021 at 20:34):
Actually, any 3-regular graph that's edge 3-colorable works as a counterexample. Each set of edges of the same color forms a perfect matching, and these sets are disjoint.
Alena Gusakov (Jun 22 2021 at 20:46):
@Eric Rodriguez sorry about that, i'll try to circle back to that PR this week or something
Alena Gusakov (Jun 22 2021 at 20:46):
i've just completely forgotten about it cause i started a class
Kyle Miller (Jun 22 2021 at 20:47):
I think I've understood it now. Corrected:
import combinatorics.simple_graph.basic
import combinatorics.simple_graph.matching
open_locale classical
noncomputable theory
open fintype
instance {V : Type*} [fintype V] (G : simple_graph V) : fintype G.matching := sorry
-- https://mathoverflow.net/questions/267002/graphs-with-only-disjoint-perfect-matchings
lemma k4_if_perfect_matchings_disjoint {V : Type*} [fintype V]
(G : simple_graph V)
(hc : card {m : G.matching | m.is_perfect} ≥ 3)
(hd : ∀ (m m' : G.matching), m.is_perfect → m'.is_perfect → m ≠ m' → disjoint m.edges m'.edges) :
card V = 4 ∧ G = complete_graph V :=
sorry
Kyle Miller (Jun 22 2021 at 21:03):
I think this corrected theorem is still not correct, though, because there's another counterexample:
image.png
This is the generalized Petersen graph G(9,2), which is uniquely edge 3-colorable (meaning, up to permutation of colors, there is only one edge 3-coloring).
If you have a graph such that all its perfect matchings are disjoint, then you can take the subgraph consisting of edges that are members of one of the perfect matchings. If there are at least three perfect matchings, then choose three of the perfect matchings and throw the rest of the edges out. If you take each perfect matching as a distinct color, then you are left with an edge 3-coloring. Conversely, given an edge 3-coloring you get three disjoint perfect matchings on the original graph.
Yaël Dillies (Jun 22 2021 at 21:05):
Their argument is to form a cycle from two matchings. What does it give here?
Kyle Miller (Jun 22 2021 at 21:14):
Matsumoto, "Conjectures on uniquely 3-edge colorable graphs" in Contributions to Discrete Mathematics (2016) lists some conjectures. Fiorini and Wilson conjecture that every nonplanar 3-regular uniquely edge 3-colorable graph is related to G(9,2) by a sequence of delta-wye moves, and that every planar 3-regular uniquely edge 3-colorable graph is related to K_4 by a sequence of delta-wye moves.
Yaël Dillies (Jun 22 2021 at 21:15):
Oh wow! That was quite a quick digging up
Kyle Miller (Jun 22 2021 at 21:16):
I think I've made a silly mistake though. Just because a graph is uniquely edge 3-colorable doesn't mean there are only three perfect matchings. It's worth checking G(9,2) just to be sure...
Kevin Buzzard (Jun 22 2021 at 21:21):
Did you see the recent AI graph counterexample paper?
Yaël Dillies (Jun 22 2021 at 21:22):
Oh what's that?
Kevin Buzzard (Jun 22 2021 at 21:22):
Gowers tweeted about it a few weeks ago and it was discussed here too, maybe in one of the ML streams
Mario Krenn (Jun 22 2021 at 21:51):
Kyle Miller said:
I must not have understood the theorem, because this is a counterexample to the formalized statement:
image.pngYou can get such a counterexample from any face 3-coloring of a 3-regular graph cellularly embedded on a surface. (In this case, a cube graph on a plane/sphere.)
Thanks for the examples. However, this graph has more than 3 perfect matchings. grafik.png -- and thus not all PMs are disjoint sets of edges.
Kyle Miller (Jun 22 2021 at 21:52):
@Mario Krenn I also just counted the number of perfect matchings for G(9,2): 22
Mario Krenn (Jun 22 2021 at 21:55):
@Kyle Miller Ah ok good. If you find a counter example, send me your bank account. I announced a 3000Euro prize for a counter example (or proof) of the generalization :D (see https://mariokrenn.wordpress.com/graph-theory-question/ or https://mathoverflow.net/questions/311325/vertex-coloring-inherited-from-perfect-matchings-motivated-by-quantum-physics)
Kyle Miller (Jun 22 2021 at 21:55):
The cube example was from when I thought it was whether there existed three disjoint perfect matchings, and G(9,2) was when I mistakenly thought having three simultaneously disjoint perfect matchings in a cubic graph meant there couldn't be more perfect matchings. The second formalized theorem statement seems to be correct so far.
Mario Krenn (Jun 22 2021 at 21:59):
Kyle Miller said:
Mario Krenn By the way, in case it's useful, here's a potential formalization of the theorem statement:
Wow thats so cool, thanks a lot, will try to go through it tomorrow in detail! thanks :)
Eric Rodriguez (Jun 22 2021 at 22:03):
Alena Gusakov said:
Eric Rodriguez sorry about that, i'll try to circle back to that PR this week or something
No worries, hadn't seen you around in forever so just wanted to remind you ^^ hope the class went well
Mario Krenn (Jun 22 2021 at 22:08):
Kevin Buzzard said:
Did you see the recent AI graph counterexample paper?
Do you mean this one: https://arxiv.org/abs/2104.14516 ?
Kevin Buzzard (Jun 22 2021 at 22:10):
Yes that was it. Thanks for finding it -- was about to plough through Twitter to try and find the URL again!
Mario Krenn (Jun 22 2021 at 22:12):
Kevin Buzzard said:
Yes that was it. Thanks for finding it -- was about to plough through Twitter to try and find the URL again!
I just had a call with an AI expert (who works with Christian S.) about Lean and formal AI provers, he mentioned it, funny that 10mins later you mention it :D
Yaël Dillies (Jun 24 2021 at 06:38):
Mario Krenn said:
Do you mean this one: https://arxiv.org/abs/2104.14516 ?
I just read it. This is insane!
Yaël Dillies (Jun 24 2021 at 06:39):
Maybe one day we will routinely use this kind of approach to check conjectures even before publishing.
Kevin Buzzard (Jun 24 2021 at 07:41):
Not if they're conjectures about infinite-dimensional Banach spaces...
Patrick Massot (Jun 24 2021 at 08:34):
Yaël Dillies said:
Maybe one day we will routinely use this kind of approach to check conjectures even before publishing.
As Kevin hinted at, the proportion of mathematics that could be treated like this is infinitesimal, although it gets a huge popular science press coverage because it's so much easier to talk about.
Kyle Miller (Jun 24 2021 at 16:45):
Rob Kirby once suggested using AI to generate candidate exotic 's, which is not implausible because compact smooth 4-manifolds can be represented by, essentially, a graph -- a Kirby diagram. I've been skeptical, though, because it's unclear how you'd train something like this if there are no examples.
The great thing about extremal graph theory for this seems to be that questions come with a natural choice of objective/reward function. It would be cool if 4-manifolds had similar (computable) functions that measured how close to being an a diagram is and how exotic the manifold is. Maybe, at least, an AI could learn how to simplify Kirby diagrams, since diagrams have a natural measure of complexity.
Adam Topaz (Jun 24 2021 at 16:48):
I also remember seeing some papers doing something with Calabi Yau varieties using ML.
Bryan Gin-ge Chen (Jun 24 2021 at 16:48):
I remember hearing about this paper which seems relevant. @Scott Morrison isn't subscribed to this stream though (and I'm not sure if I should forcibly subscribe him).
Kyle Miller (Jun 24 2021 at 16:52):
@Bryan Gin-ge Chen My understanding is that the current state-of-the-art in Kirby diagram simplification is Bob Gompf himself
Bryan Gin-ge Chen (Jun 24 2021 at 18:21):
That could well be the case. I do remember being shown some papers of Akbulut with really amazing sequences of Kirby diagrams too.
Patrick Massot (Jun 24 2021 at 19:17):
Kyle Miller said:
My understanding is that the current state-of-the-art in Kirby diagram simplification is Bob Gompf himself
Don't you mean Akbulut?
Patrick Massot (Jun 24 2021 at 19:18):
When I read your first message I immediately thought: OMG, he wants a artifical Akbulut...
Kevin Buzzard (Jun 24 2021 at 22:22):
The Calabi Yau ML stuff is guessing data from equations and when the guy spoke about it at Imperial I asked a bunch of questions about the nature of the data (eg he's claiming that his AI can predict the dimension of some cohomology space with 90% accuracy and I asked whether the answer was 0 90% of the time and he said he never checked).
Arthur Paulino (Nov 08 2021 at 02:26):
I need help on this one: https://github.com/leanprover-community/mathlib/pull/10210
I was able to prove the is_perfect_iff
lemma (thanks @Kyle Miller for the help with the right implication). But now I got stuck on the is_perfect_then_even_card_vertices
lemma (and on the one above it).
Arthur Paulino (Nov 08 2021 at 12:44):
I decided to make the PR smaller and just do the refactoring, defining matchings as subgraphs. It's ready for review!
Yaël Dillies (Nov 08 2021 at 15:26):
I would like to know what people think of defining matchings vs having them as a special case of k-factors.
Arthur Paulino (Nov 08 2021 at 15:30):
Technically there's no definition of a matching, but rather a characterization of subgraphs that are matchings (according to the approach suggested by Kyle)
Yaël Dillies (Nov 08 2021 at 15:40):
Sure, take my question as "Should we spell it G.is_matching H
or G.is_factor 1 H
?"
Arthur Paulino (Nov 08 2021 at 15:41):
We can have both of them and a lemma that proves their equivalence, wdyt?
Yaël Dillies (Nov 08 2021 at 15:42):
Or we can just not have is_matching
.<insert Kyle's opinion here>
Arthur Paulino (Nov 08 2021 at 15:46):
I am usually in favor of API richness that helps with usability. Ppl usually do study matchings in UG CS courses and thinking of them as 2-factors is not as straightforward
Arthur Paulino (Nov 08 2021 at 15:47):
The more general we make the API, the more alien it will look to outcomers... it's a thin trade-off :thinking:
I'm not sure where to draw the line, but it's something to keep in mind
Kevin Buzzard (Nov 08 2021 at 15:53):
Each definition comes with a cost (the API), and each definition is one more thing for Lean to unfold, so there needs to be some sort of balance, but it's a bit of an art working out where it is. I was very frustrated over the weekend not being able to say is_singleton
and instead having to keep asking for non-empty subsingletons, but I persevered because I didn't want to make a robust API for something which "we have already" in some sense.
Arthur Paulino (Nov 08 2021 at 16:17):
If the primary goal is to have everything as efficiently formalized as possible, then I am all in favor of dropping matchings. But if we're also targeting people without as much mathematical maturity and even less "Lean maturity", then it becomes a concern (not only for matchings, but for more general use cases of mathlib
)
Kyle Miller (Nov 08 2021 at 16:22):
I'm not sure how many theorems about factors will apply to matchings, so it likely won't be a bad kind of API duplication. Also, it seems very likely to me that, should it come to it, we can define G.is_matching
in terms of G.is_factor
without too much additional work, given how things are looking right now, so my opinion right now is to carry on.
(I'll try to take more of a look at this matching PR later today.)
Kyle Miller (Nov 08 2021 at 16:26):
Regarding alien definitions: one thing to keep in mind is that once you have a definition, you can build out interfaces to it that look more normal. This can be justified if the definition is more powerful somehow, or if it reduces maintenance costs for the relatively small team that develops mathlib. (Defining colorings to be homomorphisms is an example of this -- this isn't an uncommon way for mathematicians to study colorings anyway, and it lets us reuse a bunch of machinery that had already been written (and it helped me notice that there are some missing things about homomorphisms). Also, we could create an API for it that looked like the obvious translation.)
Kyle Miller (Nov 08 2021 at 16:29):
(Even graph homomorphisms are defined in terms of docs#rel_hom, which is essentially the definition of a homomorphism for an undirected graph allowing self-loops.)
Arthur Paulino (Nov 08 2021 at 16:32):
This is true. The PR that characterizes matchings as subgraphs ended up enriching the subgraph API
Patrick Massot (Nov 08 2021 at 16:32):
Arthur Paulino said:
If the primary goal is to have everything as efficiently formalized as possible, then I am all in favor of dropping matchings. But if we're also targeting people without as much mathematical maturity and even less "Lean maturity", then it becomes a concern (not only for matchings, but for more general use cases of
mathlib
)
We have a very clear answer to this. mathlib
tries to be a comprehensive library for professional mathematicians and computer scientists. Then you can build a teaching library out of it if you want. This is done in the tutorial project which uses a custom definition for limits of sequences of real numbers but then secretly hooks into mathlib behind the scene when it needs to use without proof the Bolzano-Weirstrass theorem.
Mauricio Collares (Nov 08 2021 at 17:01):
Yaël Dillies said:
Sure, take my question as "Should we spell it
G.is_matching H
orG.is_factor 1 H
?"
Typically a "factor" of G is defined to be a spanning subgraph of G, and a k-factor of G is defined to be a k-regular factor of G. With this terminology, 1-factors correspond to perfect matchings only.
If I understand correctly, the notion of is_factor
proposed here says that the subgraph H
, when coerced to a graph, is regular (but not necessarily spanning). If so, would adding is_regular
and a coercion be enough?
Mauricio Collares (Nov 08 2021 at 17:18):
For a fixed graph H and a host graph G, a common definition is to say a graph G' is an H-factor of G if G' is a spanning subgraph of G isomorphic to a bunch of disjoint copies of H, as in https://arxiv.org/abs/0803.3406 for example. This generalizes 1-factors (which are K_2-factors). It does not generalize k-factors as is, but it's easy to find a common generalization by replacing H by a family $\mathcal{H}$ of graphs (which you could take as the family of $k$-regular graphs, say). I don't think it's useful to state it like this in mathlib right now, but it's certainly a concept people care about: as an indication, the aforementioned paper won the 2012 Fulkerson Prize.
Arthur Paulino (Nov 08 2021 at 18:25):
@Mauricio Collares How would you organize the API to accommodate such generalization accounting for the fact that "_-factor" is used with _ replaced by an integer or by the name of a graph?
Mauricio Collares (Nov 08 2021 at 18:31):
No idea, I guess another name would be necessary. But I wouldn't worry about the more general concept until someone decides to prove a result that uses it; I just couldn't resist mentioning it. Don't let that message interrupt you :) My main point was the first message (that is, I think "factor" usually implies "spanning" while "matching" doesn't)
Kyle Miller (Nov 08 2021 at 18:55):
@Mauricio Collares That's a good point that factors are spanning subgraphs. Maybe the following seems reasonable then if it's formalized as a relation:
def simple_graph.is_factor_of (k : ℕ) (G G' : simple_graph V) := G ≤ G' ∧ G.is_regular_of_degree k
Then you can write G.is_factor_of 1 G'
for G
being a perfect matching of G'
.
Kyle Miller (Nov 08 2021 at 18:56):
(the order on simple_graph V
is "spanning subgraph of")
Kyle Miller (Nov 08 2021 at 18:59):
(I'm very ignorant about k-factors beyond perfect matchings.)
Arthur Paulino (Nov 08 2021 at 19:03):
Another possibility, maybe a bit awkward but shorter, is being able to state H.factors G
("factors" as a verb)
Yaël Dillies (Nov 08 2021 at 19:51):
I think it's nice to access the factor number, so that you can tell "is a 1-factor"
Yaël Dillies (Nov 08 2021 at 19:51):
What do you think of my current definition at branch#quantum_graph
Arthur Paulino (Nov 08 2021 at 19:53):
Arthur Paulino (Nov 08 2021 at 20:01):
It's nice even though it's tightly related to k-regular graphs. As Mauricio said, if we need something more generic we can come up with it in the future
Arthur Paulino (Nov 11 2021 at 18:39):
@Kyle Miller On the lemma that you proposed on the PR:
lemma is_matching_iff : M.is_matching ↔ ∀ (v ∈ M.support), ∃! (w ∈ M.support), M.adj v w`
I think it needs to be:
lemma is_matching_iff : M.is_matching ↔ ∀ (v ∈ M.verts), v ∈ M.support ∧ ∃! (w ∈ M.support), M.adj v w
Kyle Miller (Nov 11 2021 at 18:44):
There's a lemma you could add, which is that M.support
is a subset of M.verts
Arthur Paulino (Nov 11 2021 at 18:47):
That's not the issue. The problem I'm experiencing is when I have to prove that there exists a w
such that M.adj v w
but I don't have the guarantee that v ∈ M.support
(no guarantee that v
has a neighbor)
Arthur Paulino (Nov 11 2021 at 18:47):
The only guarantee that I have is that v ∈ M.verts
Arthur Paulino (Nov 11 2021 at 18:48):
This is the problematic state:
V: Type u
G: simple_graph V
M: G.subgraph
v: V
h: ∀ (v : V), v ∈ M.support → (∃ (x : V), (x ∈ M.support ∧ M.adj v x) ∧ ∀ (y : V), y ∈ M.support → M.adj v y → y = x)
hv: ∀ (v : V), v ∈ M.verts
⊢ ∃ (x : V), M.adj v x ∧ ∀ (y : V), M.adj v y → y = x
Arthur Paulino (Nov 11 2021 at 18:50):
(Notice that I've strengthen the right side of the Iff
on my modified lemma)
Arthur Paulino (Nov 11 2021 at 18:53):
(Also I'm not proving is_matching_iff
right now. I'm using it to prove is_perfect_iff
)
Kyle Miller (Nov 11 2021 at 18:56):
Oh, right. Maybe this is the true theorem:
lemma is_matching_iff : M.is_matching ↔ ∀ (v ∈ M.verts), ∃! w, M.adj v w`
I think I confused support
with verts
Arthur Paulino (Nov 11 2021 at 18:59):
That should work, yeah
Kyle Miller (Nov 11 2021 at 18:59):
Actually, let's make this (∀ {{v}}, v ∈ M.verts -> ∃! w, M.adj v w
) be the definition of is_matching
, and then make the two properties in the structure
I suggested be lemmas.
Kyle Miller (Nov 11 2021 at 19:00):
I guess eq_of_adj
is unnecessary since it's that's part of exists-unique, but M.verts = M.support
takes a little proof.
Arthur Paulino (Nov 11 2021 at 19:38):
Alright let me dig into that
Arthur Paulino (Nov 11 2021 at 19:42):
What does {{v}}
mean?
Yaël Dillies (Nov 11 2021 at 20:07):
It means "implicit but left explicit in the type signature so long as the next explicit argument isn't fed in"
Eric Rodriguez (Nov 11 2021 at 20:08):
I used to dislike them but they've strongly grown on me
Yaël Dillies (Nov 11 2021 at 20:08):
I do think they're great.
Arthur Paulino (Nov 11 2021 at 22:30):
@Kyle Miller I got the definitions and lemmas you proposed to work:
https://github.com/leanprover-community/mathlib/pull/10210
Arthur Paulino (Nov 11 2021 at 22:32):
I think I noticed something we could benefit from: lemmas that prove that edges sets and incidence sets are finite if the vertices are finite
Arthur Paulino (Nov 11 2021 at 22:33):
This would free us from the necessity of placing multiple [fintype _]
restrictions when we could just derive them from [fintype V]
Kyle Miller (Nov 11 2021 at 22:34):
Those exist, and they just depend on having enough decidable instances. [decidable_rel G.adj]
and potentially [decidable_eq V]
Kyle Miller (Nov 11 2021 at 22:35):
Technically it's better for lemmas to use the most generic typeclass arguments, though, since they're easier to apply, rather ones derived from others. (Even though it's a pain to write lemmas this way.)
Arthur Paulino (Nov 11 2021 at 22:39):
Ah, you mean this:
instance edges_fintype [decidable_eq V] [fintype V] [decidable_rel G.adj] :
fintype G.edge_set := subtype.fintype _
Arthur Paulino (Nov 11 2021 at 22:41):
And we have those for subgraphs too. Nice :D
Kyle Miller (Nov 11 2021 at 22:41):
This is an example of how it's difficult to discover how to get wanted typeclass instances.
It would be nice if there were a way to query the typeclass inference system while telling it the kind of typeclasses you're interested in (maybe decidable
for example), and then it searches like usual, but whenever it's going to fail it looks at the list of wanted typeclasses, and if it's there it pretends it was satisfied. Then for each instance it obtains at the end, it can give you the list of typeclasses you need to satisfy.
Arthur Paulino (Nov 11 2021 at 22:42):
Do you mean something like library_search
or something more interactive in the Lean infoview?
Kyle Miller (Nov 11 2021 at 22:43):
Maybe a version of this can be implemented by temporarily introducing priority-0 instances implemented by sorry
for the ones you're interested in, and then walking through the instance's term at the end to discover which of these instances were used.
Kyle Miller (Nov 11 2021 at 22:44):
I'd imagine an interface like library_search
/suggest
or a command like #find
Kyle Miller (Nov 11 2021 at 22:45):
This sorry
version doesn't give you all instances though, just the first that might match.
(The point of the having a kinds of typeclasses you're interested in is to keep this from having too many results.)
Arthur Paulino (Nov 15 2021 at 00:55):
Ah, I forgot to say it explicitly: this PR is ready for review: https://github.com/leanprover-community/mathlib/pull/10210
Arthur Paulino (Nov 26 2021 at 19:29):
Oops https://github.com/leanprover-community/mathlib/pull/10210#discussion_r757640946
Arthur Paulino (Nov 26 2021 at 19:29):
@Yaël Dillies It was merged after I removed it from the to do list
Yaël Dillies (Nov 26 2021 at 20:15):
Ah, whoops!
Yaël Dillies (Nov 26 2021 at 20:16):
My bad. You can just put it back in your next PR to this file
Arthur Paulino (Nov 26 2021 at 21:09):
I will just do it right away
Arthur Paulino (Dec 17 2021 at 17:04):
I decided to try to tackle some of the todo's regarding graph matchings and I'm not being able to state this lemma:
lemma is_matching_iff {M : subgraph G} :
M.is_matching ↔ ∀ (v : V), M.degree v ≤ 1 :=
begin
sorry
end
Lean says:
failed to synthesize type class instance for
V : Type u,
G : simple_graph V,
M : G.subgraph,
v : V
⊢ fintype ↥(M.neighbor_set v)
But how can I add a []
-like implicit parameter that suffices this need for every v : V
?
Yaël Dillies (Dec 17 2021 at 17:06):
If you look at docs#simple_graph.neighbor_set_fintype, you see that you need [fintype V] [decidable_rel G.adj]
Yaël Dillies (Dec 17 2021 at 17:07):
Theoretically, you only need docs#simple_graph.locally_finite. But I guess we haven't quite worked out how to granularly require finiteness.
Arthur Paulino (Dec 17 2021 at 17:12):
Hmm, locally_finite
would do the trick if we had something equivalent for subgraphs. I'm going to add it
Yaël Dillies (Dec 17 2021 at 17:15):
All this duplication between simple_graph
, simple_graph.subgraph
, and soon weighted graphs (see branch#quantum_graph) is getting annoying... I'll pull out a plan to refactor the graph library in the next few days.
Arthur Paulino (Dec 17 2021 at 17:15):
An option is to require that G
is locally finite and prove that every subgraph of G must be locally finite. Another option is to define locally finiteness for subgraphs specifically and only require that
Yaël Dillies (Dec 17 2021 at 17:16):
Given the current state of things, I'd advise you against adding a specific predicate for subgraphs.
Arthur Paulino (Dec 17 2021 at 17:17):
Alright, to avoid unnecessary work (given your refactoring intent), I'm just going to get it going with [fintype V] [decidable_rel M.adj]
Arthur Paulino (Dec 17 2021 at 17:18):
Because it's less restrictive than requiring locally finiteness for the entire supergraph G
Arthur Paulino (Dec 17 2021 at 17:20):
Also please let me know if/when you start the refactoring. I want to see it closely :eyes:
Yaël Dillies (Dec 17 2021 at 17:20):
I will! I already started prototyping yesterday.
Arthur Paulino (Dec 17 2021 at 17:28):
huh, wait. the lemma is wrong
Arthur Paulino (Dec 17 2021 at 17:29):
This is the lemma:
lemma is_matching_iff {M : subgraph G} [fintype V] [decidable_rel M.adj] :
M.is_matching ↔ ∀ (v : V), M.degree v = 1 := sorry
Arthur Paulino (Dec 17 2021 at 17:30):
(not ≤ 1
... but = 1
)
Kyle Miller (Dec 17 2021 at 18:15):
Yaël Dillies said:
Theoretically, you only need docs#simple_graph.locally_finite. But I guess we haven't quite worked out how to granularly require finiteness.
It's a reducible definition for Π (v : V), fintype (G.neighbor_set v)
, mostly as a convenience for when you actually need every vertex to have finite degree.
Kyle Miller (Dec 17 2021 at 18:18):
@Arthur Paulino All you need is [Π (v : V), fintype (G'.neighbor_set v)]
as a hypothesis.
Kyle Miller (Dec 17 2021 at 18:21):
Arthur Paulino said:
(not
≤ 1
... but= 1
)
Oh, I see, it's still not right with = 1
, though. The subgraph.degree
interface is defined so that vertices outside the subgraph have degree 0. ∀ (v : V), v \in M.verts -> M.degree v = 1
should do it.
Arthur Paulino (Dec 17 2021 at 18:23):
:octopus: Thanks!
Kyle Miller (Dec 17 2021 at 21:06):
@Yaël Dillies For weighted graphs, did you consider with_bot
instead of option
?
@[ext] structure weighted_graph (α : Type*) (W : Type*) :=
(weight : α → α → option W)
(weight_self (a : α) : weight a a = none)
(weight_comm (a b : α) : weight a b = weight b a)
Also, to cut down on all this code duplication, I strongly suggest renaming weighted_graph.to_simple_graph
to weighted_graph.coe
or something equally short and then using G.coe.adj
instead of ever defining G.adj
.
Kyle Miller (Dec 17 2021 at 21:10):
The reason simple_graph.subgraph
has some seemingly duplicated API is that they're giving forms of definitions and lemmas in terms of the underlying graph's V
type (so for example allowing garbage values on vertices outside the subgraph). The intent I had was that for things where avoiding subtype
s isn't useful, you'd do G'.coe.whatever
.
Yaël Dillies (Dec 17 2021 at 21:13):
I have a better idea than all of that, which would also apply to subgraphs. But I want to get a shiny prototype before showing it to you.
Yaël Dillies (Dec 17 2021 at 21:14):
Kyle Miller said:
For weighted graphs, did you consider
with_bot
instead ofoption
?
I actually did, and thought it would be a better choice given that the weight order come from lifting everything from W
to option W
to α → option W
to α → α → option W
.
Kyle Miller (Dec 17 2021 at 21:16):
Yaël Dillies said:
I have a better idea than all of that, which would also apply to subgraphs. But I want to get a shiny prototype before showing it to you.
How mysterious. Can you describe the idea at least?
Yaël Dillies (Dec 17 2021 at 21:18):
Holds in two words, eleven letters: hom refactor.
Arthur Paulino (Dec 17 2021 at 21:23):
My proof came down to proving this:
lemma degree_eq_one_of_unique_adj {G' : subgraph G} {v : V} [fintype (G'.neighbor_set v)] :
G'.degree v = 1 ↔ ∃! (w : V), G'.adj v w
But I'm kinda lost dealing with the definition of degree
. Any hints?
Kyle Miller (Dec 17 2021 at 21:29):
@Yaël Dillies Ok, if I understand you, that's roughly one of the original designs I had for graphs, but there were complexities that weren't clear were worth it so kept things with the simpler design until we had a combinatorial explosion of combinatorial objects.
Were you thinking something roughly like this https://leanprover.zulipchat.com/#narrow/stream/113488-general/topic/Typeclasses.20for.20morphisms/near/258738465 ?
There are some ergonomics problems, and I find it to be a bit sad that you lose G.adj v w
dot notation syntax, but it's worth looking into again.
Yaël Dillies (Dec 17 2021 at 21:31):
Yes, but not quite. I'm really thinking along the lines of #9888
Kyle Miller (Dec 17 2021 at 21:36):
Anyway, it seems like we're roughly on the same page. At some point I was going to try having a has_adj
class along with is_adj_loopless
and is_adj_symm
property classes.
Arthur Paulino (Dec 17 2021 at 21:41):
Arthur Paulino said:
My proof came down to proving this:
lemma degree_eq_one_of_unique_adj {G' : subgraph G} {v : V} [fintype (G'.neighbor_set v)] : G'.degree v = 1 ↔ ∃! (w : V), G'.adj v w
But I'm kinda lost dealing with the definition of
degree
. Any hints?
ping :big_smile:
Kyle Miller (Dec 17 2021 at 21:43):
@Arthur Paulino You need a lemma that the degree is 1 iff the neighbor_set
is a singleton, I think. This lemma doesn't seem to exist for either simple_graph
or subgraph
yet.
Kyle Miller (Dec 17 2021 at 21:45):
I'm not immediately finding a mathlib theorem that fintype s = 1 <-> exists x, s = {x}
Eric Rodriguez (Dec 17 2021 at 21:46):
Do you mean finset there, Kyle? I'm fairly sure it exists
Arthur Paulino (Dec 17 2021 at 21:46):
Ah then it's not as straightforward as I expected (given the lemmas we currently have)
Kyle Miller (Dec 17 2021 at 21:47):
@Eric Rodriguez I think degree
is defined using fintype.card (G'.neighbor_set v)
Kyle Miller (Dec 17 2021 at 21:48):
@Arthur Paulino It's fairly straightforward, and you can patch together a few lemmas. One is to turn this into (G'.neighbor_set v).to_finset.card
using some lemmas from data.set.finite
Kyle Miller (Dec 17 2021 at 21:48):
Another seems to be docs#finset.card_le_one_iff_subset_singleton
Yaël Dillies (Dec 17 2021 at 21:48):
Kyle Miller said:
Anyway, it seems like we're roughly on the same page. At some point I was going to try having a
has_adj
class along withis_adj_loopless
andis_adj_symm
property classes.
Okay great! What I'm doing now is finding a way to clear up a few arrows in the instance graph that don't commute.
Kyle Miller (Dec 17 2021 at 21:49):
Oh, never mind, this is better: docs#finset.card_eq_one
Arthur Paulino (Dec 17 2021 at 21:51):
It's a bit funny because it's done the exact opposite for simple_graph
:
/--
`G.degree v` is the number of vertices adjacent to `v`.
-/
def degree : ℕ := (G.neighbor_finset v).card
@[simp]
lemma card_neighbor_set_eq_degree : fintype.card (G.neighbor_set v) = G.degree v :=
(set.to_finset_card _).symm
Arthur Paulino (Dec 17 2021 at 21:52):
I mean, starting with finset.card
and then turning it into fintype.card
Arthur Paulino (Dec 17 2021 at 21:53):
Is there something strange here or is my intuition fooling me?
Kyle Miller (Dec 17 2021 at 21:54):
@Arthur Paulino I've argued for removing G.neighbor_finset v
before since it's just (G.neighbor_set v).to_finset
, but I've done absolutely nothing about it. Perhaps simple_graph.subgraph.degree
should be defined as (G.neighbor_set v).to_finset.degree
to match up with simple_graph
better.
Arthur Paulino (Dec 17 2021 at 21:56):
I'll leave things as they are for now because there's a hope Yael's refactor might kill these
Kyle Miller (Dec 17 2021 at 21:56):
On the other hand, maybe with these typeclasses Yael is talking about we'll be able to have neighbor_finset
at lower cost. The problem is that, even with the typeclasses, you need lemmas for both neighbor_set
and neighbor_finset
.
Arthur Paulino (Dec 17 2021 at 21:58):
Isn't it possible to design neighbor_set
and neighbor_finset
such that everything that works for neighbor_set
works for neighbor_finset
?
Arthur Paulino (Dec 17 2021 at 21:59):
And then just have more lemmas for neighbor_finset
because it's more restricted
Arthur Paulino (Dec 17 2021 at 22:01):
Anyways, I'll try to get it going with your tips and what we have for now :+1:
Kyle Miller (Dec 17 2021 at 22:09):
This seems to be the main sort of use of neighbor_finset
: https://github.com/leanprover-community/mathlib/blob/master/src/combinatorics/simple_graph/adj_matrix.lean#L187 (it makes summation nicer looking). Ideally, we could sum over set
too. Might be a use for a finset_like
typeclass?
Unfortunately you can't really have things work for both, since one is a set
and one is a finset
.
Arthur Paulino (Dec 17 2021 at 22:45):
Kyle Miller said:
Arthur Paulino You need a lemma that the degree is 1 iff the
neighbor_set
is a singleton, I think. This lemma doesn't seem to exist for eithersimple_graph
orsubgraph
yet.
Hm, I don't think the iff
works because of the "at most" part:
/-- A set `s` is a `subsingleton`, if it has at most one element. -/
protected def subsingleton (s : set α) : Prop :=
∀ ⦃x⦄ (hx : x ∈ s) ⦃y⦄ (hy : y ∈ s), x = y
Kyle Miller (Dec 17 2021 at 22:51):
@Arthur Paulino What's the problem you're running into? Are you still dealing with degree = 1? (Be careful about difference between singleton
and subsingleton
, if that's helpful.)
Arthur Paulino (Dec 17 2021 at 22:52):
I indeed confused those
Arthur Paulino (Dec 17 2021 at 23:41):
Alright, I got it!
lemma card_neighbor_finset_eq_degree {G' : subgraph G} {v : V} [fintype (G'.neighbor_set v)] :
(G'.neighbor_set v).to_finset.card = G'.degree v := by rw [degree, set.to_finset_card]
lemma degree_eq_one_of_unique_adj {G' : subgraph G} {v : V} [fintype (G'.neighbor_set v)] :
G'.degree v = 1 ↔ ∃! (w : V), G'.adj v w :=
begin
rw [← card_neighbor_finset_eq_degree, finset.card_eq_one, finset.singleton_iff_unique_mem],
simp only [set.mem_to_finset, mem_neighbor_set],
end
lemma is_matching_iff {M : subgraph G} [Π (v : V), fintype (M.neighbor_set v)] :
M.is_matching ↔ ∀ (v : V), v ∈ M.verts → M.degree v = 1 :=
begin
split,
{ intros h v hvm,
exact degree_eq_one_of_unique_adj.mpr (h hvm),},
{ intros hv v hvm,
exact degree_eq_one_of_unique_adj.mp (hv v hvm), },
end
Arthur Paulino (Dec 17 2021 at 23:42):
Ideas on how to golf is_matching_iff
further?
Kevin Buzzard (Dec 18 2021 at 00:00):
You could just write it in term mode with pointy brackets
Yaël Dillies (Dec 18 2021 at 00:01):
You should get something like that in the end. Golfed enough to my standards
⟨λ h v hvm, degree_eq_one_of_unique_adj.2 $ h hvm,
λ hv v hvm, degree_eq_one_of_unique_adj.1 $ hv v hvm⟩
Kevin Buzzard (Dec 18 2021 at 00:02):
Does simp [degree_eq_one_of_unique_adj]
work?
Arthur Paulino (Dec 18 2021 at 00:03):
Kevin Buzzard said:
Does
simp [degree_eq_one_of_unique_adj]
work?
nope :/
Kyle Miller (Dec 18 2021 at 00:05):
Definitely does, you just need to refl
it at the end :smile:
simpa
does that for you:
lemma is_matching_iff {M : subgraph G} [Π (v : V), fintype (M.neighbor_set v)] :
M.is_matching ↔ ∀ (v : V), v ∈ M.verts → M.degree v = 1 :=
by simpa [degree_eq_one_of_unique_adj]
Arthur Paulino (Dec 18 2021 at 00:06):
Wow!
Arthur Paulino (Dec 18 2021 at 00:13):
PR: #10864
Arthur Paulino (Dec 19 2021 at 17:06):
How could we prove that a matching is 2-colorable? Are these the only options?
- Redefine coloring for subgraphs
- Coerce the subgraph into a graph and state the lemma for the graph instead?
I think both options are uneasy :thinking:
I'm starting to crave for a refactor that would allow us to say that a graph is a subgraph of another graph with a Prop
:eyes:
Kyle Miller (Dec 19 2021 at 19:12):
@Arthur Paulino The second option is how I imagined it going.
I started implementing it, but I can't keep working on it right now. The idea here is that matchings have a function to their edge set, and then using the axiom of choice (via docs#function.surj_inv) you can choose a vertex for each edge. The bool
-valued coloring is whether or not the vertex was the chosen vertex.
/-- Given a vertex, give the unique edge of the matching it is incident to. -/
noncomputable
def is_matching.to_edge {M : subgraph G} (h : M.is_matching)
(v : M.verts) : M.edge_set :=
⟨⟦(v, (h v.property).some)⟧, (h v.property).some_spec.1⟩
lemma is_matching.to_edge.surjective {M : subgraph G} (h : M.is_matching) :
function.surjective h.to_edge :=
begin
rintro ⟨e, he⟩,
refine sym2.ind (λ x y he, _) e he,
use ⟨x, M.edge_vert he⟩,
simp only [is_matching.to_edge, subtype.mk_eq_mk, subtype.coe_mk, sym2.congr_right],
exact ((h (M.edge_vert he)).some_spec.2 y he).symm,
end
lemma is_matching.eq_to_edge_of_adj {M : subgraph G} (h : M.is_matching)
{v w : V} (hv : v ∈ M.verts) (hw : w ∈ M.verts) (ha : M.adj v w) :
h.to_edge ⟨v, hv⟩ = h.to_edge ⟨w, hw⟩ :=
begin
simp only [is_matching.to_edge, subtype.mk_eq_mk, subtype.coe_mk],
rw [sym2.eq_swap],
congr,
exact ((h (M.edge_vert ha)).some_spec.2 w ha).symm,
exact ((h (M.edge_vert (M.symm ha))).some_spec.2 v (M.symm ha)),
end
lemma loopless (G' : subgraph G) (v : V) (h : G'.adj v v) : false :=
G.loopless v (G'.adj_sub h)
noncomputable
def bicoloring_of_matching {M : subgraph G} (h : M.is_matching) :
M.coe.coloring bool :=
begin
let f := function.surj_inv (is_matching.to_edge.surjective h),
classical,
let c : M.verts → bool := λ v, f (h.to_edge v) = v,
fsplit,
use c,
rintros ⟨v, hv⟩ ⟨w, hw⟩,
simp,
intros ha h',
by_cases hc : f (h.to_edge ⟨v, hv⟩) = ⟨v, hv⟩,
{ rw h.eq_to_edge_of_adj hw hv (M.symm ha) at h',
simp only [hc, true_iff, eq_self_iff_true, subtype.mk_eq_mk] at h',
subst h',
exact M.loopless _ ha, },
{ simp [hc] at h',
rw h.eq_to_edge_of_adj hv hw ha at hc,
sorry, },
end
Arthur Paulino (Dec 19 2021 at 23:29):
@Kyle Miller wanna start the PR and I can try to take over?
Arthur Paulino (Dec 27 2021 at 20:52):
I'm trying to take another TODO
item down but I'm quite sure I'm doing something strange here.
I'm trying to prove that the existence of a perfect matching on a graph implies that the cardinality of the number of vertices is even. For that, I'm telling lean "use the number of edges in the matching", but the proof follows quite strangely from there.
Here's the file with my current attempt. Help is much appreciated :pray:
Kyle Miller (Dec 27 2021 at 21:21):
I suggest using docs#simple_graph.is_perfect_matching_iff and docs#Exist.some to define a function simple_graph.is_perfect_matching.other : V -> V
, then prove it's docs#function.involutive and without fixed points (not sure if a predicate exists for that), then use some lemma (that you might need to write, maybe something in docs#simple_graph.dart gives a hint) to show fintype.card V
is even.
Kyle Miller (Dec 27 2021 at 21:24):
Maybe the idea is that you get a map to_edge : V -> M.edge_set
that's 2-to-1, with simple_graph.is_perfect_matching.other
being the map whose orbits partition V
into the fibers of the to_edge
map.
Kyle Miller (Dec 27 2021 at 21:25):
so you should be able to take things rather directly from the module for simple_graph.dart
Arthur Paulino (Dec 27 2021 at 21:25):
What do you mean by "without fixed points"?
Kyle Miller (Dec 27 2021 at 21:58):
@Arthur Paulino By the way, a more streamlined argument is to apply docs#simple_graph.even_card_odd_degree_vertices to M.spanning_coe
Kyle Miller (Dec 27 2021 at 21:59):
using an is_perfect_matching
analogue of docs#simple_graph.subgraph.is_matching_iff_forall_degree (one without the v ∈ M.verts
hypothesis)
Kyle Miller (Dec 27 2021 at 22:00):
This is the kind of thing I mean by without fixed points: docs#simple_graph.dart.rev_ne
Kyle Miller (Dec 27 2021 at 22:01):
It would still be nice to have simple_graph.is_perfect_matching.other
and to prove some properties about it.
Kyle Miller (Dec 27 2021 at 22:04):
For example, prove that dart.fst
defines an equivalence between M.spanning_coe.dart
and V
, and that dart.fst
is an isomorphism in the sense that dart.fst d.rev = h.other (dart.fst d)
(where h : M.is_perfect_matching
).
Yaël Dillies (Dec 27 2021 at 22:16):
@Arthur Paulino, do you mind if I work on this branch? I have an idea of how the proof could go (and I think I'm gonna need the API surrounding that result very soon)
Arthur Paulino (Dec 27 2021 at 22:18):
Yaël Dillies said:
Arthur Paulino, do you mind if I work on this branch? I have an idea of how the proof could go (and I think I'm gonna need the API surrounding that result very soon)
Not at all, you can go for it.
If you don't take Kyle's suggestion as your route (defining simple_graph.is_perfect_matching.other
and proving those results for it), you can also add it as a TODO
and we can deal with it later :+1:
Yaël Dillies (Dec 27 2021 at 22:20):
I'm first gonna prove the slightly more general result that the support of a matching is even.
Kyle Miller (Dec 27 2021 at 22:21):
Are you going to use even_card_odd_degree_vertices
? That seems potentially the most straightforward (though it would be for M.coe
rather than M.spanning_coe
)
Yaël Dillies (Dec 27 2021 at 22:23):
Given that this result is basically the handshaking lemma, I should probably use the handshaking lemma in the proof :grinning: But I'm not excluding finding a more convenient generalization/variation of even_card_odd_degree_vertices
first.
Bhavik Mehta (Dec 27 2021 at 22:24):
It could be helpful to have a function is_perfect_matching.get_edge : V -> sym2 V
which is guaranteed to have other
and the given vertex, and to be an edge of the graph. (And probably the non-perfect generalisation)
Arthur Paulino (Dec 27 2021 at 22:24):
I thought the proof would go smooth with sum_degrees_eq_twice_card_edges
. I still don't understand why it didn't work :sweat_smile:
Arthur Paulino (Dec 27 2021 at 22:27):
Bhavik Mehta said:
It could be helpful to have a function
is_perfect_matching.get_edge : V -> sym2 V
which is guaranteed to haveother
and the given vertex, and to be an edge of the graph. (And probably the non-perfect generalisation)
Yeah that function seemed to be the start of Kyle's reasoning here.
Arthur Paulino (Dec 27 2021 at 22:32):
BTW, while the simple_graph
vs subgraph
definitions don't get refactored, some instances that carry some assumptions down from the simple graph to its subgraphs would be very useful. E.g.: locally finiteness of neighbors on a vertex, rel
decidability of subgraph.adj
etc
Arthur Paulino (Dec 27 2021 at 22:34):
Actually this one is already contemplated:
instance finite_at {G' : subgraph G} (v : G'.verts) [decidable_rel G'.adj]
[fintype (G.neighbor_set v)] : fintype (G'.neighbor_set v) :=
set.fintype_subset (G.neighbor_set v) (G'.neighbor_set_subset v)
Kyle Miller (Dec 27 2021 at 22:36):
For what it's worth, here's how to use sum_degrees_eq_twice_card_edges
:
lemma is_perfect_matching_iff_forall_degree {M : subgraph G}
[Π (v : V), fintype (M.neighbor_set v)] :
M.is_perfect_matching ↔ ∀ (v : V), M.degree v = 1 :=
by simp [degree_eq_one_iff_unique_adj, is_perfect_matching_iff]
@[simp]
lemma spanning_coe_degree {G' : G.subgraph} (v : V)
[fintype (G'.neighbor_set v)] [fintype (G'.spanning_coe.neighbor_set v)] :
G'.spanning_coe.degree v = G'.degree v :=
begin
rw [← card_neighbor_set_eq_degree, subgraph.degree],
congr,
end
lemma even_card_vertices_of_perfect_matching {M : subgraph G}
[fintype V] [decidable_eq V] [decidable_rel G.adj]
(h : M.is_perfect_matching) : even (fintype.card V) :=
begin
classical,
rw is_perfect_matching_iff_forall_degree at h,
have := M.spanning_coe.sum_degrees_eq_twice_card_edges,
simp [h] at this,
exact ⟨_, this⟩,
end
Kyle Miller (Dec 27 2021 at 22:36):
(I'd like the first two lemmas in the library somewhere anyway.)
Arthur Paulino (Dec 27 2021 at 22:37):
Oh it's done :rofl:
Arthur Paulino (Dec 27 2021 at 22:38):
@Yaël Dillies I can just push those proofs that Kyle already did
Kyle Miller (Dec 27 2021 at 22:38):
That doesn't have the more general one, though.
Bhavik Mehta (Dec 27 2021 at 22:39):
I wonder if this can be used to prove the more general one - given a matching it is perfect on itself, so it has an even number of vertices
Yaël Dillies (Dec 27 2021 at 22:40):
Dang, just went to have a glass a water and here comes the proof :rofl:
Arthur Paulino (Dec 27 2021 at 22:41):
It's true tho. I think having the more general one and this one following it would be nicer
Kyle Miller (Dec 27 2021 at 22:41):
I wonder if it's worth generalizing this lemma:
lemma is_matching_iff_forall_degree {M : subgraph G} [Π (v : V), fintype (M.neighbor_set v)] :
M.is_matching ↔ ∀ (v : V), v ∈ M.verts → M.degree v = 1
We don't need a fintype
instance for every vertex, just the ones in the support.
Yaël Dillies (Dec 27 2021 at 22:42):
We currently handle finiteness quite badly, so I would be eager for a full rethink on how to do it.
Arthur Paulino (Dec 27 2021 at 22:44):
@Yaël Dillies I'm going to push the proofs Kyle wrote and then you can improve it, okay?
Kyle Miller (Dec 27 2021 at 22:45):
It's funny, being able to have varying finiteness at different vertices is something I think we managed to actually pull off, vs the alternative (which was only finite graphs).
Kyle Miller (Dec 27 2021 at 22:45):
Maybe it's obvious in retrospect, since we have this API
Yaël Dillies (Dec 27 2021 at 22:47):
With all the kerfuffle of switching between finsets and sets? I saw Alena in pain writing the SRG branch back in March, and my medication was "Take more finsets".
Kyle Miller (Dec 27 2021 at 22:47):
(I'm happy to hear constructive criticism about what could be improved, but general comments about API being "bad" I don't find to be particularly helpful.)
Yaël Dillies (Dec 27 2021 at 22:49):
I'm trying to come up with something :smile:
Yaël Dillies (Dec 27 2021 at 22:50):
And sorry, I should stop insulting your APIs.
Arthur Paulino (Dec 27 2021 at 22:50):
okay @Yaël Dillies you can go for it. in the meantime I'm going to define the V -> edge
function that Bhavik and Kyle were talking about
Kevin Buzzard (Dec 27 2021 at 22:51):
Never use finsets at all and do everything with set.finite
:-)
Arthur Paulino (Dec 27 2021 at 22:53):
Since the topic of graph API came up, I'm going to take the chance and make a question that I've been longing to ask for a while now :D
Yaël Dillies (Dec 27 2021 at 22:53):
Kevin, the finsect outcast :grinning:
Bhavik Mehta (Dec 27 2021 at 23:07):
Kyle Miller said:
It's funny, being able to have varying finiteness at different vertices is something I think we managed to actually pull off, vs the alternative (which was only finite graphs).
I agree, but here's a particular thing which I think is missing?
instance {V : Type*} (G : simple_graph V) (G' : subgraph G) [fintype V] (v : V) :
fintype (G'.neighbor_set v) := by apply_instance
Yaël Dillies (Dec 27 2021 at 23:08):
lol I was writing that instance just now
Bhavik Mehta (Dec 27 2021 at 23:09):
Oh actually it's already there, never mind!
Yaël Dillies (Dec 27 2021 at 23:09):
The one I'm interested in takes fintype M.support
instead.
Kyle Miller (Dec 27 2021 at 23:09):
There are definitely some decidability instances missing for subgraph
Kyle Miller (Dec 27 2021 at 23:09):
instance [decidable_pred (∈ M.support)] [fintype V] : fintype M.support := set_fintype _
Kyle Miller (Dec 27 2021 at 23:10):
Yaël Dillies said:
The one I'm interested in takes
fintype M.support
instead.
I was too :smile:
Kyle Miller (Dec 27 2021 at 23:10):
I'm not sure the decidability instance needed, but I'd started on this one:
instance support_decidable_pred [decidable_rel G.adj] : decidable_pred (∈ M.support) :=
begin
end
(I doubt I have the right hypotheses.)
Yaël Dillies (Dec 27 2021 at 23:11):
You also need fintype V
I'm afraid, because ∈ M.support
is an existential.
Arthur Paulino (Dec 27 2021 at 23:13):
@Yaël Dillies do you want to push to that branch or open a PR into it?
Yaël Dillies (Dec 27 2021 at 23:13):
I'll just push I think
Arthur Paulino (Dec 27 2021 at 23:14):
Alright (just wanted to check so we don't step on each other's toes)
Kyle Miller (Dec 27 2021 at 23:14):
(I'm not working on this anymore -- just wanted to show how to use the lemma. No more toe stepping from me :footprints:)
Arthur Paulino (Dec 27 2021 at 23:16):
Kyle do you mind if I push the is_matching.to_edge
function and the following two lemmas that you proved about it here?
Kyle Miller (Dec 27 2021 at 23:18):
Nope!
Yaël Dillies (Dec 27 2021 at 23:18):
Okay, got the instance.
Arthur Paulino (Dec 27 2021 at 23:25):
I'm also adding the loopless
lemma into the subgraph API, but I changed it slightly:
protected lemma loopless {v : V} (G' : subgraph G) : ¬G'.adj v v :=
by {by_contra h, exact G.loopless v (G'.adj_sub h) }
Kyle Miller (Dec 27 2021 at 23:26):
One thing we need to fix for the simple graph API is that many lemma statements use derived decidability and fintype instances, rather than having everything be taken as instance arguments. This is a Known Bug that causes some random problems.
(A way I've wanted to solve this is to change how computability works in mathlib in general, but it would be nice if someone fixed these things sooner than whenever that might happen :wink:)
Yaël Dillies (Dec 27 2021 at 23:27):
Arthur Paulino said:
I'm also adding the
loopless
lemma into the subgraph API, but I changed it slightly:protected lemma loopless {v : V} (G' : subgraph G) : ¬G'.adj v v := by {by_contra h, exact G.loopless v (G'.adj_sub h) }
adj_irrefl
!
Yaël Dillies (Dec 27 2021 at 23:28):
Kyle Miller said:
(A way I've wanted to solve this is to change how computability works in mathlib in general, but it would be nice if someone fixed these things sooner than whenever that might happen :wink:)
I'm gonna ask the protocolary question: Will it change in Lean 4?
Arthur Paulino (Dec 27 2021 at 23:29):
Yaël Dillies said:
Arthur Paulino said:
I'm also adding the
loopless
lemma into the subgraph API, but I changed it slightly:protected lemma loopless {v : V} (G' : subgraph G) : ¬G'.adj v v := by {by_contra h, exact G.loopless v (G'.adj_sub h) }
adj_irrefl
!
lemma adj_irrefl {v : V} (G' : subgraph G) : ¬G'.adj v v :=
by { by_contra h, exact G.loopless v (G'.adj_sub h) }
Yaël Dillies (Dec 27 2021 at 23:29):
Because yeah clearly decidability management is a pain and shouldn't have to be dealt with. After all, why not a system which puts in the correct decidability assumptions on each lemma, unless it yucks in which case you do it by hand?
Kyle Miller (Dec 27 2021 at 23:33):
Regarding loopless
and adj_irrefl
-- should we change simple_graph.loopless
to simple_graph.adj_irrefl
and add simple_graph.loopless
as an alias?
Yaël Dillies (Dec 27 2021 at 23:34):
Yes please, that would be much more in line with the rest of mathlib :smiling_face:
Kyle Miller (Dec 27 2021 at 23:34):
At some level I feel like this is caving in to viewing simple graphs as just being relations.
Yaël Dillies (Dec 27 2021 at 23:34):
Exactly
Yaël Dillies (Dec 27 2021 at 23:35):
And #11000 gives up on those custom names altogether.
Arthur Paulino (Dec 27 2021 at 23:35):
Yeah I've been thinking about this idea of being able to have graphs of whatever (not limiting the type of a vertex)
Kyle Miller (Dec 27 2021 at 23:36):
Anyway, so long as it's still simple_graph.loopless
, I think it ought to be called simple_graph.subgraph.loopless
. I'm very open to adj_irrefl
being an alias in both cases for now.
Kyle Miller (Dec 27 2021 at 23:37):
@Arthur Paulino If I understand you, the intent there is to use sigma types when you want graphs with any vertex type
Yaël Dillies (Dec 27 2021 at 23:37):
The next step is of course to drop the subgraph.adj
spelling and only use the dot-less graph.adj
Arthur Paulino (Dec 27 2021 at 23:38):
Kyle Miller said:
Anyway, so long as it's still
simple_graph.loopless
, I think it ought to be calledsimple_graph.subgraph.loopless
. I'm very open toadj_irrefl
being an alias in both cases for now.
Can I just do a full refactor and stick to adj_irrefl
all the way through?
Yaël Dillies (Dec 27 2021 at 23:38):
with dot notatable lemmas like graph.adj.symm
Kyle Miller (Dec 27 2021 at 23:38):
@Yaël Dillies That's not an "of course" -- I really think we don't have to compromise and lose dot notation.
Yaël Dillies (Dec 27 2021 at 23:38):
Reread my message :grinning:
Yaël Dillies (Dec 27 2021 at 23:39):
It's a matter of shifting what we're dot notating on.
Kyle Miller (Dec 27 2021 at 23:39):
I know, and I mean I think we can still have dot notation on the object itself.
Yaël Dillies (Dec 27 2021 at 23:40):
But yeah, the dot notation on concrete structures has to be lost for the general lemmas. With the current state of things, this is what refactoring to a typeclass hierarchy entails.
Kyle Miller (Dec 27 2021 at 23:40):
(It might take some small modifications to Lean, but I still need to make sure it can't be done without that.)
Yaël Dillies (Dec 27 2021 at 23:41):
If you're willing to dig into Lean itself, then yeah I'm sure you can fix that. But I don't think this is that important. And in particular we shouldn't delay the refactor because of loss of dot notation IMO
Arthur Paulino (Dec 27 2021 at 23:42):
@Yaël Dillies I saw that you just pushed a commit. I'm gonna push a commit on top of it okay?
Arthur Paulino (Dec 27 2021 at 23:43):
(so you can pull before continuing)
Yaël Dillies (Dec 27 2021 at 23:43):
Go ahead. I'm off for the day
Bhavik Mehta (Dec 27 2021 at 23:43):
Yaël Dillies said:
Yes please, that would be much more in line with the rest of mathlib :smiling_face:
This isn't actually true, there is exactly one relation which uses _irrefl
, namely lt
, and exactly one instance of less
to describe a property. The mathlib pattern is actually to use irrefl
or irrefl_of
together with the irreflexivity typeclass.
Arthur Paulino (Dec 28 2021 at 00:27):
Btw, today's brainstorming session was fun. Thanks! :D
Arthur Paulino (Dec 28 2021 at 00:31):
This is the current state of the PR: #11083 (after hopefully everything we've discussed here)
Arthur Paulino (Dec 28 2021 at 04:25):
@Kyle Miller almost at the same time you posted on the PR, I finished Yael's proof
Arthur Paulino (Dec 28 2021 at 04:29):
It doesn't require any of the assumptions you mentioned on your comment.
Neither [∀ v, fintype (M.neighbor_set v)]
nor [∀ v, fintype (M.coe.neighbor_set v)]
Arthur Paulino (Dec 28 2021 at 04:50):
I have committed your suggestions as well as your alternative proof. Feel free to commit directly to the branch if you want to adjust details manually before we mark the PR as ready for review :+1:
Arthur Paulino (Dec 28 2021 at 04:51):
(or just comment here or on the PR and I can commit the adjustments)
Kyle Miller (Dec 28 2021 at 05:00):
@Arthur Paulino Oh right, not sure what I was thinking, those are definitely not necessary.
noncomputable instance (G' : subgraph G) [fintype G'.verts] (a : V) : fintype (G'.neighbor_set a) :=
fintype.of_injective (λ (v : G'.neighbor_set a), (⟨v, G'.edge_vert (G'.adj_symm v.2)⟩ : G'.verts))
(λ v w h, by { ext, convert congr_arg subtype.val h })
lemma is_matching.even_card {M : subgraph G} [hM : fintype M.verts] [decidable_eq V]
[decidable_rel G.adj] (h : M.is_matching) :
even (M.verts.to_finset.card) :=
begin
classical,
rw is_matching_iff_forall_degree at h,
have := M.coe.sum_degrees_eq_twice_card_edges, simp [h] at this,
use M.coe.edge_finset.card,
rw [← this, set.to_finset_card],
refl,
end
Arthur Paulino (Dec 28 2021 at 05:14):
So we leave the two proofs?
Arthur Paulino (Dec 28 2021 at 05:15):
hmm, actually we have this lemma:
lemma is_matching.support_eq_verts {M : subgraph G} (h : M.is_matching) : M.support = M.verts
Kyle Miller (Dec 28 2021 at 05:16):
Exactly -- even M.verts.to_finset.card
seems to me to be more basic than even M.support.to_finset.card
.
Kyle Miller (Dec 28 2021 at 05:17):
The proofs are basically the same, but when using M.verts
you don't need the unfreezingI
business.
Arthur Paulino (Dec 28 2021 at 05:18):
And now is_perfect_matching.even_card
should be even simpler right?
Arthur Paulino (Dec 28 2021 at 05:41):
The PR is looking good for now. We can just golf it from here
Arthur Paulino (Dec 28 2021 at 05:42):
I've marked it as ready for review
Yaël Dillies (Dec 28 2021 at 08:11):
Kyle Miller said:
The proofs are basically the same, but when using
M.verts
you don't need theunfreezingI
business.
I used M.support
precisely because some lemmas were already using it instead of verts
and I didn't want to introduce disparity.
Kyle Miller (Dec 28 2021 at 14:27):
@Yaël Dillies Are you proposing to use M.support
instead of M.verts
? If you're instead explaining what led you to choose it, for what it's worth I forgot what "the point" of docs#simple_graph.subgraph.is_matching.support_eq_verts was until I looked at all the code hours later (I, too, had started writing an M.support
version to see what might be challenging, but you finished that one first).
Arthur Paulino (Dec 28 2021 at 14:49):
IIRC, Yael's motivation was because he would need this result in a near future, but I think he was referring to is_perfect_matching.even_card
Arthur Paulino (Dec 28 2021 at 14:50):
I am now trying to prove it this way:
lemma is_perfect_matching.even_card' {M : subgraph G} [fintype V] (h : M.is_perfect_matching) :
even (fintype.card V) :=
begin
have := is_matching.even_card h.1,
rw card_verts_eq_of_spanning h.2 at this,
exact this,
end
But now I need to prove these:
instance [fintype V] {G' : subgraph G} : fintype G'.verts := sorry
lemma card_verts_eq_of_spanning [fintype V] {G' : subgraph G}
(h : G'.is_spanning) : G'.verts.to_finset.card = fintype.card V := sorry
Arthur Paulino (Dec 28 2021 at 14:59):
lemma card_verts_eq_of_spanning [fintype V] {G' : subgraph G}
(h : G'.is_spanning) : G'.verts.to_finset.card = fintype.card V :=
by { congr, ext1, simp at *, solve_by_elim }
Kyle Miller (Dec 28 2021 at 15:15):
For writing the lemma, it's better to include fintype
instances for everything in sight:
lemma card_verts_eq_of_spanning [fintype V] {G' : subgraph G} [fintype G'.verts]
(h : G'.is_spanning) : G'.verts.to_finset.card = fintype.card V :=
by { rw is_spanning_iff at h, congr, convert set.to_finset_univ }
(Removed the non-terminal simp and used an existing lemma. There's a bit of magic here with convert
; I think it runs assumption
automatically?)
Kyle Miller (Dec 28 2021 at 15:16):
There's already an instance fintype G'.verts
from fintype V
if you have the right decidability instances:
instance [fintype V] {G' : subgraph G} [decidable_pred (∈ G'.verts)]: fintype G'.verts :=
by apply_instance
Kyle Miller (Dec 28 2021 at 15:17):
So you can get even_card'
working by starting it with the classical
tactic.
Arthur Paulino (Dec 28 2021 at 15:18):
Kyle Miller said:
For writing the lemma, it's better to include
fintype
instances for everything in sight
Doesn't that make the lemma more restrictive?
Kyle Miller (Dec 28 2021 at 15:18):
Then a little bit of golfing:
lemma is_perfect_matching.even_card' {M : subgraph G} [fintype V] (h : M.is_perfect_matching) :
even (fintype.card V) :=
by { classical, simpa [card_verts_eq_of_spanning h.2] using is_matching.even_card h.1 }
Kyle Miller (Dec 28 2021 at 15:19):
Arthur Paulino said:
Kyle Miller said:
For writing the lemma, it's better to include
fintype
instances for everything in sightDoesn't that make the lemma more restrictive?
It's the opposite: it makes sure you can apply it no matter which instances show up in the expression
Kyle Miller (Dec 28 2021 at 15:21):
"Be permissive in what you accept": all the instances in the goal are universally quantified here
set_option pp.implicit true
#check @card_verts_eq_of_spanning
/-
∀ {V : Type u_1} {G : simple_graph V} [_inst_1 : fintype V] {G' : G.subgraph} [_inst_2 : fintype ↥(G'.verts)],
G'.is_spanning → (@set.to_finset V G'.verts _inst_2).card = @fintype.card V _inst_1
-/
Arthur Paulino (Dec 28 2021 at 15:22):
Now I'm confused :upside_down:
Arthur Paulino (Dec 28 2021 at 15:22):
I thought that adding more []
parameters to my lemmas would restrict their usage
Kyle Miller (Dec 28 2021 at 15:22):
Compare it to this:
lemma card_verts_eq_of_spanning [fintype V] {G' : subgraph G} [decidable_pred (∈ G'.verts)]
(h : G'.is_spanning) : G'.verts.to_finset.card = fintype.card V := sorry
set_option pp.implicit true
#check @card_verts_eq_of_spanning
/-
∀ {V : Type u_1} {G : simple_graph V} [_inst_1 : fintype V] {G' : G.subgraph} [_inst_2 : @decidable_pred V (λ (_x : V), _x ∈ G'.verts)],
G'.is_spanning → (@set.to_finset V G'.verts (@verts.fintype V G _inst_1 G' (λ (a : V), _inst_2 a))).card = @fintype.card V _inst_1
-/
Kyle Miller (Dec 28 2021 at 15:23):
This only applies to the case when the set.to_finset
expression's fintype
instance is created using set.fintype
.
Kyle Miller (Dec 28 2021 at 15:23):
When we get this wrong, this is why we need convert
sometimes.
Arthur Paulino (Dec 28 2021 at 15:30):
I will need to chew on this a little longer. Either way, this is the PR now: #11083
Kyle Miller (Dec 28 2021 at 15:30):
@Arthur Paulino The situation is analogous to the difference between these lemmas:
lemma foo {α : Sort*} (x : unit) (y z : α) : x = () := subsingleton.elim _ _
lemma foo' {α : Sort*} (y z : α) : () = () := rfl
The first lemma is more general than the second.
Kyle Miller (Dec 28 2021 at 15:31):
fintype
is also a subsingleton -- even though all fintype
instances for the same type are equal, they're not definitionally equal, so it's better to let them be additional arguments.
Arthur Paulino (Dec 28 2021 at 15:34):
That's probably why I hit this wall
Kyle Miller (Dec 28 2021 at 15:36):
If I remember correctly, that's a different issue (that I also ran into). I think one was finset.univ : finset V
and the other was finset.univ : finset (set.univ : set V)
.
Kyle Miller (Dec 28 2021 at 15:37):
(In the second case, set.univ
is being coerced to a type.)
Kyle Miller (Dec 28 2021 at 15:38):
It would probably be useful having a lemma in mathlib that these have the same cardinality if one doesn't already exist.
Kyle Miller (Dec 28 2021 at 15:40):
example {α : Type*} [fintype α] :
(finset.univ : finset (set.univ : set α)).card = (finset.univ : finset α).card := sorry
Arthur Paulino (Dec 28 2021 at 15:41):
Would it make card_verts_eq_of_spanning
trivial?
Arthur Paulino (Dec 28 2021 at 15:41):
(just to make sure I'm following)
Kyle Miller (Dec 28 2021 at 15:43):
Ok, good, got the types right and it's true:
example {α : Type*} [fintype α] :
(finset.univ : finset (set.univ : set α)).card = (finset.univ : finset α).card :=
begin
classical,
rw ← finset.card_image_of_injective finset.univ subtype.coe_injective,
congr,
ext,
simp,
apply_instance,
end
Kyle Miller (Dec 28 2021 at 15:46):
Arthur Paulino said:
Would it make
card_verts_eq_of_spanning
trivial?
I don't know. It seems your proof of that lemma avoided this. I'm not completely sure if it's what you ran into yesterday, but it's definitely something I ran into.
Arthur Paulino (Dec 28 2021 at 15:51):
I'm going to post #11083 on #PR reviews okay?
Yaël Dillies (Dec 28 2021 at 18:08):
My reasoning is just that M.support
was already used while M.verts
wasn't and M.verts
is in general stronger than M.support
.
Arthur Paulino (Dec 30 2021 at 21:45):
Kyle Miller said:
Ok, good, got the types right and it's true:
example {α : Type*} [fintype α] : (finset.univ : finset (set.univ : set α)).card = (finset.univ : finset α).card := begin classical, rw ← finset.card_image_of_injective finset.univ subtype.coe_injective, congr, ext, simp, apply_instance, end
Do you think this should go somewhere?
Last updated: Dec 20 2023 at 11:08 UTC