Zulip Chat Archive

Stream: new members

Topic: fun with pfun and dite


Jalex Stark (May 07 2020 at 02:18):

This code block is kinda long but I think is close to minimal. I'm trying to define a notion of the limit of an increasing sequence of partial functions. I define the limiting function in tactic mode using by_cases. Later I unfold it and try to tell Lean which branch it goes down with rw dif_pos, but I get an error

rewrite tactic failed, did not find instance of the pattern in the target expression
  dite ?m_1 ?m_4 ?m_5

while the goal state looks like

a 
    dom
      (id
         (λ (a : α),
            dite ( (n : ), a  dom (F n))
              (λ (h :  (n : ), a  dom (F n)), let k :  := classical.some h in F k a)
              (λ (h : ¬∃ (n : ), a  dom (F n)), none)))

which to my human eyes clearly contains dite _ _ _ in it.

Here's the code:

import tactic
import data.set.basic

universes u
open_locale classical
open pfun

def pfun.extends {α β : Type} (F f : α  →. β) : Prop := dom f  dom F   a ha ha', (f a).get ha = (F a).get ha'


def limit_of_chain {α β : Type}  (F :   (α →. β)) (F_chain :  n k, k  n  pfun.extends (F k) (F n) ) : α →. β := begin
intro a,
by_cases  n, a  dom (F n),
 swap, {exact none},
have hk := classical.some_spec h,
let k:= classical.some h,
exact (F k) a,
end

def limit_of_chain_extends {α β : Type}  (F :   (α →. β)) (F_chain :  n k, k  n  pfun.extends (F k) (F n)) :  n, pfun.extends (limit_of_chain F F_chain) (F n) := begin
intro n, rw pfun.extends,
split,
    rw set.subset_def, intros a ha,
    unfold limit_of_chain,
rw dif_pos,
end

Mario Carneiro (May 07 2020 at 02:19):

it's under a binder

Mario Carneiro (May 07 2020 at 02:19):

simp can get at this, rw can't

Jalex Stark (May 07 2020 at 02:20):

oh interesting

Jalex Stark (May 07 2020 at 02:20):

so simp only [dif_pos] will make progress?
EDIT: I think it doesn't

Reid Barton (May 07 2020 at 02:20):

Perhaps we could improve the error message

Kenny Lau (May 07 2020 at 02:20):

should we rewrite rw so that it can access binders?

Reid Barton (May 07 2020 at 02:20):

I mean, there is a lot that can go wrong with rw, but in this case the error message is actually just a lie

Mario Carneiro (May 07 2020 at 02:21):

there is simp_rw I think, which uses simp with settings to make it act more like rw

Kenny Lau (May 07 2020 at 02:22):

but can it succeed without knowing all the inputs of a theorem?

Kenny Lau (May 07 2020 at 02:22):

because rw can (and generates metavariables) while simp fails

Jalex Stark (May 07 2020 at 02:22):

in my context, simp only [id.def, roption.coe_none], and simp_rw dif_pos, have the same effect

Mario Carneiro (May 07 2020 at 02:22):

simp only [dif_pos] will not make progress because it doesn't have the proof of the condition available

Mario Carneiro (May 07 2020 at 02:23):

unlike rw, which is happy to apply conditional rewrites and gives you the conditions as subgoals

Mario Carneiro (May 07 2020 at 02:24):

Does simp only [dif_pos _] work?

Jalex Stark (May 07 2020 at 02:24):

have calc1 : ∃ (n : ℕ), a ∈ dom (F n), use n, exact ha, simp only [dif_pos, calc1],
this doesn't work

Jalex Stark (May 07 2020 at 02:25):

neither does simp only [dif_pos _]

Jalex Stark (May 07 2020 at 02:25):

(would these problems not arise if I was avoiding the use of tactics in constructing data?)

Reid Barton (May 07 2020 at 02:26):

The binder binds a different a. Actually I can't tell what is happening.

Jalex Stark (May 07 2020 at 02:27):

Reid Barton said:

The binder binds a different a. Actually I can't tell what is happening.

does simp only [id.def, roption.coe_none], make it a little clearer?

Reid Barton (May 07 2020 at 02:27):

Oh right, a pfun actually is a function. Maybe it would be more profitable to simplify from the outside first.

Reid Barton (May 07 2020 at 02:30):

Like presumably a \in dom f is some assertion about f a, and then the lambda will reduce

Reid Barton (May 07 2020 at 02:31):

and then you wouldn't be in this situation where you can't provide the proof of which case you are in because you have no way to talk about the variable a

Jalex Stark (May 07 2020 at 02:33):

I think maybe this did some "simplifying from the outside" although I'm not really sure what happened (the work_on_goal line came from tidy?)

import tactic
import data.set.basic

universes u
open_locale classical
open pfun

def pfun.extends {α β : Type} (F f : α  →. β) : Prop := dom f  dom F   a ha ha', (f a).get ha = (F a).get ha'


