Skip to content

feat: contractive and nonexp tactics - #558

Open
oliversoeser wants to merge 79 commits into
leanprover-community:masterfrom
oliversoeser:fixpoint-construction
Open

feat: contractive and nonexp tactics#558
oliversoeser wants to merge 79 commits into
leanprover-community:masterfrom
oliversoeser:fixpoint-construction

Conversation

@oliversoeser

@oliversoeser oliversoeser commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Description

Implements contractive and nonexp tactics to automatically solve OFE.Contractive and OFE.NonExpansive goals, respectively.

Closes #123

Checklist

  • My code follows the mathlib naming and code style conventions
  • I have added my name to the authors section of any appropriate files

@markusdemedeiros

Copy link
Copy Markdown
Collaborator

This is sweet! I think we should wait until #550 is merged though, since it is still a debated question how this new parameter is going to be inferred, and this will probably change your tactic.

@MackieLoeffel MackieLoeffel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR and sorry for the delay in reviewing. I slightly cleaned up the PR and moved around some files. Overall the PR looks nice, but I tried using nonexp and contractive in more places in the repo and ran into some problems. See the comments below.


meta partial def contractiveMain (goal : MVarId) (guarded : Bool) : TacticM Unit := do
if ← goal.isAssigned then return
trace[NonExp] "Goal: {← goal.getType}"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using the tactic and it failed without giving any information. So I added some rudimentary tracing to the tactic, but it is currently not great. For example, it does not show what instances were tried or which step succeeded. Can you add better tracing information?

refine ((equiv_iff.mpr le_upd_unfold).dist).trans ?_
refine .trans ?_ ((equiv_iff.mpr le_upd_unfold).dist).symm
-- TODO: Why does nonexp not work here?
refine forall_ne (fun i => ?_)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using nonexp here and it failed. Do you know why?

In general, I think it would be good to make a pass over the repo and use nonexp and contractive for all NonExpansive and Contractive obligations.

(fun a => NextContractive.distLater_dist (fun m hm => h m hm a))⟩
Contractive (saved_pred_own (GF := GF) (A := A) γ dq) where
distLater_dist := -- TODO: Why does by contractive not work here?
fun {_ _ _} h => saved_anything_ne γ dq |>.ne

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried using by contractive here and it failed. Do you know why?

Comment thread Iris/IrisTest/NonExp.lean
ne := by nonexp

/- `nonexp` should also work when directly called on a NonExpansive goal -/
example : NonExpansive (fun x : α => x) := by nonexp

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think nonexp should also work when directly called on a NonExpansive goal. Otherwise, it will be very confusing for the users. Same for contractive. Can you make this work?

contractiveSetup
contractiveMain (← getMainGoal) false

elab "nonexp" : tactic => do

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually need two different tactics for nonexp and contractive or can they be unified into a single tactic?

if ← tryStep (contractiveMain · guarded) distLaterStep goal then return

-- applies a non-expansive lemma
if ← tryStep (contractiveMain · guarded) nonexpStep goal then return

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation is based on backtracking between the different options. Do we actually need the backtracking or can we just stick with the first case that works?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Contractivity tactic

3 participants