1#script (lua) 2 3function table.shallow_copy(t) 4 local t2 = {} 5 for k,v in pairs(t) do 6 t2[k] = v 7 end 8 return t2 9end 10 11function table.append(t, val) 12 t[#t + 1] = val 13end 14 15function table.get(t, key, def) 16 local val = t[key] 17 if val ~= nil then 18 return val 19 else 20 return def 21 end 22end 23 24function table.sort_unique(t) 25 local set = {} 26 for k, v in ipairs(t) do 27 set[tostring(v)] = v 28 end 29 local ret = {} 30 for k, v in pairs(set) do 31 table.append(ret, v) 32 end 33 table.sort(ret) 34 return ret 35end 36 37function table.map(t, f) 38 for k, v in ipairs(t) do 39 t[k] = f(v) 40 end 41 return t 42end 43 44function string.startswith(str, pre) 45 return string.sub(str, 1, string.len(pre)) == pre 46end 47 48function bool_to_num(var) 49 return var and 1 or 0 50end 51 52Function = clingo.Function 53Tuple = clingo.Tuple 54 55local Context = { } 56function Context:__index(key) 57 return Context[key] 58end 59 60function Context.new(reified) 61 local self = setmetatable({}, Context) 62 self.__reified = table.shallow_copy(reified) 63 return self 64end 65 66function Context:get() 67 return self.__reified 68end 69 70local Observer = { } 71Observer.__index = Observer 72 73function Observer.new() 74 local self = setmetatable({}, Observer) 75 self.__delayed = {} 76 self.__symbols = {} 77 self.__reified = {} 78 self.__terms = {} 79 self.__elems = {} 80 return self 81end 82 83function Observer:__index(name) 84 f = Observer[name] 85 if f == nil then 86 assert(not string.startswith(name, "_")) 87 return function (...) 88 table.append(self.__delayed, {name, {...}}) 89 end 90 else 91 return f 92 end 93end 94 95function Observer:__map(lit) 96 local sign = false 97 if lit < 0 then 98 sign = true 99 lit = -lit 100 end 101 local ret = table.get(self.__symbols, lit, Function("__aux")) 102 if sign then 103 ret = Function("neg", {ret}) 104 end 105 return ret 106end 107 108function Observer:__map_lits(t) 109 for k, v in ipairs(t) do 110 t[k] = self:__map(v) 111 end 112 return t 113end 114 115function Observer:__map_wlits(t) 116 for k, v in ipairs(t) do 117 t[k] = Tuple({self:__map(v[1]), v[2]}) 118 end 119 return t 120end 121 122function Observer:init_program(incremental) 123 table.append(self.__reified, Function("init_program", {bool_to_num(incremental)})) 124end 125 126function Observer:begin_step() 127 table.append(self.__reified, Function("begin_step", {})) 128end 129 130function Observer:_rule(choice, head, body) 131 head = table.sort_unique(self:__map_lits(head)) 132 body = table.sort_unique(self:__map_lits(body)) 133 table.append(self.__reified, Function("rule", {bool_to_num(choice), Tuple(head), Tuple(body)})) 134end 135 136function Observer:_weight_rule(choice, head, lower_bound, body) 137 head = table.sort_unique(self:__map_lits(head)) 138 body = table.sort_unique(self:__map_wlits(body)) 139 table.append(self.__reified, Function("weight_rule", {bool_to_num(choice), Tuple(head), lower_bound, Tuple(body)})) 140end 141 142function Observer:_minimize(priority, literals) 143 literals = table.sort_unique(self:__map_wlits(literals)) 144 table.append(self.__reified, Function("minimize", {priority, Tuple(literals)})) 145end 146 147function Observer:_project(atoms) 148 atoms = table.sort_unique(self:__map_lits(atoms)) 149 table.append(self.__reified, Function("project", {Tuple(atoms)})) 150end 151 152function Observer:output_atom(symbol, atom) 153 self.__symbols[atom] = symbol 154 table.append(self.__reified, Function("output_atom", {symbol})) 155end 156 157function Observer:_output_term(symbol, condition) 158 condition = table.sort_unique(self:__map_lits(condition)) 159 table.append(self.__reified, Function("output_term", {symbol, Tuple(condition)})) 160end 161 162function Observer:_output_csp(symbol, value, condition) 163 condition = table.sort_unique(self:__map_lits(condition)) 164 table.append(self.__reified, Function("output_csp", {symbol, value, Tuple(condition)})) 165end 166 167function Observer:_external(atom, value) 168 table.append(self.__reified, Function("external", {self:__map(atom), tostring(value)})) 169end 170 171function Observer:_assume(literals) 172 literals = table.sort_unique(self:__map_lits(literals)) 173 table.append(self.__reified, Function("assume", {Tuple(literals)})) 174end 175 176function Observer:_heuristic(atom, type, bias, priority, condition) 177 condition = table.sort_unique(self:__map_lits(condition)) 178 table.append(self.__reified, Function("heuristic", {self:__map(atom), tostring(type), bias, Tuple(condition)})) 179end 180 181function Observer:_acyc_edge(node_u, node_v, condition) 182 condition = table.sort_unique(self:__map_lits(condition)) 183 table.append(self.__reified, Function("acyc_edge", {node_u, node_v, Tuple(condition)})) 184end 185 186function Observer:theory_term_number(term_id, number) 187 self.__terms[term_id] = function() return number end 188end 189 190function Observer:theory_term_string(term_id, name) 191 self.__terms[term_id] = function() return Function(name) end 192end 193 194function Observer:theory_term_compound(term_id, name_id_or_type, arguments) 195 self.__terms[term_id] = function () 196 return Function(self.__terms[name_id_or_type]().name, table.map(arguments, function (i) 197 return self.__terms[i]() 198 end)) 199 end 200end 201 202function Observer:theory_element(element_id, terms, condition) 203 self.__elems[element_id] = function () 204 condition = table.sort_unique(self:__map_lits(condition)) 205 return Function("elem", {Tuple(table.map(terms, function (i) 206 return self.__terms[i]() 207 end)), Tuple(condition)}) 208 end 209end 210 211function Observer:_theory_atom(atom_id_or_zero, term_id, elements) 212 elements = table.sort_unique(table.map(elements, function (e) 213 return self.__elems[e]() 214 end)) 215 self.__symbols[atom_id_or_zero] = Function("theory", {self.__terms[term_id](), Tuple(elements)}); 216end 217 218function Observer:_theory_atom_with_guard(atom_id_or_zero, term_id, elements, operator_id, right_hand_side_id) 219 elements = table.sort_unique(table.map(elements, function (e) 220 return self.__elems[e]() 221 end)) 222 self.__symbols[atom_id_or_zero] = Function("theory", {self.__terms[term_id](), Tuple(elements), self.__terms[operator_id](), self.__terms[right_hand_side_id]()}); 223end 224 225function Observer:end_step() 226 table.append(self.__reified, Function("end_step", {})) 227end 228 229function Observer:finalize() 230 if unpack == nil then 231 unpack = table.unpack 232 end 233 for _, v in ipairs(self.__delayed) do 234 local name, args 235 name, args = v[1], v[2] 236 if string.startswith(name, "theory_atom") then 237 self["_" .. name](unpack(args)) 238 end 239 end 240 for _, v in ipairs(self.__delayed) do 241 local name, args 242 name, args = v[1], v[2] 243 if not string.startswith(name, "theory_atom") then 244 self["_" .. name](unpack(args)) 245 end 246 end 247 return Context.new(self.__reified) 248end 249 250function main(prg) 251 f = Function("f", {1}) 252 g = Function("g") 253 obs = Observer.new() 254 prg:register_observer(obs) 255 prg:ground({{"base", {}}}) 256 prg:solve{assumptions={{Function("b"), false}}} 257 ctx = obs:finalize() 258 prg:add("q", {}, "q(@get()).") 259 prg:ground({{"q", {}}}, ctx) 260 prg:solve() 261end 262 263#end. 264 265$x $= 1. 266$y $= 2. 267 2681 {a; b}. 269#minimize {1:a; 2:b}. 270#project a. 271#show x : a, b. 272#external a. 273#heuristic a : b. [1@2,sign] 274#edge (a,b) : a, b. 275 276#theory t { 277 term { + : 1, binary, left }; 278 &a/0 : term, any; 279 &b/1 : term, {=}, term, any 280}. 281a :- &a { 1+2,"test": a, b }. 282b :- &b(3) { } = 17. 283