繁体   English   中英

设计DFA接受可被数字'n'整除的二进制字符串

[英]Design DFA accepting binary strings divisible by a number 'n'

我需要学习如何设计DFA,以便给定任意数字'n',它接受二进制字符串{0,1},其十进制等效数可以被'n'整除。

不同的'n'会有不同的DFA,但有人可以提供一个基本的方法,我应该遵循任何数字0 <n <10。

下面,我写了一个n等于5的答案,但是您可以应用相同的方法为任何n值和“任何位置数系统”绘制DFA,例如二进制,三元......

首先使用术语“完全DFA”, 在完整域中定义的DFA:δ:Q×Σ→Q称为“完全DFA”。 换句话说,我们可以说; 在完整DFA的转换图中,没有丢失边缘(例如,从Q中的每个状态,对于Σ中的每个语言符号存在一个输出边缘)。 注意:有时我们将部分 DFA定义为δ⊆Q×Σ→Q(读: 如何在DFA的定义中读取“δ:Q×Σ→Q” )。

设计DFA接受可被数字'n'整除的二进制数:

步骤1 :当您将数字ω除以n提醒可以是0,1,...,(n - 2)或(n - 1)。 如果余数为0 ,则意味着ω可被n整除,否则不能。 因此,在我的DFA中,将存在对应于余数值r的状态q r ,其中0 <= r <= (n - 1) ,并且DFA中的状态总数为n
在Σ上处理数字串ω之后,结束状态为q r意味着ω%n => r(%提醒操作符)。

在任何自动机中,状态的目的就像存储元素。 在atomata中的状态存储一些信息,如风扇的开关,可以判断风扇是处于“关闭”还是处于“开启”状态。 对于n = 5,DFA中的五个状态对应于五个提醒信息,如下所示:

  1. 如果提醒为0,则达到状态q 0。状态q 0是最终状态(接受状态)。 它也是一个初始状态。
  2. 如果提醒为1,则为非最终状态,状态q 1到达。
  3. 状态q 2如果提醒是2,则是非最终状态。
  4. 状态q 3如果提醒是3,则是非最终状态。
  5. 状态q 4如果提醒是4,则是非最终状态。

使用以上信息,我们可以开始绘制五种状态的转换图TD,如下所示:

图。1
图1

因此,5个状态表示5个剩余值。 在处理字符串ω之后,如果结束状态变为q 0 ,则意味着输入字符串的十进制等效值可被5整除。在上图中,q 0被标记为最终状态为两个同心圆。
另外,我已经在状态q 0处定义了转换规则δ:(q 0,0 )→q 0作为符号'0'的自循环,这是因为任何字符串的十进制等效仅由'0'为0并且0可被n整除。

步骤2 :上述TD不完整; 并且只能处理'0'的字符串。 现在添加一些边缘,以便它可以处理后续数字的字符串。 查看下表,显示可以在下一步添加的新转换规则:

