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