Zulip Chat Archive

Stream: mathlib4

Topic: Dsimp and deriv


Daniel Rehsmann (Mar 24 2025 at 18:54):

I have following code:

def U (P1 P2 q :   ) (r : ) :  := deriv q r * P1 r - (1 - q r) * deriv P1 r
lemma U_deriv_pos (h : Assumptions P1 P2 q):  r > 0, 0 < deriv (U P1 P2 q) r := by
  unfold

which gives following goal state:

 0 < deriv (fun r  deriv q r * P1 r - (1 - q r) * deriv P1 r) r

How can I remove the lambda definition here, i.e., changing the goal state to:

 0 < deriv (deriv q r * P1 r - (1 - q r) * deriv P1 r) r

1.) dsimp makes no progress
2.)change 0 < deriv (deriv q * P1 - (1 - q) * deriv P1) r works, but seems to be a very unhandy way of solving such issues.

Do you have any ideas to do this more economically?

Ilmārs Cīrulis (Mar 24 2025 at 18:57):

In the definition of U variable P2 is unused.

Etienne Marion (Mar 24 2025 at 18:58):

Can you provide a #mwe please?

Ilmārs Cīrulis (Mar 24 2025 at 18:59):

Do you mean def U (P1 P2 q : ℝ → ℝ) (r : ℝ) : ℝ := deriv q r * P1 r - (1 - q r) * deriv P2 r? Or smth like that

Daniel Rehsmann (Mar 24 2025 at 19:12):

Here a mwe

import Mathlib
open Set
open Real
noncomputable section
variable (q :   )
def f (q :   ) (r c : ) :  := c * deriv q r
lemma f_deriv_pos :  r > 0, 0 < deriv (f q) r := by
  unfold f
  dsimp

Here dsimp makes no progress, and remains at goal state

0 < deriv (fun r c  c * deriv q r) r

How can I get rid of the lambda definitions inside deriv ( ) r

Aaron Liu (Mar 24 2025 at 19:12):

Daniel Rehsmann said:

How can I remove the lambda definition here, i.e., changing the goal state to:

 0 < deriv (deriv q r * P1 r - (1 - q r) * deriv P1 r) r

Does that typecheck?

Daniel Rehsmann (Mar 24 2025 at 19:13):

(deleted)

Daniel Rehsmann (Mar 24 2025 at 19:14):

Aaron Liu said:

Daniel Rehsmann said:

How can I remove the lambda definition here, i.e., changing the goal state to:

 0 < deriv (deriv q r * P1 r - (1 - q r) * deriv P1 r) r

Does that typecheck?

Yes. To simplify discussions, i added a mwe.

Etienne Marion (Mar 24 2025 at 19:16):

What change do you want to do? The first argument of deriv has to be a function.

Aaron Liu (Mar 24 2025 at 19:17):

Can confirm it does not in fact typecheck

Daniel Rehsmann (Mar 24 2025 at 19:17):

Etienne Marion said:

What change do you want to do? The first argument of deriv has to be a function.

I would like to have a goal state:0 < deriv (c * deriv q r) r

Daniel Rehsmann (Mar 24 2025 at 19:19):

Aaron Liu said:

Can confirm it does not in fact typecheck

In my environment, it does. Thats why I added a mwe

Etienne Marion (Mar 24 2025 at 19:19):

There is no c in the environment, this can't work

Daniel Rehsmann (Mar 24 2025 at 19:39):

Etienne Marion said:

There is no c in the environment, this can't work

Well, I worked a little bit on the mwe:

open Set
open Real
noncomputable section
variable (q p :   )
def f (q p:   ) (r:) :  := deriv q r + deriv p r
lemma f_deriv_pos (q p:   ) (r: ) :  r > 0, 0 < deriv (f q p) r := by
  rintro r rpos
  unfold f

has the same problem. The problem is unrelated to c.

Aaron Liu (Mar 24 2025 at 19:44):

import Mathlib
open Set
open Real
noncomputable section
variable (q p :   )
def f (q p:   ) (r:) :  := deriv q r + deriv p r
lemma f_deriv_pos (q p:   ) (r: ) :  r > 0, 0 < deriv (f q p) r := by
  rintro r rpos
  unfold f
  -- error
  #check deriv (deriv q r + deriv p r) r

Etienne Marion (Mar 24 2025 at 19:47):

I am guessing you want this:

import Mathlib

open Set
open Real
noncomputable section
variable (q p :   )
def f (q p:   ) (r:) :  := deriv q r + deriv p r
lemma f_deriv_pos (q p:   ) (r: ) :  r > 0, 0 < deriv (f q p) r := by
  rintro r rpos
  unfold f
  rw [ Pi.add_def]

The simplifier will not remove the fun r => _ because it is considered to be the most unfolded form. Either use change as you did, or find the relevant lemma (as I did with Pi.add_def), but what we usually do is just keep the fun r => _ form and apply lemmas to it directly.

Daniel Rehsmann (Mar 24 2025 at 19:51):

Ok thank you. I am quite new to lean, so the typical way to work on such nested functions is to keep expressions fun r => _ in the goal state as they are and directly apply lemmas, correct?

Etienne Marion (Mar 24 2025 at 19:54):

Indeed. Both forms are definitionally equal, which means that any lemma which applies to one will apply to the other. However, you can have trouble when you use rw to rewrite a term, because rw does not see through definitional equality. That is why some lemmas in the library exist in both versions, one for f and one for fun x => f x.

Daniel Rehsmann (Mar 24 2025 at 20:01):

I see. But pushing dsimp inside a function argument is not possible? I prefer the later notation.

Etienne Marion (Mar 24 2025 at 20:27):

I'm not sure I understand the question. If you just have f + g then dsimp won't rewrite it to fun x => f x + g x, and if you have fun x => f x + g x it won't rewrite it to f + g. However, if you have (f + g) x or (fun y => f y + g y) x then in both cases it will rewrite to f x + g x.

Daniel Rehsmann (Mar 24 2025 at 20:48):

Here again the minimal example

open Set
open Real
noncomputable section
variable (q:   )
def f3 (q:   ) (r:) :  := deriv q r
lemma f3_deriv_pos (q:   ) (r: ) :  r > 0, 0 < deriv (f3 q) r := by
  rintro r rpos
  unfold f3

I simply want to push dsimp (or any simp tactic that gets rid of the lambda expression) on the _ section of of the function
deriv (_) r

Etienne Marion (Mar 24 2025 at 21:08):

You can just change your definition of f3.

import Mathlib

noncomputable def f3 (q :   ) :    := deriv q

lemma f3_deriv_pos (q :   ) :  r > 0, 0 < deriv (f3 q) r := by
  intro r rpos
  unfold f3

Daniel Rehsmann (Mar 24 2025 at 21:11):

Perfect! Thank you!


Last updated: May 02 2025 at 03:31 UTC