Advertisement
partyboy1a

SAT-solver-framework.lua

Jan 29th, 2013
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function deepcopy(v)
  2.     if(type(v)=="table") then
  3.         local t = {}
  4.         local key, val
  5.         for key, val in pairs(t) do
  6.             t[key] = deepcopy(val)
  7.         end
  8.         return t
  9.     else
  10.         return v
  11.     end
  12. end
  13.  
  14. total_number_of_variables = 0
  15.  
  16. Var = {}
  17. pvar = {}
  18. num_to_var = {}
  19. function NewVar(name, entries, print_entries)
  20.     if print_entries==nil then print_entries=true end
  21.     assert(print_entries == true or print_entries == false or
  22.         print_entries == "true" or print_entries == "false",
  23.         "print_entries was wrong! (Maybe you wanted NewVar("..
  24.         name..",{"..tostring(entries)..","..tostring(print_entries).."})   ?")
  25.  
  26.     local tab = {}
  27.     local ctab, ulim
  28.     if type(entries)=="table" then
  29.         temp = {}
  30.         for i=0,#entries do
  31.             temp[i] = 1
  32.         end
  33.         while(true) do
  34.             ctab = tab
  35.             for i=1,#entries-1 do
  36.                 if type(ctab[temp[i]])=="nil" then ctab[temp[i]]={} end
  37.                 ctab = ctab[temp[i]]
  38.             end
  39.             for j=1,entries[#entries] do
  40.                 total_number_of_variables = total_number_of_variables + 1
  41.                 ctab[j] = total_number_of_variables
  42.                
  43.                 local temp2 = {}
  44.                 for i=1,#entries-1 do temp2[i]=temp[i] end
  45.                 temp2[#entries] = j
  46.                 num_to_var[total_number_of_variables] = {
  47.                     name = name, entry = temp2
  48.                 }
  49.             end
  50.             temp[#entries-1] = temp[#entries-1] + 1
  51.            
  52.             ulim = #entries-1
  53.             while(ulim > 0 and temp[ulim] > entries[ulim]) do
  54.                 temp[ulim] = 1
  55.                 ulim = ulim - 1
  56.                 temp[ulim] = temp[ulim] + 1
  57.             end
  58.             if ulim == 0 then break end
  59.         end
  60.         Var[name] = tab
  61.     elseif type(entries)=="number" then
  62.         for i=1,entries do
  63.             total_number_of_variables = total_number_of_variables + 1
  64.             tab[i]= total_number_of_variables
  65.             num_to_var[total_number_of_variables] = {
  66.                 name = name, entry = i
  67.             }
  68.         end
  69.         Var[name] = tab
  70.     elseif type(entries)=="nil" then
  71.         total_number_of_variables = total_number_of_variables + 1
  72.         Var[name] = total_number_of_variables
  73.         num_to_var[total_number_of_variables] = {
  74.             name = name
  75.         }
  76.     end
  77.     pvar[name] = print_entries
  78. end
  79.  
  80. total_number_of_clauses = 0
  81. clause = {}
  82.  
  83. function CheckClause(cl)
  84.     assert(type(cl) == "table",
  85.             "ERROR: cl should be a table")
  86.  
  87.     assert(#cl > 0, "ERROR: inserting an empty table! (pretty pointless, it's never solvable)")
  88.     for i=1,#cl,2 do
  89.         assert(type(cl[i]) == "number",
  90.             "ERROR: cl["..i.."]="..tostring(cl[i])..", but should be a number")
  91.         assert(type(cl[i+1]) == "boolean",
  92.             "ERROR: cl["..(i+1).."]="..tostring(cl[i+1])..", but should be true or false")
  93.     end
  94. end
  95.  
  96. function AddSimpleClause(cl)
  97.     total_number_of_clauses = total_number_of_clauses + 1
  98.     CheckClause(cl)
  99.     clause[total_number_of_clauses] = cl
  100. end
  101.  
  102. function AddIfThenClause(str_if, cl1, str_then, cl2)
  103.     assert(str_if=="if" or str_if=="if ALL" or str_if=="if ONE",
  104.         "bad argument for str_if, it is "..str_if..", but must be"..
  105.         "\n  if"..
  106.         "\nOR"..
  107.         "\n  if ALL"..
  108.         "\nOR"..
  109.         "\n  if ONE")
  110.     assert(str_then=="then" or str_then=="then ALL" or str_then=="then ONE",
  111.         "bad argument for str_then, it is "..str_then..", but must be"..
  112.         "\n  then"..
  113.         "\nOR"..
  114.         "\n  then ALL"..
  115.         "\nOR"..
  116.         "\n then ONE")
  117.  
  118.     CheckClause(cl1)
  119.     CheckClause(cl2)
  120.  
  121.     local invert_cl1 = {}
  122.     for i=1,#cl1,2 do
  123.         invert_cl1[i] = cl1[i]
  124.         invert_cl1[i + 1] = not cl1[i + 1]
  125.     end    
  126.  
  127.     if str_if=="if" or str_if=="if ALL" then
  128.        
  129.         if str_then=="then" or str_then=="then ALL" then
  130.  
  131.             for i=1,#cl2,2 do
  132.                 local t = {}
  133.                 for j=1,#invert_cl1 do
  134.                     t[j] = invert_cl1[j]
  135.                 end
  136.                 t[#t+1] = cl2[i]
  137.                 t[#t+1] = cl2[i+1]
  138.                 AddSimpleClause(t)
  139.             end
  140.  
  141.         elseif str_then=="then ONE" then
  142.  
  143.             local t = {}
  144.             for j=1,#invert_cl1 do
  145.                 t[j] = invert_cl1[j]
  146.             end
  147.             for j=1,#cl2 do
  148.                 t[#t+1] = cl2[j]
  149.             end
  150.             AddSimpleClause(t)
  151.         end
  152.  
  153.     elseif str_if=="if ONE" then
  154.        
  155.         if str_then=="then" or str_then=="then ALL" then
  156.  
  157.             for i=1,#invert_cl1,2 do for j=1,#cl2,2 do
  158.                 AddSimpleClause{
  159.                     invert_cl1[i], invert_cl1[i+1],
  160.                     cl2[j], cl2[j+1]}
  161.             end end
  162.  
  163.         elseif str_then=="then ONE" then
  164.  
  165.             for i=1,#invert_cl1,2 do
  166.                 local t = {invert_cl1[i], invert_cl1[i+1]}
  167.                 for j=1,#cl2 do
  168.                     t[#t+1] = cl2[j]
  169.                 end
  170.                 AddSimpleClause(t)
  171.             end
  172.  
  173.         end
  174.     end
  175. end
  176.  
  177. function AddIfAndOnlyIfClause(str_cl1, cl1, str_ifandonlyif, str_cl2, cl2)
  178.     assert(str_cl1=="ONE of" or str_cl1=="ALL of",
  179.         "str_cl1 not specified, must be"..
  180.         "\n   ONE of"..
  181.         "\nOR"..
  182.         "\n   ALL of")
  183.     assert(str_cl2=="ONE of" or str_cl2=="ALL of",
  184.         "str_cl2 not specified, must be"..
  185.         "\n   ONE of"..
  186.         "\nOR"..
  187.         "\n   ALL of")
  188.     assert(str_ifandonlyif=="if and only if",
  189.         "str_ifandonlyif must be exactly the following string:"..
  190.         "\n   if and only if")
  191.    
  192.     CheckClause(cl1)
  193.     CheckClause(cl2)
  194.    
  195.     if str_cl1=="ALL of" then
  196.         if str_cl2=="ALL of" then
  197.             AddIfThenClause("if ALL", cl1, "then ALL", cl2)
  198.             AddIfThenClause("if ALL", cl2, "then ALL", cl1)
  199.         elseif str_cl2=="ONE of" then
  200.             AddIfThenClause("if ALL", cl1, "then ONE", cl2)
  201.             AddIfThenClause("if ONE", cl2, "then ALL", cl1)
  202.         end
  203.     elseif str_cl1=="ONE of" then
  204.         if str_cl2=="ALL of" then
  205.             AddIfThenClause("if ONE", cl1, "then ALL", cl2)
  206.             AddIfThenClause("if ALL", cl2, "then ONE", cl1)
  207.         elseif str_cl2=="ONE of" then
  208.             AddIfThenClause("if ONE", cl1, "then ONE", cl2)
  209.             AddIfThenClause("if ONE", cl2, "then ONE", cl1)
  210.         end    
  211.     end
  212. end
  213.  
  214. function UnitClause(var, bool)
  215.     AddSimpleClause{var, bool}
  216. end
  217.  
  218. function NewClause()
  219.     return {}
  220. end
  221.  
  222. function ExtendClause(cl, var, bool)
  223.     assert(type(var)=="number", "var=="..tostring(var).." but should be a number")
  224.     assert(type(bool)=="boolean", "bool=="..tostring(bool).." but should be true or false")
  225.     cl[#cl + 1] = var
  226.     cl[#cl + 1] = bool
  227. end
  228.  
  229. function WriteSATfile()
  230.     file = io.open("satfile.cnf", "w")
  231.     file.write(file, "p cnf "..total_number_of_variables.." "..total_number_of_clauses.."\n")
  232.     local s = ""
  233.     for i=1,total_number_of_clauses do
  234.         s = ""
  235.         local j = 1
  236.         while(clause[i][j] ~= nil and clause[i][j+1] ~= nil) do
  237.             if not clause[i][j+1] then s = s .. "-" end
  238.             s = s .. clause[i][j] .. " "
  239.             j = j + 2
  240.         end
  241.         file.write(file, s.."0\n")
  242.     end
  243.     file.close(file)   
  244. end
  245.  
  246. function ParseSolution()
  247.     file = io.open("solutionfile", "r")
  248.     Sol = {}
  249.     local s, lin
  250.     for lin in file.lines(file) do for s in string.gmatch(lin, "[%d%-]+") do
  251.         local b
  252.         s = s + 0
  253.         if s > 0 then
  254.             b = true
  255.         elseif s < 0 then
  256.             b = false
  257.             s = -s
  258.         else
  259.             break
  260.         end
  261.    
  262.         local con = num_to_var[s]
  263.         local name = con.name
  264.         local entry = con.entry
  265.         if type(entry)=="nil" then
  266.             Sol[name] = b
  267.         elseif type(entry)=="number" then
  268.             entry = entry + 0
  269.             if type(Sol[name])=="nil" then
  270.                 Sol[name] = {}
  271.             end
  272.             Sol[name][entry] = b
  273.         elseif type(entry)=="table" then
  274.             if type(Sol[name])=="nil" then
  275.                 Sol[name] = {}
  276.             end
  277.             local v = Sol[name]
  278.             for j = 1, #entry - 1 do
  279.                 if type(v[entry[j]])=="nil" then
  280.                     v[entry[j]] = {}
  281.                 end
  282.                 v = v[entry[j]]
  283.             end
  284.             v[entry[#entry]] = b
  285.         end
  286.     end end
  287. end
  288.  
  289. function PrintSolution()
  290.  
  291.     local function PrintVar(s, v, p)
  292.         if p==false then return end
  293.         if type(v)=="number" then
  294.             print(s..": ".." unknown")
  295.         elseif type(v)=="boolean" then
  296.             if p==nil or p==true or tostring(v)==tostring(p) then print(s..": "..tostring(v)) end
  297.         elseif type(v)=="table" then
  298.             for key, val in pairs(v) do
  299.                 PrintVar(s.."["..key.."]", val, p)
  300.             end
  301.         end
  302.     end
  303.     for key, val in pairs(Sol) do
  304.         PrintVar(key, val, pvar[key])
  305.     end
  306. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement