[英]Understanding failures of recursive calls on simple proof about FSA and regular languages in Agda
I'm trying to prove that a simple FSA in Agda only accepts string which end in zero- this is the first example in Sipser's book.我试图证明 Agda 中的简单 FSA 只接受以零结尾的字符串——这是 Sipser 书中的第一个示例。 I didn't implement evalFSA as a predicate, but rather as function, and am confused as to whether this was the right or wrong choice, as I'm now having trouble proving the soundness and completeness results with respect to the machine and the language, and whether this implementation detail is the cause of my difficululties.
我没有将 evalFSA 实现为谓词,而是将其实现为 function,并且对这是正确还是错误的选择感到困惑,因为我现在无法证明关于机器和语言的健全性和完整性结果,以及这个实现细节是否是我遇到困难的原因。
As soon as I pattern match on x below, it highlights the below line blue.一旦我在下面的 x 上进行模式匹配,它就会突出显示下面的蓝色线。 what does this mean, why is it doing it, and why does pattern matching on x0 resolve it?
这是什么意思,为什么要这样做,为什么 x0 上的模式匹配会解决它?
soundM : (xs : List Σ') → evalFSA' M xs → endsIn0 xs
soundM (x ∷ []) evM = {!!}
soundM (x0 ∷ x1 ∷ xs) evM = {!!}
-- soundM (0' ∷ []) f = tt
and here is the final issue.这是最后一个问题。 why can't I apply the recursive call in the 1' case?
为什么我不能在 1' 的情况下应用递归调用? the only difference between the f's is the use current state of the machine and the input string, but obviously this seems like a symmetry of the system that shouldn't effect our ability to compute.
f 之间的唯一区别是机器的使用电流 state 和输入字符串,但显然这似乎是系统的对称性,不应该影响我们的计算能力。
soundM' : (xs : List Σ') → evalFSA' M xs → endsIn0 xs
soundM' (0' ∷ []) evM = tt
soundM' (0' ∷ x1 ∷ xs) f = soundM' (x1 ∷ xs) f
soundM' (1' ∷ x1 ∷ xs) f = soundM' {!!} f
Here is the inferred f in the 0' case:这是在 0' 情况下推断的 f:
f : modal.helper M 0' (x1 ∷ xs) M xs (δ' S₁ x1)
And similairly in the 1' case:同样在 1' 的情况下:
f : modal.helper M 1' (x1 ∷ xs) M xs (δ' S₂ x1)
I'm having, simultaneous issues with what I'm calling completeness as well我也遇到了我所说的完整性的问题
completeM : (xs : List Σ') → endsIn0 xs → evalFSA' M xs ≡ ⊤
completeM (0' ∷ []) ex = refl
completeM (0' ∷ x1 ∷ xs) ex = completeM (x1 ∷ xs) ex
completeM (1' ∷ x1 ∷ xs) ex = {!!}
Here is the code to get here这是到达这里的代码
module fsa where
open import Bool
open import Level using (_⊔_)
open import Data.Nat.Base as Nat using (ℕ; zero; suc; _<′_; _+_)
open import Data.List.Base as List using (List; []; _∷_)
-- open import Data.Product as Prod using (∃; _×_; _,_)
open import Data.Empty
open import Data.Unit
open import Relation.Binary.PropositionalEquality using (_≡_; refl; subst)
-- open import Data.Fin as Fin
record FSA : Set₁ where
field
Q : Set
Σ : Set
δ : Q → Σ → Q
q₀ : Q
F : Q → Set
evalFSA' : (fsa : FSA) → List (FSA.Σ fsa) → Set
evalFSA' fsa [] = ⊥
evalFSA' fsa (x ∷ xs) = helper fsa (x ∷ xs) (FSA.q₀ fsa)
where
helper : (fsa : FSA) → List (FSA.Σ fsa) → (FSA.Q fsa) → Set
helper fsa [] q = FSA.F fsa q
helper fsa (x ∷ xs) q = helper fsa xs ((FSA.δ fsa) q x)
data Q' : Set where
S₁ : Q'
S₂ : Q'
data Σ' : Set where
0' : Σ'
1' : Σ'
q₀' : Q'
q₀' = S₁
F' : Q' → Set
F' S₁ = ⊤
F' S₂ = ⊥
δ' : Q' → Σ' → Q'
δ' S₁ 0' = S₁
δ' S₁ 1' = S₂
δ' S₂ 0' = S₁
δ' S₂ 1' = S₂
M : FSA
FSA.Q M = Q'
FSA.Σ M = Σ'
FSA.δ M = δ'
FSA.q₀ M = q₀'
FSA.F M = F'
exF1 = evalFSA' M (0' ∷ [])
exF2 = evalFSA' M (1' ∷ (0' ∷ 0' ∷ 1' ∷ []))
-- a more general endIn that i was orignally trying to use, but likewise failed to get to work
data Dec (A : Set) : Set where
yes : A → Dec A
no : (A → ⊥) → Dec A
sigDec : (x y : Σ') → Dec (x ≡ y)
sigDec 0' 0' = yes refl
sigDec 0' 1' = no (λ ())
sigDec 1' 0' = no (λ ())
sigDec 1' 1' = yes refl
endsIn : {X : Set} → ((x y : X) → Dec (x ≡ y)) → List X → X → Set
endsIn d [] x = ⊥
endsIn d (x ∷ []) x0 with (d x0 x)
... | yes refl = ⊤
... | no x1 = ⊥
endsIn d (x ∷ x1 ∷ xs) x0 = endsIn d (x1 ∷ xs) x0
_endsIn'_ : List Σ' → Σ' → Set
xs endsIn' x = endsIn sigDec xs x
endsIn0 : List Σ' → Set
endsIn0 [] = ⊥
endsIn0 (0' ∷ []) = ⊤
endsIn0 (0' ∷ x ∷ xs) = endsIn0 (x ∷ xs)
endsIn0 (1' ∷ xs) = endsIn0 xs
-- testing
10endsin0 = (1' ∷ 0' ∷ []) endsIn' 0'
n10endsin0 = (1' ∷ 1' ∷ []) endsIn' 0'
Your post is very large and contains numerous elements, which all can be commented in different ways.您的帖子很大,包含许多元素,都可以用不同的方式发表评论。 I will address them one by one, and explain the choices I made to make these elements more easily accessible.
我将一一解决它们,并解释我为使这些元素更易于访问而做出的选择。 Note that these choices consist in minor elements in your codes, mostly cosmetic, which do not change in any way the semantics of your definitions.
请注意,这些选择包含在代码中的次要元素中,主要是装饰性的,它们不会以任何方式改变定义的语义。 I start by giving you the correct code in details, after which I answer the questions.
我首先详细地给你正确的代码,然后我回答问题。
Let us start by cleaning up these imports to the minimum needed:让我们首先将这些导入清理到所需的最低限度:
module FSA where
open import Data.List.Base
open import Data.Empty
open import Data.Unit
I then kept your definition of your automaton record:然后,我保留了您对自动机记录的定义:
record FSA : Set₁ where
field
Q : Set
Σ : Set
δ : Q → Σ → Q
q₀ : Q
F : Q → Set
I have extracted your helper
function from the evalFSA'
function.我已经从
evalFSA'
function 中提取了你的helper
function。 The reason for this change is that when using when
, the function inherits all the parameters from the parent function, which makes it harder to comprehend further goals such as modal.helper M 0' (x1 ∷ xs) M xs (δ' S₁ x1)
.这种变化的原因是,当使用
when
,function 继承了父 function 的所有参数,这使得更难以理解进一步的目标,例如modal.helper M 0' (x1 ∷ xs) M xs (δ' S₁ x1)
.
helper : (fsa : FSA) → List (FSA.Σ fsa) → (FSA.Q fsa) → Set
helper fsa [] q = FSA.F fsa q
helper fsa (x ∷ xs) q = helper fsa xs ((FSA.δ fsa) q x)
evalFSA' : (fsa : FSA) → List (FSA.Σ fsa) → Set
evalFSA' fsa [] = ⊥
evalFSA' fsa (x ∷ xs) = helper fsa (x ∷ xs) (FSA.q₀ fsa)
Then your case study automaton remains the same, although I simplified the record instantiation without using copatterns:然后您的案例研究自动机保持不变,尽管我在不使用 copatterns 的情况下简化了记录实例化:
data Q' : Set where
S₁ : Q'
S₂ : Q'
data Σ' : Set where
0' : Σ'
1' : Σ'
q₀' : Q'
q₀' = S₁
F' : Q' → Set
F' S₁ = ⊤
F' S₂ = ⊥
δ' : Q' → Σ' → Q'
δ' S₁ 0' = S₁
δ' S₁ 1' = S₂
δ' S₂ 0' = S₁
δ' S₂ 1' = S₂
M : FSA
M = record { Q = Q' ; Σ = Σ' ; δ = δ' ; q₀ = q₀' ; F = F' }
I also simplified your predicate endsWith0
as follows:我还简化了您的谓词
endsWith0
如下:
endsWith0 : List Σ' → Set
endsWith0 [] = ⊥
endsWith0 (0' ∷ []) = ⊤
endsWith0 (_ ∷ xs) = endsWith0 xs
From this point on, soundM
and completeM
are proved as follows (I homogenized their signatures):从这一点开始,
soundM
和completeM
被证明如下(我将它们的签名同质化了):
soundM : ∀ xs → evalFSA' M xs → endsWith0 xs
soundM (0' ∷ []) evM = evM
soundM (0' ∷ x₁ ∷ xs) evM = soundM (x₁ ∷ xs) evM
soundM (1' ∷ 0' ∷ xs) evM = soundM (0' ∷ xs) evM
soundM (1' ∷ 1' ∷ xs) evM = soundM (1' ∷ xs) evM
completeM : ∀ xs → endsWith0 xs → evalFSA' M xs
completeM (0' ∷ []) ex = ex
completeM (0' ∷ x₁ ∷ xs) = completeM (x₁ ∷ xs)
completeM (1' ∷ 0' ∷ xs) = completeM (0' ∷ xs)
completeM (1' ∷ 1' ∷ xs) = completeM (1' ∷ xs)
I didn't implement evalFSA as a predicate, but rather as function, and am confused as to whether this was the right or wrong choice
我没有将 evalFSA 实现为谓词,而是将其实现为 function,并且对这是正确还是错误的选择感到困惑
There are no good answer to this question.这个问题没有很好的答案。 Both ideas are possible, and often debated on other questions on this site.
这两种想法都是可能的,并且经常在本网站上就其他问题进行辩论。 I personally always use predicates when possible, but others have arguments in favor of functions returning
⊤
or ⊥
.我个人总是尽可能使用谓词,但其他人有 arguments 支持返回
⊤
或⊥
的函数。 And, as you noticed it is possible to prove what you wanted using your implementation.而且,正如您所注意到的,可以使用您的实现来证明您想要什么。
it highlights the below line blue.
它突出显示下面的蓝色线。 what does this mean
这是什么意思
As far as I know, this is a bug.据我所知,这是一个错误。 Some weird coloration like that started to occasionally happen to me recently as well, but they apparently do not mean anything.
最近我也开始偶尔出现类似的一些奇怪的颜色,但它们显然没有任何意义。
You asked the following question:您问了以下问题:
why can't I apply the recursive call in the 1' case?
为什么我不能在 1' 的情况下应用递归调用? the only difference between the f's is the use current state of the machine and the input string, but obviously this seems like a symmetry of the system that shouldn't effect our ability to compute
f 之间的唯一区别是机器的使用电流 state 和输入字符串,但显然这似乎是系统的对称性,不应该影响我们的计算能力
Answering this question is actually quite simple, but this answer was somewhat hidden in your implementation because you embedded the definition of helper
inside the definition of evalFSA'
, which I changed as explained.回答这个问题实际上很简单,但是这个答案在您的实现中有些隐藏,因为您将
helper
的定义嵌入到evalFSA'
的定义中,我按照解释进行了更改。
Let us consider the following code while proving soundM
:让我们在证明
soundM
时考虑以下代码:
soundM : (xs : List Σ') → evalFSA' M xs → endsWith0 xs
soundM (0' ∷ []) evM = evM
soundM (0' ∷ x ∷ xs) evM = soundM (x ∷ xs) {!evM!}
soundM (1' ∷ x ∷ xs) evM = soundM (x ∷ xs) {!evM!}
When asking Agda what is the goal and the type of the current element in the first goal, it answers:当询问 Agda 的目标是什么以及第一个目标中当前元素的类型时,它会回答:
Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₁ x)
Since you have defined q₀'
as follows:由于您已将
q₀'
定义如下:
q₀' : Q'
q₀' = S₁
Agda know that q₀'
is definitionally equal to S₁
which means the current term has actually the same type as the goal, which is why it is accepted. Agda 知道
q₀'
在定义上等于S₁
,这意味着当前术语实际上与目标具有相同的类型,这就是它被接受的原因。
In the other hole however, asking Agda the same information gives:然而,在另一个洞中,向 Agda 询问相同的信息给出了:
Goal: helper M xs (δ' q₀' x)
Have: helper M xs (δ' S₂ x)
In this case, q₀'
is not definitionally equal to S₂
(and not equal in any way actually) which means these types are not equal, and it is not possible to conclude right away.在这种情况下,
q₀'
定义上不等于S₂
(实际上也不等于),这意味着这些类型不相等,并且不可能立即得出结论。
As shown in my code, pattern matching an additional time on x
allows agda to further reduce the goal which allows us to conclude.如我的代码所示,在
x
上进行模式匹配的额外时间允许 agda 进一步减少允许我们得出结论的目标。
A similar reasoning is used to provide a proof of completeM
类似的推理用于提供
completeM
的证明
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.