def limit_of_chain {α β : Type}  (F :   (α →. β)) (F_chain :  n k, k  n  pfun.extends (F k) (F n) ) : α →. β := begin
intro a,
by_cases  n, a  dom (F n),
 swap, {exact none},
have hk := classical.some_spec h,
let k:= classical.some h,
exact (F k) a,
end

def limit_of_chain_extends {α β : Type}  (F :   (α →. β)) (F_chain :  n k, k  n  pfun.extends (F k) (F n)) :  n, pfun.extends (limit_of_chain F F_chain) (F n) := begin
intro n, rw pfun.extends,
split,
    rw set.subset_def, intros a ha,
    unfold limit_of_chain,
-- have calc1 : ∃ (n : ℕ), a ∈ dom (F n), use n, exact ha,
simp only [id.def, roption.coe_none],

refine (mem_dom
   (λ (a : α),
      dite ( (n : ), a  dom (F n)) (λ (h :  (n : ), a  dom (F n)), F (classical.some h) a)
        (λ (h : ¬∃ (n : ), a  dom (F n)), roption.none))
   a).mpr
  _,
existsi ((F n) a).get ha,
work_on_goal 0 { dsimp at *, fsplit },
rw dif_pos,
end

Reid Barton (May 07 2020 at 02:33):

By the way, part of the point of pfun is you don't have to use by_cases at all

Jalex Stark (May 07 2020 at 02:34):

hmm how would you define limit_of_chain?

Jalex Stark (May 07 2020 at 02:37):

(for my application to categoriticity of DLOs, I only need the case where the limit of the partial functions is total, so I could cut out my use of by_cases by adding the positive case as an assumption)

Jalex Stark (May 07 2020 at 02:37):

(as a zulip meta question, does this conversation belong in "new members" or "math"?)

Reid Barton (May 07 2020 at 02:38):

for example

def limit_of_chain {α β : Type} (F :   (α →. β))
  (F_chain :  n k, k  n  pfun.extends (F k) (F n) ) :
  α →. β :=
begin
  refine λ a, ⟨∃ n, a  dom (F n), λ h, _⟩,
  have hk := classical.some_spec h,
  let k:= classical.some h,
  exact ((F k) a).get hk,
end

(by the way you seem to be missing noncomputable theory?)

Reid Barton (May 07 2020 at 02:38):

in principle you could make the value part computable too, since you only have to search over naturals

Jalex Stark (May 07 2020 at 02:39):

thanks, I added noncomputable theory. I should probably convince VSCode to autogenerate headers for me

Jalex Stark (May 07 2020 at 02:40):

oh cool I like this

Jalex Stark (May 07 2020 at 02:43):

with your definition, tidy can make a lot of progress :)

Jalex Stark (May 07 2020 at 17:23):

It works!

import tactic
import data.set.basic

universes u
open_locale classical
noncomputable theory
open pfun

def pfun.extends {α β : Type} (F f : α  →. β) : Prop := dom f  dom F   a ha ha', (f a).get ha = (F a).get ha'

def limit_of_chain {α β : Type} (F :   (α →. β))
  (F_chain :  n k, k  n  pfun.extends (F k) (F n) ) :
  α →. β :=
begin
  refine λ a, ⟨∃ n, a  dom (F n), λ h, _⟩,
  have hk := classical.some_spec h,
  let k:= classical.some h,
  exact ((F k) a).get hk,
end

lemma chain_pointwise_constant
    {α β : Type}
    (F :   (α →. β))
    (F_chain :  n k, k  n  pfun.extends (F k) (F n) ) :
     n k a ha_n ha_k, (F k a).get ha_k  = (F n a).get ha_n :=
begin
intros,
cases le_total k n;
have calc1 := F_chain _ _ h,
try {repeat {apply calc1.right
        <|> symmetry},},
end

lemma limit_of_chain_spec
    {α β : Type}
    {a : α}
    (F :   (α →. β))
    (F_chain :  n k, k  n  pfun.extends (F k) (F n))
    (ha' : (limit_of_chain F F_chain a).dom) :
     (k : ) (ha_k : (F k a).dom),
    (F k a).get ha_k
    = (limit_of_chain F F_chain a).get ha' :=
begin
unfold limit_of_chain at ha', simp only [] at ha',
cases ha' with k hk, existsi k,
existsi hk,
unfold limit_of_chain, simp only [],
apply chain_pointwise_constant _ F_chain,
end

def limit_of_chain_extends {α β : Type}  (F :   (α →. β)) (F_chain :  n k, k  n  pfun.extends (F k) (F n)) :  n, pfun.extends (limit_of_chain F F_chain) (F n) := begin
intro n, rw pfun.extends,
split,
    {rw set.subset_def, intros a ha,
    unfold limit_of_chain, tidy},
intros a ha ha',
suffices key :  k ha_k, (F k a).get ha_k = (limit_of_chain F F_chain a).get ha',
cases key with k key,
cases key with ha_k key,
rw  key,
cases le_total k n;
apply chain_pointwise_constant _ F_chain,
apply limit_of_chain_spec,
end

Last updated: Dec 20 2023 at 11:08 UTC