SATã½ã«ããä½ãä¼ (1)
é©å½ã«ã¾ã£ããã¨ãä»åã¯ä¸æºåã¿ãããªãã®ã ãã§ãã
å ¥å
ãã£ãããªã®ã§ãã¼ã¿å½¢å¼ã¯ SAT Competitions ã®å½¢å¼ã¨æãã¦ããããã¨æãã¾ãããåºãããããªãã®ã¯ã¨ã¦ãä½ããªãã§ããã©ãæ¯è¼ããæã«ãã®æ¹ã便å©ããã
ã¾ããå ¥åã¯Conjunctive Normal Formã®è«çå¼ã§ä¸ããã¨ã®ãã¨ã
(x1 or !x5 or x4) and (!x1 or x5 or x3 or x4) and (!x3 or !x4)
ãããããããå¤æ°ãå¤æ°ã®å¦å® (= ãªãã©ã«)ããorã§ç¹ãã ãã® (= é¸è¨ç¯)ããandã§ç¹ãã ãã®ãã¨ããå½¢ã®å¼ã§ãããã¡ã¤ã«å½¢å¼ã¨ãã¦ã¯ãDIMACSå½¢å¼ã¨ããã®ã§ä¸ãããããããããããªããã¹ããã¡ã¤ã«ã§ãã
c c ã³ã¡ã³ãã c p cnf 5 3 1 -5 4 0 -1 5 3 4 0 -3 -4 0
- æåã«ä½è¡ãã³ã¡ã³ã (c XXXXX)
- 次ã«ãããçãªãã® (p cnf å¤æ°ã®åæ° é¸è¨ç¯ã®æ°)
- 以ä¸ãä¸è¡ã«ä¸åã®é¸è¨ç¯ãã¹ãã¼ã¹åºåãã®æ´æ°åã§ã
- æ£ã®æ°ã¯notãã¤ãã¦ãªãå¤æ°
- è² ã®æ°ã¯notãã¤ãã¦ãå¤æ°
- ã¼ãã¯é¸è¨ç¯ã®çµãã
åºå
åºåã¯ãè«çå¼ã true ã«ãããã¨ãã§ããå ´åã¯
s SATISFIABLE v 1 -2 3 -4 -5 0
ã®ããã«ãã¦ããã¨ãã° x1,x3 ãtrueã«ã㦠x2,x4,x5 ãfalseã«ããã°OKãã¨ããä¾ãæ¨æºåºåã«åºãã¾ããè¤æ°ã®trueã«ããããããå ´åãã©ããï¼ã¤åºãã°ããã§ããåæã«ãå®è¡ãã¡ã¤ã«ã®çµäºã³ã¼ãã¨ã㦠10 ãè¿ãã¾ãã
åºåã¯ãè«çå¼ã true ã«ãããã¨ãã§ããªãå ´åã¯ã
s UNSATISFIABLE
ã ãã§ãããå®è¡ãã¡ã¤ã«ã®çµäºã³ã¼ãã¨ã㦠20 ãè¿ãã
ã³ã³ãã¹ãã®ããã«æéå¶éãããå ´åãæéåãçã§ã©ã¡ãã¨ãããããªãã£ãå ´åã¯ã
s UNKNOWN
ã§ãçµäºã³ã¼ãã¨ã㦠0 ãè¿ããã¨ããããããã¯èªåã«ã¯é¢ä¿ãªãããªã
Take 1 : å®å ¨ã«å ¨æ¢ç´¢
ã¾ãã¯ã¦ã©ã¼ã ã¢ããã¨ãã¦ãå ¨ã¦ã®å¤æ°å²ãå½ã¦ãã¿ã¼ã³ãç·å½ããã§è©¦ãã¦ã¿ãã½ã«ããæ¸ãã¦ã¿ã¾ãããä»ã®ã¨ããDè¨èªã使ã£ã¦ãã¾ãã
import std.stdio; import std.stream, std.cstream; import std.string; import std.conv; class SAT { private: alias int Literal; /// éã¼ãæ´æ°ã+n 㯠xnã-n 㯠!xn ã表ã int varOf( Literal lit ) { return (lit>0 ? lit-1 : -lit-1); } bool isPositive( Literal lit ) { return (lit>0); } alias Literal[] Clause; /// [-1,+2,+3] ã !x1|x2|x3 ã表ã alias Clause[] CNF; /// [[-1,+2],[+3,-2]] 㧠(!x1|x2)&(x3|!x2) ã表ã private: int numVar; /// å¤æ°ã®åæ° CNF cnf; /// è«çå¼ public: /// DIMACS format ã®å ¥åã¹ããªã¼ã ããé©å½ã«èªã¿è¾¼ã¿ this( InputStream sin ) { foreach(char[] s; sin) if( s.length && s[0]!='c' ) if( s[0] == 'p' ) numVar = to!(int)( (s.idup.split)[2] ); else cnf ~= to!(int[])( (s.idup.split)[0..$-1] ); } /// ããããã¯ãã«ã§å¤æ°ã¸ã®å¤å²ãå½ã¦ãä¸ãã¦è©ä¾¡ bool eval(BitVec)( BitVec bv ) { bool be = true; foreach(clause; cnf) { bool bc = false; foreach(lit; clause) { static if( is(bv[0]) ) bool bl = bv[varOf(lit)]; else bool bl = !!((bv>>varOf(lit))&1); bc |= isPositive(lit) ? bl : !bl; } be &= bc; } return be; } } bool solve( SAT s ) { long MASK = (1L << s.numVar) - 1; B_LOOP: for(long B=0; B<=MASK; ++B) if( s.eval(B) ) { // Satisfied writeln("s SATISFIABLE"); write("v"); for(int i=0; i<s.numVar; ++i) write(" ", (B>>i)&1 ? i+1 : -i-1); writeln(" ", 0); return true; } // Not satisfied writeln("s UNSATISFIABLE"); return false; } int main() { auto s = new SAT(din); return solve(s) ? 10 : 20; }
ãã¦ããããæä½ã©ã¤ã³ã®ããã©ã¼ãã³ã¹ã¨è¨ããã¨ã«ãªãã¾ããã©ã®ãããã®ã¹ãã¼ãããªã¼ã
20å¤æ°85ç¯ã®3-CNFï¼åé¸è¨èª¬ã®ãªãã©ã«æ°ãå ¨é¨3ã®ãã®ï¼ã©ã³ãã ãã¼ã¿ãä½ã£ã¦è©¦ãã¦ã¿ã¾ãããè²ã 試ãã¦ã¿ãã¨ãããç¯æ°ãããããæ¸ããã¨SATISFIABLEã ãããããããå¢ããã¨UNSATISFIABLEã ããã«ãªã£ã¦ãã¾ããããªã®ã§ãæ¯è¼å¯¾è±¡ã¯PicoSATã§ãã
<picosat> s SATISFIABLE v -1 2 3 -4 -5 6 7 8 9 -10 11 12 13 -14 15 -16 17 -18 19 20 0 [10] : 99 ms <hzkrsat> s SATISFIABLE v 1 2 -3 -4 5 -6 7 8 -9 10 -11 12 -13 14 -15 16 -17 -18 19 -20 0 [10] : 5977 ms
ã¨ãã£ãã¨ããããã¡ããããã£ã¨å¤§ããå ¥åãå°ãããã¨ã©ãã©ãå·®ã¯éãã¦ããã¾ããã25å¤æ°105ç¯ã ã¨â¦
<picosat> s SATISFIABLE v 1 -2 3 -4 5 6 7 -8 -9 -10 11 -12 -13 -14 -15 -16 -17 18 19 20 -21 22 -23 -24 v 25 0 [10] : 105 ms <hzkrsat> s SATISFIABLE v -1 2 -3 4 5 6 -7 -8 -9 10 -11 -12 -13 -14 -15 -16 17 18 19 -20 21 -22 -23 24 - 25 0 [10] : 222315 ms
ã¨ããããã§ã次åããè²ã 試ãã¦æ¹åãã¦ãããããããªã¼ã¨æãã¾ãã
éè«
ããããã°ãå¤æ°ã¨ç¯æ°ã®æ¯ã4.4898ãè¶ ããã¨ã»ã¼ç¢ºå®ã«UNSATISFIABLEã¨ããè«æãåã«èªãã§ãã¸ã¼ï¼ãã¨æã£ã¦ããã®ãæãåºãã¾ããã確ãã«èªåã§æã§å®é¨ãã¦ã¿ãã¨ãã®è¾ºãã«å¢ãããã¾ãããé¢ç½ãã£ãã§ãã
ã°ã°ã£ã¦ã¿ãã¨ãã¤ãããã®SATã½ã«ãã¯åºæ¬çã« DPLL ã¨ããæ çµã¿ã§è§£ãã¦ãããããã次ã¯ãã®è¾ºããã¡ãã£ã¨èª¿ã¹ã¦ã¿ãããã¨æãã¾ããäºå®ã¯æªå®ã§ãã