Zulip Chat Archive
Stream: new members
Topic: How would you complete this inductive proof?
Agnishom Chattopadhyay (Sep 28 2022 at 20:15):
I am trying to do some very simple constructions and proofs using the computability libraries.
How would you complete this proof?
import computability.regular_expressions
import computability.NFA
import computability.epsilon_NFA
import computability.language
universes u v
variables {α : Type u} {σ σ' : Type v}
def choice (M : ε_NFA α σ) (N : ε_NFA α σ') : (ε_NFA α (σ ⊕ σ')) :=
{ start := (sum.inl <$> M.start) ∪ (sum.inr <$> N.start),
accept := (sum.inl <$> M.accept) ∪ (sum.inr <$> N.accept),
step :=
λ s a,
match s with
| sum.inl s := sum.inl <$> M.step s a
| sum.inr s := sum.inr <$> N.step s a
end }
lemma choice_eval (M : ε_NFA α σ) (N : ε_NFA α σ') (w : list α) (x : σ) :
x ∈ M.eval w → sum.inl x ∈ (choice M N).eval w :=
begin
intro h,
induction w with a w ih generalizing x,
{ simp at h,
simp,
cases h,
{ apply ε_NFA.subset_ε_closure,
fconstructor,
finish,
},
{
apply ε_NFA.ε_closure.step,
{ -- ?? refine (sum.inl h_s),
}
}
},
end
Any hints would be helpful. I am not sure I understand how the ε_NFA.ε_closure inductive proposition can be used.
Eric Rodriguez (Sep 28 2022 at 21:49):
it'll probably make it easier if you make some API for your definition, such as what the eps_closure
of choice
is (for specific inl/inr)
Eric Rodriguez (Sep 28 2022 at 21:49):
also, I think people are generally more likely to help if there's no autogenerated names in your code; it makes it hard to read and use
Agnishom Chattopadhyay (Sep 28 2022 at 23:51):
thanks, that is probably a good idea.
Joanna Choules (Sep 29 2022 at 09:40):
You can avoid having to supply sum.inl h_s
in a separate step by currying it into ε_NFA.ε_closure.step
and apply
ing that:
apply ε_NFA.ε_closure.step (sum.inl h_s),
That way you're just left with two metavariable-free subgoals.
The constructor
family of tactics all seem to do broadly the same thing, which is to try and apply
each constructor of the goal type in turn until they find one that works. In this case fconstructor
applies or.inl
, which happens to be the correct constructor to let you complete the proof – or.inr
is also applicable here, though, and if fconstructor
had applied that instead then you'd be stuck with an unprovable goal.
Joanna Choules (Sep 29 2022 at 22:27):
So I had a go at finishing this proof myself (very happy to share the code if you'd like) and one of the tricky parts is that the default induction principle for list
sends you down the wrong path. ε_NFA.eval
works with input strings that accumulate new elements at the end, whereas lists, definitionally speaking, accumulate from the front. The solution is to tell the induction
tactic to use a different principle:
Agnishom Chattopadhyay (Oct 03 2022 at 20:00):
Thanks, that is interesting to note. I have not looked back at this in a while, but I will try to give it another try soon.
By the way, how does Lean know that the lemma list.reverse_rec_on
can be used as an induction principle?
Joanna Choules (Oct 03 2022 at 21:53):
It does it by inspecting the result type. From docs#tactic_doc.tactic.induction:
induction e using r
allows the user to specify the principle of induction that should be used. Herer
should be a theorem whose result type must be of the formC t
, whereC
is a bound variable andt
is a (possibly empty) sequence of bound variables
Last updated: Dec 20 2023 at 11:08 UTC