┌──────┬──────┬─────────────┬─────────┐
│NumberBinaryRemainder(%5)End-state│
├──────┼──────┼─────────────┼─────────┤
│One   │1     │1            │q1       │
├──────┼──────┼─────────────┼─────────┤
│Two   │10    │2            │q2       │
├──────┼──────┼─────────────┼─────────┤
│Three │11    │3            │q3       │
├──────┼──────┼─────────────┼─────────┤
│Four  │100   │4            │q4       │
└──────┴──────┴─────────────┴─────────┘
  1. 要处理二进制字符串'1' ,应该有一个转换规则δ:(q 0,1 )→q 1
  2. 两个: -二进制表示为'10' ,结束状态应该是Q 2,并且处理'10' ,我们只需要增加一个转移规则δ:(Q 1,0)→Q 2
    路径 :→(q 0 )─1→(q 1 )─0→(q 2
  3. 三: -二进制它是'11'最终状态是Q 3,我们需要添加一个转换规则δ:(Q 1,1)→Q 3
    路径 :→(q 0 )─1→(q 1 )─1→(q 3
  4. 四: - 在二进制'100' ,结束状态为q 4 TD已经处理了前缀字符串'10' ,我们只需要添加一个新的过渡规则δ:(Q 2,0)→Q 4
    路径 :→(q 0 )─1→(q 1 )─0→(q 2 )─0→(q 4

图-2- 图-2

步骤3 :五= 101
图2中的上述转换图仍然是不完整的并且存在许多缺失边,例如,没有为δ定义转换:(q 2,1 ) - 并且应该存在规则来处理像'101'这样'101'字符串。
因为'101' = 5可以被5整除,并且为了接受'101'我将在上面的图-2中添加δ:(q 2,1 )→q 0
路径: →(q 0 )─1→(q 1 )─0→(q 2 )─1→(q 0
使用这个新规则,转换图如下:

无花果-3- 图-3-

在每个步骤的下面,我选择下一个后续的二进制数来添加缺失的边缘,直到我将TD作为“完整的DFA”。

步骤4 :六= 110。

我们可以在图3中将当前TD中的'11'处理为:→(q 0 )─11→(q 3 )─0→( )。 因为6%5 = 1,这意味着添加一个规则δ:(Q 3,0)→,Q 1。

无花果-4- 图-4-

步骤5 :七= 111

┌──────┬──────┬─────────────┬─────────┬────────────┬───────────┐
│NumberBinaryRemainder(%5)End-state PathAdd       │
├──────┼──────┼─────────────┼─────────┼────────────┼───────────┤
│Seven │111   │7 % 5 = 2    │q2       │ q0─11→q3    q3─1→q2    │
└──────┴──────┴─────────────┴─────────┴────────────┴───────────┘

无花果-5- 图-5

步骤-6 :八= 1000

┌──────┬──────┬─────────────┬─────────┬──────────┬─────────┐
│NumberBinaryRemainder(%5)End-state PathAdd     │
├──────┼──────┼─────────────┼─────────┼──────────┼─────────┤
│Eight │1000  │8 % 5 = 3    │q3       │q0─100→q4 │ q4─0→q3  │
└──────┴──────┴─────────────┴─────────┴──────────┴─────────┘

无花果-6- 图-6

步骤7 :九= 1001

┌──────┬──────┬─────────────┬─────────┬──────────┬─────────┐
│NumberBinaryRemainder(%5)End-state PathAdd     │
├──────┼──────┼─────────────┼─────────┼──────────┼─────────┤
│Nine  │1001  │9 % 5 = 4    │q4       │q0─100→q4 │ q4─1→q4  │
└──────┴──────┴─────────────┴─────────┴──────────┴─────────┘

图-7- 图-7

在TD-7中,边的总数是10 == Q×Σ= 5×2。它是一个完整的DFA,可以接受所有可能的二进制字符串,这些十进制等效值可以被5整除。

设计DFA接受可被数字n整除的三元数:

步骤1与二进制完全相同,使用图-1。

步骤2添加零,一,二

┌───────┬───────┬─────────────┬─────────┬──────────────┐
│DecimalTernaryRemainder(%5)End-state   Add        │
├───────┼───────┼─────────────┼─────────┼──────────────┤
│Zero   │0      │0            │q0       │ δ:(q0,0)→q0  │
├───────┼───────┼─────────────┼─────────┼──────────────┤
│One    │1      │1            │q1       │ δ:(q0,1)→q1  │
├───────┼───────┼─────────────┼─────────┼──────────────┤
│Two    │2      │2            │q2       │ δ:(q0,2)→q3  │
└───────┴───────┴─────────────┴─────────┴──────────────┘

无花果-8-
图8

第3步添加三,四,五

┌───────┬───────┬─────────────┬─────────┬─────────────┐
│DecimalTernaryRemainder(%5)End-stateAdd        │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Three  │10     │3            │q3       │ δ:(q1,0)→q3 │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Four   │11     │4            │q4       │ δ:(q1,1)→q4 │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Five   │12     │0            │q0       │ δ:(q1,2)→q0 │
└───────┴───────┴─────────────┴─────────┴─────────────┘

图9
图9

第四步加六,七,八

┌───────┬───────┬─────────────┬─────────┬─────────────┐
│DecimalTernaryRemainder(%5)End-stateAdd        │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Six    │20     │1            │q1       │ δ:(q2,0)→q1 │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Seven  │21     │2            │q2       │ δ:(q2,1)→q2 │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Eight  │22     │3            │q3       │ δ:(q2,2)→q3 │
└───────┴───────┴─────────────┴─────────┴─────────────┘

无花果-10
图-10

步骤5加九,十,十一

┌───────┬───────┬─────────────┬─────────┬─────────────┐
│DecimalTernaryRemainder(%5)End-stateAdd        │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Nine   │100    │4            │q4       │ δ:(q3,0)→q4 │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Ten    │101    │0            │q0       │ δ:(q3,1)→q0 │
├───────┼───────┼─────────────┼─────────┼─────────────┤
│Eleven │102    │1            │q1       │ δ:(q3,2)→q1 │
└───────┴───────┴─────────────┴─────────┴─────────────┘

无花果-11
图11

步骤6添加十二,十三,十四

┌────────┬───────┬─────────────┬─────────┬─────────────┐
│DecimalTernaryRemainder(%5)End-stateAdd        │
├────────┼───────┼─────────────┼─────────┼─────────────┤
│Twelve  │110    │2            │q2       │ δ:(q4,0)→q2 │
├────────┼───────┼─────────────┼─────────┼─────────────┤
│Thirteen│111    │3            │q3       │ δ:(q4,1)→q3 │
├────────┼───────┼─────────────┼─────────┼─────────────┤
│Fourteen│112    │4            │q4       │ δ:(q4,2)→q4 │
└────────┴───────┴─────────────┴─────────┴─────────────┘

无花果-12
图-12

转换图-12中的边缘总数为15 = Q×Σ= 5 * 3(完整的DFA)。 并且这个DFA可以接受所有字符串组成{0,1,2}这些十进制等值可以被5整除。
如果你注意到每一步,在表中有三个条目,因为在每一步我都添加一个状态的所有可能的传出边缘来制作一个完整的DFA(我添加一个边缘,以便q r状态得到的余数是r )!

要进一步添加,请记住两种常规语言的联合也是常规语言。 如果你需要设计一个接受二进制字符串的DFA,那么十进制等值可以被3或5整除,然后绘制两个单独的DFA,可以被3和5整除,然后将两个DFA结合起来构造目标DFA(对于1 <= n <= 10你必须联合10个DFA)。

如果要求您绘制接受二进制字符串的DFA,使得十进制等效值可以被5和3整除,那么您正在寻找可被15整除的DFA(但是6和8呢?)。

注意:使用此技术绘制的DFA只有在数字n和基数之间没有公因子时才会最小化DFA,例如,在第一个示例中没有 5到2之间,或者在第二个示例中没有5到3之间,因此上面构造的两个DFA都是最小化DFA。 如果您有兴趣进一步阅读有关nb基础可能的迷你状态的文章: 可分性和状态复杂性

下面我添加了一个Python脚本,我在学习Python库pygraphviz的同时编写了它。 我正在添加它我希望它可以对某些人有所帮助。

设计DFA为基数'b'数字字符串可被数字'n'整除:

因此,我们可以应用上述技巧来绘制DFA以识别任何基数'b'数字字符串,这些字符串可以对给定数字'n'进行整除。 在那个DFA中,状态总数将是n (对于n余数),边数应该等于'b'*'n' - 这是完整的DFA:'b'= DFA语言中符号的数量和'n '=州的数量。

使用上面的技巧,下面我写了一个Python脚本来绘制输入basenumber DFA。 在脚本中,函数divided_by_Nbase * number步骤填充DFA的转换规则。 在每个step-num中,我使用函数baseN()num转换为数字字符串num_s 为了避免处理每个数字字符串,我使用了临时数据结构lookup_table 在每个步骤中,数字字符串num_s结束状态被评估并存储在lookup_table以用于下一步骤。

对于DFA的转换图,我使用Pygraphviz库编写了一个函数draw_transition_graph (非常容易使用)。 要使用此脚本,您需要安装graphviz 要在转换图中添加彩色边缘,我会为每个符号get_color_dict函数随机生成颜色代码。

#!/usr/bin/env python
import pygraphviz as pgv
from pprint import pprint
from random import choice as rchoice

def baseN(n, b, syms="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
    """ converts a number `n` into base `b` string """
    return ((n == 0) and syms[0]) or (
        baseN(n//b, b, syms).lstrip(syms[0]) + syms[n % b])

def divided_by_N(number, base):
    """
    constructs DFA that accepts given `base` number strings
    those are divisible by a given `number`
    """
    ACCEPTING_STATE = START_STATE = '0'
    SYMBOL_0 = '0'
    dfa = {
        str(from_state): {
            str(symbol): 'to_state' for symbol in range(base)
        }
        for from_state in range(number)
    }
    dfa[START_STATE][SYMBOL_0] = ACCEPTING_STATE
    # `lookup_table` keeps track: 'number string' -->[dfa]--> 'end_state'
    lookup_table = { SYMBOL_0: ACCEPTING_STATE }.setdefault
    for num in range(number * base):
        end_state = str(num % number)
        num_s = baseN(num, base)
        before_end_state = lookup_table(num_s[:-1], START_STATE)
        dfa[before_end_state][num_s[-1]] = end_state
        lookup_table(num_s, end_state)
    return dfa

def symcolrhexcodes(symbols):
    """
    returns dict of color codes mapped with alphabets symbol in symbols
    """
    return {
        symbol: '#'+''.join([
            rchoice("8A6C2B590D1F4E37") for _ in "FFFFFF"
        ])
        for symbol in symbols
    }

def draw_transition_graph(dfa, filename="filename"):
    ACCEPTING_STATE = START_STATE = '0'
    colors = symcolrhexcodes(dfa[START_STATE].keys())
    # draw transition graph
    tg = pgv.AGraph(strict=False, directed=True, decorate=True)
    for from_state in dfa:
        for symbol, to_state in dfa[from_state].iteritems():
            tg.add_edge("Q%s"%from_state, "Q%s"%to_state,
                        label=symbol, color=colors[symbol],
                        fontcolor=colors[symbol])

    # add intial edge from an invisible node!
    tg.add_node('null', shape='plaintext', label='start')
    tg.add_edge('null', "Q%s"%START_STATE,)

    # make end acception state as 'doublecircle'
    tg.get_node("Q%s"%ACCEPTING_STATE).attr['shape'] = 'doublecircle'
    tg.draw(filename, prog='circo')
    tg.close()

def print_transition_table(dfa):
    print("DFA accepting number string in base '%(base)s' "
            "those are divisible by '%(number)s':" % {
                'base': len(dfa['0']),
                'number': len(dfa),})
    pprint(dfa)

if __name__ == "__main__":
    number = input ("Enter NUMBER: ")
    base = input ("Enter BASE of number system: ")
    dfa = divided_by_N(number, base)

    print_transition_table(dfa)
    draw_transition_graph(dfa)

执行它:

~/study/divide-5/script$ python script.py 
Enter NUMBER: 5
Enter BASE of number system: 4
DFA accepting number string in base '4' those are divisible by '5':
{'0': {'0': '0', '1': '1', '2': '2', '3': '3'},
 '1': {'0': '4', '1': '0', '2': '1', '3': '2'},
 '2': {'0': '3', '1': '4', '2': '0', '3': '1'},
 '3': {'0': '2', '1': '3', '2': '4', '3': '0'},
 '4': {'0': '1', '1': '2', '2': '3', '3': '4'}}
~/study/divide-5/script$ ls
script.py filename.png
~/study/divide-5/script$ display filename

输出:

base_4_divided_5_best
DFA接受基数4中的数字字符串,可以被5整除

同样,输入base = 4和number = 7生成 - dfa接受基数'4'中的数字字符串,它们可被'7'整除
顺便说一句,尝试将filename更改为.png.jpeg

引用我用来编写这个脚本的那些:
➊函数baseN来自“将整数转换为python中给定数字基础中的字符串”
➋安装“pygraphviz”: “Python没有看到pygraphviz”
➌学习使用Pygraphviz: “Python-FSM”
➍为每个语言符号生成随机十六进制颜色代码: “如何使用.join和for循环创建随机十六进制代码生成器?”

我知道我已经很晚了,但我只是想在@Grijesh提供的正确答案中添加一些内容。 我想指出@Grijesh提供的答案不会产生最小的DFA。 虽然答案肯定是获得DFA的正确方法,但如果你需要最小的DFA,你将需要调查你的除数。

例如,在二进制数中,如果除数是2的幂(即2 ^ n),则所需的最小状态数将是n + 1。 你会如何设计这样的自动机? 只需查看二进制数的属性即可。 对于一个数字,比如说8(即2 ^ 3),它的所有倍数都将最后3位作为0.例如,二进制中的40是101000.因此,对于一种语言来接受任何可被8整除的数字,我们只需要一个看到最后3位为0的自动机,我们可以只用4个状态而不是8个状态。 这是机器复杂性的一半。

实际上,这可以扩展到任何基础。 对于三元基数系统,如果我们需要设计一个自动机用于9的可除性,我们只需要看看输入的最后2个数是否为0.这可以在3个状态中再次完成。

虽然如果除数不是那么特殊,那么我们只需要通过@Grijesh的答案。 例如,在二元系统中,如果我们采用3或7或21的除数,我们将只需要那么多个状态。 因此,对于二进制系统中的任何奇数n,我们需要n个状态来定义接受n的所有倍数的语言。 另一方面,如果数字是偶数但不是2的幂(仅在二进制数的情况下),那么我们需要将数字除以2直到我们得到一个奇数,然后我们可以找到最小数量的状态添加生成的奇数和我们除以2的次数。

例如,如果我们需要找到DFA的最小状态数,它接受所有可被20整除的二进制数,我们可以:

20/2 = 10 
10/2 = 5

因此我们的答案是5 + 1 + 1 = 7 (1 + 1,因为我们将数字20除以两次)。

您可以使用简单的模块化算法构建DFA。 我们可以使用以下规则来解释w是一串k元数

V[0] = 0
V[i] = (S[i-1] * k) + to_number(str[i])

V[|w|]w表示的数字。 如果修改此规则以找到w mod N ,则规则变为此。

V[0] = 0
V[i] = ((S[i-1] * k) + to_number(str[i])) mod N

每个V[i]是从0到N-1的数字之一,它对应于DFA中的每个状态。 我们可以将其用作状态转换。

看一个例子。

k = 2,N = 5

| V | (V*2 + 0) mod 5     | (V*2 + 1) mod 5     |
+---+---------------------+---------------------+
| 0 | (0*2 + 0) mod 5 = 0 | (0*2 + 1) mod 5 = 1 |
| 1 | (1*2 + 0) mod 5 = 2 | (1*2 + 1) mod 5 = 3 |
| 2 | (2*2 + 0) mod 5 = 4 | (2*2 + 1) mod 5 = 0 |
| 3 | (3*2 + 0) mod 5 = 1 | (3*2 + 1) mod 5 = 2 |
| 4 | (4*2 + 0) mod 5 = 3 | (4*2 + 1) mod 5 = 4 |

k = 3,N = 5

| V | 0 | 1 | 2 |
+---+---+---+---+
| 0 | 0 | 1 | 2 |
| 1 | 3 | 4 | 0 |
| 2 | 1 | 2 | 3 |
| 3 | 4 | 0 | 1 |
| 4 | 2 | 3 | 4 |

现在你可以看到一个非常简单的模式。 您实际上可以构建DFA转换,只需从左到右,从上到下,从0到N-1写入重复数字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM