今天听了一个关于 Boolean satisfiability solver 的讲座。wiki 了一下,说是 NP-complete。没学过 CS,不太清楚到底啥意思,反正就是用 exhaustive search 很 expensive 了。
有趣之处,在于如何避免 exhaustive search。
先把表达式表示成 conjunctive form(不太明白啥意思,有空可以 wiki 一下),然后可以找什么 pair 消去某个变量,缺点是表达式会变长,需要很多 memory。
还有个时间换空间的办法,类似于 binary tree based exhaustive search,每次检测到 conflict 就 traceback。
前面是60年代的算法,然后过了30年,有一个改进的版本。建一个 map,在遍历 tree 的时候,可以通过 constraints 来 force 某些变量的值。在 conflict 的时候,去分析那个 map,找到哪些变量取了哪些值,导致了这个 conflict,根据分析结果,添加一个 redundant constraint,然后,可以 traceback multiple levels。那个新的 constraint,可以避免以后很多无谓的 search。实际上,因为它是 redundant,完全可以从 theoretical analysis 得到。最有趣之处是它采用了类似 machine learning 的方法来学到新的 constraint。这个很像人脑解决问题的方法,摔倒了,学一下什么是坑,以后再看见坑就绕过了。而且比人脑强大的一点是,只要 memory 足够,就不会忘记。用在 AI 上面,那真是很强大了。
关于 search order,当变量很多的时候,随机选一些变量开始,可能 search 了很多步,都没有得到结果。这时候,有可能就是 lost 了,引入了太多无关的变量。可以直接返回到 root,再随机选一些新的变量开始search。之前的 search 并不是 wasting time,因为已经学到的 constraint 可以保留下来并且 guide future searches。
这些算法主要是用在 millions of variables 上面,比如检测大规模电路之类的。对于一些小的 application,可能 exhaustive search 就够用了。
不知道 sudoku 怎样,感觉跟这个问题很像,只不过是9元而不是 binary 的。假设可以对 sudoku 应用这个算法,那就跟人脑解题的步骤差不多了。先从显而易见的格子开始,通过某些 conflict,迅速确定某些格子的值。然后,再找某些更复杂的 conflict pattern,确定一部分值。剩下的(which is very rare,if you can identify complexy pattern in the previous step),就用 exhaustive search 了。不知道直接对 sudoku 用 exhaustive search 效果怎样,反正现在 PC 的 CPU 和 memory 都挺强大的,说不定可以直接解决了吧,大不了多 search 几层。