在Python中使用Levenshtein距离作为启发式生成字符串的爬山算法?

在Python中使用Levenshtein距离作为启发式生成字符串的爬山算法?,python,string,algorithm,levenshtein-distance,hill-climbing,Python,String,Algorithm,Levenshtein Distance,Hill Climbing,我一直在关注这一点,我被他们的一个自我检查问题困住了,问题是这样的: 自我检查 这是一个自我检查,涵盖了目前为止的所有内容。你可能有 听说过无限猴子定理吗?这个定理说明猴子 在打字机键盘上随意敲击键盘,可获得无限量 当然,时间几乎肯定会键入给定的文本,例如完整的 威廉·莎士比亚的作品。好吧,假设我们用一只猴子代替一只猴子 Python函数。你认为一条Python需要多长时间 函数只生成莎士比亚的一句话?判决 我们要拍的是:“我觉得它像只黄鼠狼” 你不会想在浏览器中运行这个,所以启动它 您最喜欢的

我一直在关注这一点,我被他们的一个自我检查问题困住了,问题是这样的:

自我检查

这是一个自我检查,涵盖了目前为止的所有内容。你可能有 听说过无限猴子定理吗?这个定理说明猴子 在打字机键盘上随意敲击键盘,可获得无限量 当然,时间几乎肯定会键入给定的文本,例如完整的 威廉·莎士比亚的作品。好吧,假设我们用一只猴子代替一只猴子 Python函数。你认为一条Python需要多长时间 函数只生成莎士比亚的一句话?判决 我们要拍的是:“我觉得它像只黄鼠狼”

你不会想在浏览器中运行这个,所以启动它 您最喜欢的Python IDE。我们模拟的方法是编写一个 函数生成一个长度为27个字符的字符串 从字母表中的26个字母加上 空间我们将编写另一个函数,对生成的每个函数进行评分 将随机生成的字符串与目标进行比较

第三个函数将重复调用generate和score,如果100% 这些字母中有一个是正确的,我们完成了。如果字母不正确 然后,我们将生成一个全新的字符串。以便更容易理解 你的程序的进度第三个函数应该打印出最好的结果 到目前为止生成的字符串及其每1000次尝试的分数

自我检查挑战

在自检中查看您是否可以通过保持 正确的字母,最好只修改一个字符 到目前为止。这是“hill”类中的一种算法 “爬山”算法,也就是说,我们只保留更好的结果 比前一个好

我编写了一些代码,使用生成的字符串和需要的字符串之间的Levenshtein距离来完成此挑战的第一部分

import random, string, nltk

def string_generator(length, collection):
    """
    takes all characters in collection and generates a string of size length.
    """
    return ''.join([random.choice(collection) for _ in xrange(length)])

def string_tester(output, text):
    """
    compares strings given and returns the Levenshtein distance.
    """
    return nltk.metrics.edit_distance(output, text)

if __name__ == '__main__':
    collection = [x for x in (string.ascii_lowercase + ' ')]
    longest_distance = 27
    best_string = None
    ctr = 0
    while True:
        random_string = string_generator(26, collection)
        distance = string_tester(random_string, "methinks it is like a weasel")
            ctr += 1
        ctr %= 1000
            if distance < longest_distance:
            best_string = random_string
            longest_distance = distance
            # end if the string generated is same as the one given
        if longest_distance == 0:
            print best_string
            print longest_distance
            break
            # use the best string to generate a better string every 1000th time
        if ctr == 0:
            print longest_distance
            print best_string
            # TODO: optimization here
我不知道如何在TODO时生成更好的字符串——在迭代之前使用最好的字符串和给定的方法

tl;dr:我如何编写一个爬山算法,使用Levenshtein距离作为启发,直到它生成特定的字符串?请概述过程

target_word = "hello world"
target_size = len(target_word)
alphabet = "abcdefghijklmnopqrstuvwxyz "
def make_guess(alphabet,size):
   return "".join(random.choice(alphabet) for _ in range(size))

guess = make_guess(alphabet,target_size)

for i in itertools.count(0):
   if guess == target_word:
      break;
   if not i % 1000:
      print "Best So Far:",guess
   #climb hill and replace our guess if our next guess is better
   guess = min(guess,make_guess(alphabet,target_size),key=lambda _guess:levenstein(_guess,target_word))
