Zulip Chat Archive

Stream: new members

Topic: Pattern match on `finset`


Tage Johansson (Nov 02 2022 at 18:50):

Hello,

I know the topic is a bit vague, but I simply want to decide a proposition about a finite set. I'd like to pattern match on the set just as I'm used to pattern match on lists. I saw there is finset.induction_on, but I don't get it to work. Perhaps it expects a predicate and decidable is not a prop but a type. Anyway, here's (approximately) what I want to achieve:

def all_positive (p : finset )
                 : decidable ( x  p, 0 < x) :=
  by sorry

What would be the cleanest way to implement this?

Thanks,
Tage

Kyle Miller (Nov 02 2022 at 18:53):

There are already instances in mathlib for that, so you can do

def all_positive (p : finset )
                 : decidable ( x  p, 0 < x) :=
  infer_instance

Kyle Miller (Nov 02 2022 at 18:54):

But, just to check, are you sure you're wanting decidable here?

Kyle Miller (Nov 02 2022 at 18:56):

If you want to track down how mathlib does it, if you do

def all_positive (p : finset )
                 : decidable ( x  p, 0 < x) :=
  by apply_instance
#print all_positive

then you can see it uses docs#finset.decidable_dforall_finset

Tage Johansson (Nov 02 2022 at 18:57):

Thanks, but I just gave a simplified example. It wasn't ment to be solved by "cheating". Here what I actually want to achieve:

def weightlifting_subset (p : finset )
                         (w : )
                         : decidable ( (s : finset ), s  p  w =  x in s, x) :=
  by sorry

Tage Johansson (Nov 02 2022 at 18:59):

I want to split the proof/implementation into a case where p is empty and one case where p is a set with an inserted element.

Kyle Miller (Nov 02 2022 at 18:59):

Poking around a bit, it looks like the key is that since a finset is a kind of multiset, then you can use quotient.rec_on_subsingleton on that, which gives a list that you can compute with however you like. But you should look through how that's done.

Kyle Miller (Nov 02 2022 at 19:00):

To #xy this a bit, where is this decidable being used? I'm asking because you have a def rather than a class, which makes me wonder what you're up to.

Kyle Miller (Nov 02 2022 at 19:03):

Anyway, I'd still do this by "cheating" by using pre-existing instances wherever possible. (I switched to s.sum id, which is equivalent, just because I was in the middle of a random other Lean file)

def weightlifting_subset (p : finset )
                         (w : )
                         : decidable ( (s : finset ), s  p  w = s.sum id) :=
begin
  apply decidable_of_iff ( (s : p.powerset), w = s.1.sum id),
  simp,
end

Kyle Miller (Nov 02 2022 at 19:05):

The trick is that I knew there was a decidable instance for existentials over finite types.

Tage Johansson (Nov 02 2022 at 19:13):

Your solution seems to work, although I probably need some time to understand why. It feels all too magick!

But anyway. The problem is that I should create an algorithm that given a set of weights p and a total weight w, checks whether there exists a subset of p which sum is equal to w. Then I wanted to prove this algorithm being correct, and I thought I could do the computation and proof together by using decidable. But perhaps this isn't entirely correct?

Kyle Miller (Nov 02 2022 at 19:19):

The high-level reason this works is that there are already algorithms for this problem somewhere deep in mathlib, and we just needed to rewrite the Prop to help it see this. Whether that algorithm is any good is a different story! (I imagine it's one someone thought at least a little about runtime characteristics.)

Kyle Miller (Nov 02 2022 at 19:21):

I suppose it makes sense to use decidable this way. It can be easier to define an algorithm then prove it's correct, though if you can interleave the algorithm and proof that's fine too.

decidable is generally used as a typeclass, since it's used to synthesize decision procedures for propositions automatically. That way you can use a Prop as if it were a Bool inside programs.

Tage Johansson (Nov 02 2022 at 19:33):

Is there any way to get to know the instance used by decidable_of_iff?

Kyle Miller (Nov 02 2022 at 19:35):

It's not the best, but I might try doing #print weightlifting_subset and looking for something relevant

Kyle Miller (Nov 02 2022 at 19:37):

Another way is

set_option pp.implicit true
def weightlifting_subset (p : finset )
                         (w : )
                         : decidable ( (s : finset ), s  p  w = s.sum id) :=
begin
  show_term { apply decidable_of_iff ( (s : p.powerset), w = s.1.sum id), },
  simp,
end

and in the output I see fintype.decidable_exists_fintype ↥(p.powerset).


Last updated: Dec 20 2023 at 11:08 UTC