% Copyright (C) 2013, 2017 Peter Schueller #script (lua) function args(t) return t:args() end function name(t) return t:name() end function contains(term,item) for k,v in pairs(term:args()) do if tostring(v)==tostring(item) then return 1 end end return 0 end function concat(t) local res = "" for k,v in pairs(t:args()) do res = res .. tostring(v) end if res ~= "" then return res else return {} end end function argumentsAsSet(t) local res = "" for k,v in pairs(t:args()) do res = res .. "," .. tostring(v) end if res ~= "" then return "\\{" .. string.sub(res,2) .. "\\}" else return "\\{\\}" end end #end. % set library % construct empty set: @set() % construct one-element set: @set(elem1) % construct multi-element set: @set((elem1,elem2,elem3)) % set union: @setunion(S1,S2) % set union: @setintersection(S1,S2) % set member: @setintersection(S1,S2) % set to string conversion: @settostring(S) % set comparison: S1 == S2, S1 != S2, S1 < S2, ... #script (lua) -- transforms a lua table -- { [string_of_setmember] = Val_of_setmember, ... } -- that represents a set into a sorted lua table -- { [0] = Val_of_setmember, [1] = ... } function sethelperAssocToSortedIArray(assoctable) -- first sort the strings we use as indices a = {} for k, n in pairs(assoctable) do table.insert(a, k) end table.sort(a) -- now put the Val s corresponding to indices into b b = {} for k, n in ipairs(a) do table.insert(b,assoctable[n]) end return b end function set(elem) if elem == nil then return gringo.Fun("set") else local elements = {} if #elem:args() == 0 then elements[1] = elem else for k,v in pairs(elem:args()) do elements[tostring(v)] = v end elements = sethelperAssocToSortedIArray(elements) end return gringo.Fun("set", elements) end end function setunion(s1,s2) local elements = {} if Val.type(s1) == Val.FUNC then -- TODO error if s1:name() is not 'set' for k,v in pairs(s1:args()) do elements[tostring(v)] = v end end if Val.type(s2) == Val.FUNC then -- TODO error if s2:name() is not 'set' for k,v in pairs(s2:args()) do elements[tostring(v)] = v end end elements = sethelperAssocToSortedIArray(elements) return Val.new(Val.FUNC, "set", elements) end function setintersection(s1,s2) local elements1 = {} if Val.type(s1) == Val.FUNC then -- TODO error if s1:name() is not 'set' for k,v in pairs(s1:args()) do elements1[tostring(v)] = v end end local elements2 = {} if Val.type(s2) == Val.FUNC then -- TODO error if s2:name() is not 'set' for k,v in pairs(s2:args()) do if elements1[tostring(v)] ~= nil then elements2[tostring(v)] = v end end end elements2 = sethelperAssocToSortedIArray(elements2) return Val.new(Val.FUNC, "set", elements2) end function setmember(elem,set) for k,v in pairs(set:args()) do if tostring(elem) == tostring(v) then return 1 end end return 0 end function settostring(t) -- TODO error if t:name() is not 'set' local res = "" for k,v in pairs(t:args()) do res = res .. "," .. tostring(v) end if res ~= "" then return "{" .. string.sub(res,2) .. "}" else return "{}" end end function setelement(set) local res = {} for k,v in pairs(set:args()) do table.insert(res,v) end return res end -- foo(G,ID,E) :- dep(G,ID,_,_,S), E = @setelement(S). -- foo(G,ID,@setelement(S)) :- dep(G,ID,_,_,S). #end. #script (lua) function valuesAsList(tbl) local ret = "" for k,v in pairs(tbl) do ret = ret .. "," .. tostring(v) end ret = string.sub(ret,2) return ret end function keysAsList(tbl) local ret = "" for k,v in pairs(tbl) do ret = ret .. "," .. tostring(k) end ret = string.sub(ret,2) return ret end function cident(s) local res = tostring(s) res = string.gsub(res,"%(","") res = string.gsub(res,"%)","") res = string.gsub(res,",","_") res = string.gsub(res," ","_") return res end function logtable(t) for k,v in pairs(t) do print(k,v) end end function map(func, array) local new_array = {} for i,v in ipairs(array) do new_array[i] = func(v) end return new_array end function filterPred(pred,model) local result = {} for i,v in pairs(model:atoms()) do if v:name() == pred then table.insert(result, v:args()) end end return result end function printGraph(m,graph) local gid = graph print("digraph witness {") print("layout=dot;") -- get nodes local nodes = {} for i,node in pairs(filterPred("gn",m)) do if gid == node[1] then local n = node[2] local nid = cident(n) nodes[nid] = { ["aspnid"] = n, ["type"] = {}, ["attr"] = {} } end end -- get properties for i,prop in pairs(filterPred("gp",m)) do if gid == prop[1] then local nid = cident(prop[2]) local name = tostring(prop[3]) local setelement = tostring(prop[4]) if nodes[nid][name] == nil then nodes[nid][name] = { [setelement] = 1 } else nodes[nid][name][setelement] = 1 end end end -- print error messages local msg = "" for i,err in pairs(filterPred("error",m)) do msg = msg .. "\\n" .. tostring(err[1]) .. " " .. tostring(err[2]) end if msg ~= "" then print("{ rank=min; error [shape=rectangle,style=filled,color=red,label=\"" .. string.sub(msg,3) .. "\"]; }") end -- print nodes for nid,data in pairs(nodes) do local nstr = nid .. "[shape=rectangle" local label = "" -- label = label .. tostring(data["aspnid"]) .. " " nstr = nstr .. ",tooltip=\"" .. tostring(data["aspnid"]) .. "\"" if data["type"]["dep"] == 1 then nstr = nstr .. ",color=white" elseif data["type"]["nom"] == 1 then nstr = nstr .. ",style=filled,color=lightblue" label = label .. keysAsList(data["name"]) .. "(E)" elseif data["type"]["act"] == 1 then nstr = nstr .. ",style=filled,color=orange" label = label .. keysAsList(data["name"]) .. "(A)" elseif data["type"]["mod"] == 1 then nstr = nstr .. ",style=filled,color=green" label = label .. keysAsList(data["name"]) .. "(M)" end -- attr local attrstr = keysAsList(data["attr"]) if #attrstr > 0 or data["type"]["dep"] == 1 then label = label .. " \\{" .. attrstr .. "\\}" end label = ",label=\"" .. label .. "\"" -- print print(nstr .. label .. "];") end -- print edges for i,edge in pairs(filterPred("ge",m)) do if gid == edge[1] then local fromid = cident(edge[2]) local toid = cident(edge[3]) if nodes[fromid]["attr"]["meta"] == 1 then print(fromid .. " -> " .. toid .. " [style=dashed];") elseif nodes[toid]["attr"]["meta"] == 1 then print(fromid .. " -> " .. toid .. " [style=dashed,arrowhead=none];") elseif nodes[toid]["type"]["dep"] == 1 then print(fromid .. " -> " .. toid .. " [arrowhead=none];") else print(fromid .. " -> " .. toid .. ";") end end end -- print extra messages local msg = "" for i,message in pairs(filterPred("print",m)) do msg = msg .. "\\n" .. tostring(message[1]) end if msg ~= "" then print("{ rank=source; msg [shape=rectangle,label=\"" .. string.sub(msg,3) .. "\"]; }") end -- finish graph print("}") end function onModel(m) -- normal model printing -- print(table.concat(map(tostring, m:atoms()), ",")) for i,graph in pairs(filterPred("gprint",m)) do printGraph(m,graph[1]) end end function main(prg) prg:ground({{"base", {}}}) return prg:solve(nil,onModel) end #end. % translating graph input into graph processor concepts concept(G,ID,nom,Name) :- nom(G,ID,Name). concept(G,ID,act,Name) :- act(G,ID,Name). concept(G,ID,mod,Name) :- mod(G,ID,Name). gn(G,ID) :- concept(G,ID,_,_). gp(G,ID,name,Name) :- concept(G,ID,_,Name). gp(G,ID,type,Type) :- concept(G,ID,Type,_). gn(G,ID) :- dep(G,ID,_,_,_). gp(G,ID,type,dep) :- dep(G,ID,_,_,_). gp(G,ID,attr,@setelement(Attrib)) :- dep(G,ID,_,_,Attrib). ge(G,FromID,ID) :- dep(G,ID,FromID,_,_). ge(G,ID,ToID) :- dep(G,ID,_,ToID,_). graph(G) :- gn(G,_). % graph library: % % gn(GraphID,NodeID): % define graph node % % gp(GraphID,NodeID,PropertyName,PropertyValue): % define node property, properties can have multiple values (set semantics) % % ge(GraphID,NodeFromID,NodeToID): % define graph edge % % gcontract(Mod,Graph,Node1,Node2): % add "unify nodes Node1 and Node 2" to graph modification set (modset) Mod % % gremove(Mod,Graph,Node): % add "remove node Node" from graph modification set (modset) Mod % % gmodimport(IntoMod,FromMod): % add modifications in modset FromMod to modset IntoMod % % gimport(IntoGraphID,FromGraphID,NodeAdorn,Mod): % import one graph into another one, applying modset % * adorning node identifiers to create new node identifiers % * NodeAdorn allows to import graphs multiply % * imported node id becomes i(FromGID,FromNID,NodeAdorn) % gmod(Mod,Graph) :- gcontract(Mod,Graph,_,_). % assertion: modset is about just one graph error("invalid modset with multiple graphs (mod,g1,g2)", @concat((Mod," ",G1," ",G2))) :- gmod(Mod,G1), gmod(Mod,G2), G1