I'm currently trying to define two mutual recursive (partial) functions. I'm also using (domintros)
.
Everything worked out fine until I introduced the line let d_new = if wn then d_old ⊔ d_new else d_old ⊓ d_new in
(or operators similar to inf
and sup
). Proving pattern completeness and pattern compatibility still works out fine. But the keyword function
is now highlighted in red and shows the following error
Tactic failed
The error(s) above occurred for the goal statement⌂:
[...]
I tried to construct a minimal working example but didn't manage to reproduce the error in less complex definitions. And as most of the code is not mine, I can't publish the whole definition. Still hoping the error is so trivial that you guys can help me nonetheless. Is there a problem with the termination proof? Or something else?
Any hints are highly appreciate. Thanks in advance :)
Update: I managed to construct a minimal working example and the problem is neither with mutual recursion nor partial functions (?). Here's the code snippet:
function foo :: "nat ⇒ bool ⇒ nat" where
"foo old expand = (
let tmp = if old < 100 then old + 1 else old in
let new = if expand then old ⊔ tmp else old ⊓ tmp in
if new = old then
if expand then
foo new False
else
new
else
foo new expand)"
by pat_completeness auto
Key idea: There's a monotonically increasing function (in this case if old < 100 then old + 1 else old
. old+1
works as well, but then the example would never terminate, which is not what I'm aiming for). There's two phases. First the expand
phase where results are always chosen by means of sup
. As soon as a fixed point is reached, the algorithm switches to a second phase where values are now combined via inf
(which is trivial in this example and should terminate right away as new = old
in the first iteration).
Again, keyword function
is underlined all red and the following error ist displayed:
Tactic failed
The error(s) above occurred for the goal statement⌂:
⟦⋀old expand x xa.
⟦x = (if old < 100 then old + 1 else old);
xa = (if expand then old ⊔ x else old ⊓ x); xa = old;
expand⟧
⟹ P (xa, False) (old, expand);
⋀old expand x xa.
⟦x = (if old < 100 then old + 1 else old);
xa = (if expand then old ⊔ x else old ⊓ x); xa ≠ old⟧
⟹ P (xa, expand) (old, expand)⟧
⟹ foo_rel ≤ P
What's the issue with my definition? Potential nontermination in case the algorithm is called with expand
set to False
? (Which is sth I never intend to do.)
Here is a version that fails, but only needs Main:
function (sequential) foo :: "nat set ⇒ bool ⇒ nat set" where
"foo old expand = (
let new = old ∩ old in
if new = old then
foo new expand
else
foo new expand)"
by pat_completeness auto
I think that the way forward here is to write on the mailing list (I am not sure who feels responsible for the function package, but you have a higher chance on the mailing list)
Interesting, thanks for the example! Just realized there's no need for the 2nd param. In a nutshell:
function (sequential) foo :: "nat set ⇒ nat set" where
"foo old = (
let new = old ∩ old in
if new = old then
foo new
else
foo new)"
by pat_completeness auto
does show the Tactic failed
error, but
function (sequential) foo :: "nat set ⇒ nat set" where
"foo old = (
let new = old ∩ old in
if new = old then
foo old ∩ old
else
foo new)"
by pat_completeness auto
does not. Replacing new
in any of the other lines does not fix the problem.
Edit: Other trivial operations such as old ∪ {}
do the job (i.e. invoking the error) as well, btw.
I'll discuss this on the mailing list :)
Last updated: Dec 30 2024 at 16:22 UTC