Zulip Chat Archive
Stream: new members
Topic: Can't `refl` simple equation
Marcus Rossel (Jan 19 2021 at 14:36):
I have this goal state:
p p' : ports
h : list.length p' < list.length p
⊢ list.length p' + (list.length p - list.length p') = list.length p
... and neither refl
, finish
, library_search
, hint
, nor suggest
close the goal or suggest a solution. Is this normal?
Those "ports"-things are defined as:
def ports := list (option value)
Damiano Testa (Jan 19 2021 at 14:37):
Are those natural numbers? There is something along the lines of add_sub_cancel
in nat
, I think.
Patrick Massot (Jan 19 2021 at 14:39):
Does omega
work?
Marcus Rossel (Jan 19 2021 at 14:40):
Patrick Massot said:
Does
omega
work?
What's omega
?
Kevin Buzzard (Jan 19 2021 at 14:41):
If you've imported tactic, just try it
Patrick Massot (Jan 19 2021 at 14:41):
The answer to this question is: no it's not normal, there should be a come_on_lean
tactic closing this goal and thousands of similarly silly goals. But it's unfortunately expected.
Kevin Buzzard (Jan 19 2021 at 14:41):
Try writing "and now it's obvious" in French and see if it closes the goal. Apparently this sometimes works now!
Marcus Rossel (Jan 19 2021 at 14:42):
omega
worked! Thanks guys
Damiano Testa (Jan 19 2021 at 14:44):
This also works:
lemma simple {a b c : ℕ} {h : a < b} : a + (b - a) = b :=
begin
rw [← nat.add_sub_assoc (le_of_lt h), nat.add_sub_cancel_left],
end
Kevin Buzzard (Jan 19 2021 at 14:45):
(and it's probably faster)
Patrick Massot (Jan 19 2021 at 14:46):
The funny thing is the fact you have a strict inequality is probably making it more difficult for automation.
Damiano Testa (Jan 19 2021 at 14:46):
The omega
way:
exact (id
((propext imp_iff_not_or).trans
((λ (a a_1 : Prop) (e_1 : a = a_1) (b b_1 : Prop) (e_2 : b = b_1), congr (congr_arg or e_1) e_2) (¬a + 1 ≤ b)
(b + 1 ≤ a + 1)
((propext not_le).trans (propext nat.lt_iff_add_one_le))
(a + (b - a) = b)
(a + (b - a) = b)
(eq.refl (a + (b - a) = b))))).mpr
(omega.nat.univ_close_of_unsat_neg_elim_not 2
((omega.nat.preform.le ((omega.nat.preterm.var 1 1).add (omega.nat.preterm.cst 1))
((omega.nat.preterm.var 1 0).add (omega.nat.preterm.cst 1))).or
(omega.nat.preform.eq
((omega.nat.preterm.var 1 0).add ((omega.nat.preterm.var 1 1).sub (omega.nat.preterm.var 1 0)))
(omega.nat.preterm.var 1 1)))
(omega.nat.unsat_of_unsat_sub_elim (omega.nat.preterm.var 1 1) (omega.nat.preterm.var 1 0)
((omega.nat.preform.le
(((omega.nat.preterm.var 1 0).add (omega.nat.preterm.cst 1)).add (omega.nat.preterm.cst 1))
((omega.nat.preterm.var 1 1).add (omega.nat.preterm.cst 1))).and
((omega.nat.preform.le
(((omega.nat.preterm.var 1 0).add ((omega.nat.preterm.var 1 1).sub (omega.nat.preterm.var 1 0))).add
(omega.nat.preterm.cst 1))
(omega.nat.preterm.var 1 1)).or
(omega.nat.preform.le ((omega.nat.preterm.var 1 1).add (omega.nat.preterm.cst 1))
((omega.nat.preterm.var 1 0).add ((omega.nat.preterm.var 1 1).sub (omega.nat.preterm.var 1 0))))))
(omega.nat.unsat_of_unsat_dnf
(((omega.nat.preform.le
(((omega.nat.preterm.var 1 0).add (omega.nat.preterm.cst 1)).add (omega.nat.preterm.cst 1))
((omega.nat.preterm.var 1 1).add (omega.nat.preterm.cst 1))).and
((omega.nat.preform.le
(((omega.nat.preterm.var 1 0).add (omega.nat.preterm.var 1 2)).add (omega.nat.preterm.cst 1))
(omega.nat.preterm.var 1 1)).or
(omega.nat.preform.le ((omega.nat.preterm.var 1 1).add (omega.nat.preterm.cst 1))
((omega.nat.preterm.var 1 0).add (omega.nat.preterm.var 1 2))))).and
((omega.nat.preform.eq (omega.nat.preterm.var 1 1)
((omega.nat.preterm.var 1 0).add (omega.nat.preterm.var 1 2))).or
((omega.nat.preform.le (omega.nat.preterm.var 1 1) (omega.nat.preterm.var 1 0)).and
(omega.nat.preform.eq (omega.nat.preterm.var 1 2) (omega.nat.preterm.cst 0)))))
⟨⟨trivial, ⟨trivial, trivial⟩⟩, ⟨trivial, ⟨trivial, trivial⟩⟩⟩
⟨⟨⟨⟨⟨trivial, trivial⟩, trivial⟩, ⟨trivial, trivial⟩⟩,
⟨⟨⟨⟨trivial, trivial⟩, trivial⟩, trivial⟩,
⟨⟨trivial, trivial⟩, ⟨trivial, trivial⟩⟩⟩⟩,
⟨⟨trivial, ⟨trivial, trivial⟩⟩, ⟨⟨trivial, trivial⟩, ⟨trivial, trivial⟩⟩⟩⟩
(omega.clauses.unsat_cons
([(int.of_nat 0, [int.of_nat 1, -[1+ 0], int.of_nat 1])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, -[1+ 0]])])
[([(int.of_nat 0, [int.of_nat 0, int.of_nat 0, -[1+ 0]])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, -[1+ 0]]), (int.of_nat 0, [int.of_nat 1, -[1+ 0]])]), ([(int.of_nat 0,
[int.of_nat 1, -[1+ 0], int.of_nat 1])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[int.of_nat 1, -[1+ 0], int.of_nat 1])]), ([(int.of_nat 0, [int.of_nat 0, int.of_nat 0, -[1+ 0]])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[int.of_nat 1, -[1+ 0], int.of_nat 1]), (int.of_nat 0, [int.of_nat 1, -[1+ 0]])])]
(omega.unsat_of_unsat_eq_elim [omega.ee.factor (int.of_nat 1), omega.ee.cancel 0]
([(int.of_nat 0, [int.of_nat 1, -[1+ 0], int.of_nat 1])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, -[1+ 0]])])
(omega.unsat_of_unsat_lin_comb [0, 0, 0, 0, 1]
[(int.of_nat 0, [int.of_nat 0, int.of_nat 1, -[1+ 0]]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 1, int.of_nat 0]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0],
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0],
[int.of_nat 0, int.of_nat 0, int.of_nat 0])]
(omega.unsat_lin_comb_of [0, 0, 0, 0, 1]
[(int.of_nat 0, [int.of_nat 0, int.of_nat 1, -[1+ 0]]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 1, int.of_nat 0]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0],
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0],
[int.of_nat 0, int.of_nat 0, int.of_nat 0])]
(int.neg_succ_lt_zero 0)
(omega.forall_mem_repeat_zero_eq_zero [int.of_nat 0, int.of_nat 0, int.of_nat 0].length))))
(omega.clauses.unsat_cons
([(int.of_nat 0, [int.of_nat 0, int.of_nat 0, -[1+ 0]])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, -[1+ 0]]), (int.of_nat 0, [int.of_nat 1, -[1+ 0]])])
[([(int.of_nat 0, [int.of_nat 1, -[1+ 0], int.of_nat 1])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[int.of_nat 1, -[1+ 0], int.of_nat 1])]), ([(int.of_nat 0,
[int.of_nat 0, int.of_nat 0, -[1+ 0]])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[int.of_nat 1, -[1+ 0], int.of_nat 1]), (int.of_nat 0, [int.of_nat 1, -[1+ 0]])])]
(omega.unsat_of_unsat_eq_elim [omega.ee.factor (int.of_nat 1), omega.ee.neg, omega.ee.cancel 2]
([(int.of_nat 0, [int.of_nat 0, int.of_nat 0, -[1+ 0]])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, -[1+ 0]]), (int.of_nat 0, [int.of_nat 1, -[1+ 0]])])
(omega.unsat_of_unsat_lin_comb [0, 0, 0, 1, 0, 1]
[(int.of_nat 0, [int.of_nat 1, int.of_nat 0, int.of_nat 0]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 1, int.of_nat 0]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 0]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, int.of_nat 0]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, int.of_nat 0]), (int.of_nat 0, [int.of_nat 1, -[1+ 0], int.of_nat 0])]
(omega.unsat_lin_comb_of [0, 0, 0, 1, 0, 1]
[(int.of_nat 0, [int.of_nat 1, int.of_nat 0, int.of_nat 0]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 1, int.of_nat 0]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 0]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, int.of_nat 0]), (-[1+ 0],
[-[1+ 0], int.of_nat 1, int.of_nat 0]), (int.of_nat 0,
[int.of_nat 1, -[1+ 0], int.of_nat 0])]
(int.neg_succ_lt_zero 0)
(omega.forall_mem_repeat_zero_eq_zero [int.of_nat 0, int.of_nat 0, int.of_nat 0].length))))
(omega.clauses.unsat_cons
([(int.of_nat 0, [int.of_nat 1, -[1+ 0], int.of_nat 1])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[int.of_nat 1, -[1+ 0], int.of_nat 1])])
[([(int.of_nat 0, [int.of_nat 0, int.of_nat 0, -[1+ 0]])],
[(int.of_nat 0, [int.of_nat 1]), (int.of_nat 0, [int.of_nat 0, int.of_nat 1]), (int.of_nat 0,
[int.of_nat 0, int.of_nat 0, int.of_nat 1]), (-[1+ 0], [-[1+ 0], int.of_nat 1]), (-[1+ 0],
[int.of_nat 1, -[1+ 0], int.of_nat 1]), (int.of_nat 0, [int.of_nat 1, -[1+ 0]])])]
(omega.unsat_of_unsat_eq_elim [omega.ee.factor (int.of_nat 1), omega.ee.cancel 0]
([(int.of_nat 0, [int.of_nat 1, -[1+ 0], int.of_nat 1])],
Damiano Testa (Jan 19 2021 at 14:47):
The rewrite way:
exact (id (eq.rec (eq.refl (a + (b - a) = b)) (nat.add_sub_assoc (le_of_lt h) a).symm)).mpr
((id (eq.rec (eq.refl (a + b - a = b)) (nat.add_sub_cancel_left a b))).mpr (eq.refl b))
Damiano Testa (Jan 19 2021 at 14:48):
Patrick: library search with \le:
exact nat.add_sub_of_le h,
lemma simple {a b c : ℕ} {h : a < b} : a + (b - a) = b :=
nat.add_sub_of_le (le_of_lt h)
Patrick Massot (Jan 19 2021 at 14:50):
This confirms my theory.
Bryan Gin-ge Chen (Jan 19 2021 at 15:44):
Marcus Rossel said:
What's
omega
?
In short, it solves arithmetic goals over nat
and int
which only involve addition. See tactic#omega for more gory details. It's unfortunately a bit slow and probably needs to be rewritten from scratch as the current state is not very maintainable.
Bryan Gin-ge Chen (Jan 19 2021 at 15:47):
@Damiano Testa Note that you can write h.le
instead of le_of_lt h
; there are a lot of similar dot notation tricks for inequalities defined starting here.
Damiano Testa (Jan 19 2021 at 15:49):
Bryan, thank you very much for this pointer: I had no idea of this possibility! I also think that this is the third time that someone mentions to me the dot notation: it is taking more time than I thought to really use it!
I updated the proof above, exploiting the shortening!
Bryan Gin-ge Chen (Jan 19 2021 at 15:54):
No problem. This one's relatively minor, but I'm a big fan of the way dot notation works in Lean; it can really make long chains of applications much shorter without sacrificing too much readability.
Last updated: Dec 20 2023 at 11:08 UTC