print "Final Guess:",guess
这被称为爬山,因为只有在下一个潜在解决方案更好时,潜在解决方案才会被替换。这可能会导致其他类型的问题陈述出现问题,在这些问题陈述中,您会发现性能相对较好的局部最大值或最小值,但您会错过全局最大值或最小值

这被称为爬山,因为只有在下一个潜在解决方案更好时,潜在解决方案才会被替换。这可能会导致其他类型的问题陈述出现问题,在这些问题陈述中,您会发现性能相对较好的局部最大值或最小值,但您会错过全局最大值或最小值参见:

这本书为我提供了有关IA算法、优化和启发式的示例和完整程序,所有这些都是IA算法,包括爬山算法。

请参阅:


本书为我提供了IA算法、优化和启发式的示例和完整程序,包括爬山算法。

这是爬山的完整解决方案,只需不到100次迭代

import string
import random

def randomGen(goalList):
    characters = string.ascii_lowercase+" "
    randString =""
    for i in range(len(goalList)):
        randString = randString+characters[random.randrange(len(characters))]
    randList = [randString[i] for i in range(len(randString))]
    return randList

def scoreRand(goalList,randList):
    numScore = 0
    for i in range(len(goalList)):
        if goalList[i] == randList[i]:
            numScore = numScore+1
    return numScore / len(goalList)

def common_elements(clist,list1, list2):
    for i in range(len(list1)):
        if list1[i] == list2[i]:
            clist[i] = list1[i]
    return clist

def main():
    goal = "methinks it is like a weasel"
    goalList = [goal[i] for i in range(len(goal))]
    clist = [' ' for i in range(len(goal))]
    randList = randomGen(goalList)
    clist = common_elements(clist,goalList, randList)
    score = scoreRand(goalList,clist)
    totalIteration = 0
    while(score < 1):
        newrandList = randomGen(goalList)
        newclist = common_elements(clist,goalList, randList)
        newscore = scoreRand(goalList,clist)
        score = newscore
        randList = newrandList
        clist = newclist
        totalIteration = totalIteration+1
        print(score," : ",''.join(clist))
    print("Total iterations: ",totalIteration)

main()

这是爬山的完整解决方案,只需不到100次迭代

import string
import random

def randomGen(goalList):
    characters = string.ascii_lowercase+" "
    randString =""
    for i in range(len(goalList)):
        randString = randString+characters[random.randrange(len(characters))]
    randList = [randString[i] for i in range(len(randString))]
    return randList

def scoreRand(goalList,randList):
    numScore = 0
    for i in range(len(goalList)):
        if goalList[i] == randList[i]:
            numScore = numScore+1
    return numScore / len(goalList)

def common_elements(clist,list1, list2):
    for i in range(len(list1)):
        if list1[i] == list2[i]:
            clist[i] = list1[i]
    return clist

def main():
    goal = "methinks it is like a weasel"
    goalList = [goal[i] for i in range(len(goal))]
    clist = [' ' for i in range(len(goal))]
    randList = randomGen(goalList)
    clist = common_elements(clist,goalList, randList)
    score = scoreRand(goalList,clist)
    totalIteration = 0
    while(score < 1):
        newrandList = randomGen(goalList)
        newclist = common_elements(clist,goalList, randList)
        newscore = scoreRand(goalList,clist)
        score = newscore
        randList = newrandList
        clist = newclist
        totalIteration = totalIteration+1
        print(score," : ",''.join(clist))
    print("Total iterations: ",totalIteration)

main()

谢谢你提醒我爬山是什么。似乎我还需要做一些额外的工作,随机生成一个大字符串,而不仅仅是爬山这就是你在这里所做的。。。顺便说一句,你的编辑是正确的,最后这个算法会到达那里。。。我认为这表明,每次随机挑选一个字符串并不是完成这项任务的好方法,可能需要很长时间才能找到正确的单词,我认为这个问题更适合于遗传算法。计算当前最好的字符串几乎肯定会快得多,每次超过5分钟,11个字符随机猜测新字符串,还有3个不匹配的字母提示我爬山是什么。似乎我还需要做一些额外的工作,随机生成一个大字符串,而不仅仅是爬山这就是你在这里所做的。。。顺便说一句,你的编辑是正确的,最后这个算法会到达那里。。。我认为这表明,每次随机挑选一个字符串并不是完成这项任务的好方法,可能需要很长时间才能找到正确的单词,我认为这个问题更适合于遗传算法。计算当前最好的字符串几乎肯定会快得多,每次超过5分钟,11个字符随机猜测新字符串,仍然有3个不匹配的字母