Package rubacon :: Package generators :: Module PrologGenerator
[hide private]
[frames] | no frames]

Source Code for Module rubacon.generators.PrologGenerator

  1  import sys, os, marshal 
  2  import copy 
  3   
  4  from VariableGenerator import * 
  5  from ..utility.helpers import get_attr_list_from_model, get_attrs_from_class 
  6  from networkx import * 
  7  from ..parsers.RuleParser import RuleParser 
  8   
  9   
 10  # Generate Prolog for verifying the constraints defined in the storage. 
11 -class PrologGenerator(object):
12 13 ___MODEL_STORAGE = "data/db.model" 14 ___INFO_STORAGE = "data/db.information" 15 16 17 # @ParamType aFilename 18 # Generate the code and write it to the given file.
19 - def generate(self, aFilename):
20 """Generate the prolog code and write it to the given file.""" 21 22 vg = unique_variable_generator 23 24 # Preload the model and info and open the file 25 # for writing. 26 inf = open(self.___INFO_STORAGE) 27 a = marshal.load(inf) 28 inf.close() 29 inf = open(self.___MODEL_STORAGE) 30 m = marshal.load(inf) 31 inf.close() 32 FILE = open(aFilename, "w") 33 34 # Write the atoms for each object first, e.g.: 35 # User('userName', 'name1') 36 for className in a.iterkeys(): 37 for o in a[className]: 38 first = True 39 FILE.write(className.lower() + "(") 40 keys = o.keys() 41 keys.sort() 42 for v in keys: 43 if not first: 44 FILE.write(", ") 45 FILE.write(o[v]) 46 first = False 47 FILE.write(").\n") 48 49 # The connecting attributes must be generated 50 # Get all dependencies: 51 for d in m['dependencyDefs']: 52 #print >> sys.stderr, d 53 # get the client: 54 for classDef in m['classDefs']: 55 if classDef['name'] == d[0]: 56 client = classDef 57 if classDef['name'] == d[1]: 58 supplier = classDef 59 # print >> sys.stderr, "Connection: %s -> %s" % (supplier['name'], client['name']) 60 ## Now write the connecting attribute: 61 FILE.write("%s_%s(" % (supplier['name'].lower(), client['name'].lower())) 62 supplier_pred = supplier['name'].lower() + "(" 63 client_pred = client['name'].lower() + "(" 64 # Get the supplier and write its attributes, 65 # save the mapping into a hash 66 mapping = {} 67 first = True 68 #print >> sys.stderr, "Supplier attrs" 69 #print >> sys.stderr, supplier['attrs'] 70 #print >> sys.stderr, "Client attrs" 71 #print >> sys.stderr, client['attrs'] 72 73 attrs = supplier['attrs'] 74 attrs.sort() 75 for attr in attrs: 76 v = vg.next() 77 mapping[attr] = v 78 if not first: 79 FILE.write(', ') 80 supplier_pred += ', ' 81 else: 82 first = False 83 FILE.write(v) 84 supplier_pred += v 85 86 # FILE.write(' || ') 87 # Now write the client attributes, but replace the ones with the same 88 # name by the same variable 89 first = True 90 attrs = client['attrs'] 91 attrs.sort() 92 for attr in attrs: 93 # We aleady have a var fof this 94 if attr in mapping: 95 v = mapping[attr] 96 else: 97 v = vg.next() 98 99 if not first: 100 client_pred += ', ' 101 else: 102 first = False 103 FILE.write(', ') 104 FILE.write(v) 105 client_pred += v 106 FILE.write(") :- %s), %s).\n" % (supplier_pred, client_pred)) 107 108 # Write out the predicates for the rules: 109 rules = RuleParser.getRulesFromStore() 110 # FIXME: add context mapping 111 predicateResolver = {} 112 alreadyInserted = [] 113 nameResolver = {} 114 # print >> sys.stderr, rules 115 for rule in rules: 116 print >> sys.stderr, rule['subrules'] 117 for subrule in rule['subrules']: 118 predicate = "" 119 ruleBody = "" 120 # print >> sys.stderr, rule 121 s = Signature(m, head=subrule['head'], target=subrule['target']) 122 bWrite = True 123 if s.predicate in alreadyInserted: 124 bWrite = False # This is different in the original code, chech if it works 125 alreadyInserted.append(s.predicate) 126 predicate += s.predicate.lower() + "(" 127 ruleBody += " :- " 128 currentSig = Signature(m, predicate=s.path[0]) 129 previousPredicate = currentSig.predicate 130 ruleBody += currentSig.predicate.lower() + "(" 131 lookupVarName = {} 132 133 for i in range(0, currentSig.get_arg_count()): 134 vn = vg.next() 135 predicate += vn 136 ruleBody += vn 137 lookupVarName[currentSig.predicate + "." + currentSig.get_attribute_name(i)] = vn 138 predicate += ", " 139 140 if (i < currentSig.get_arg_count() - 1): 141 ruleBody += ", " 142 143 for node in s.path[1:]: 144 currentSig = Signature(m, predicate=node) 145 ruleBody += "), " 146 ruleBody += currentSig.predicate.lower() + "(" 147 conName = self.__getConName(m, previousPredicate, currentSig.predicate) 148 print >> sys.stderr, "ConName: %s" % conName 149 conAttrName = lookupVarName[previousPredicate + "." + conName] 150 print >> sys.stderr, "ConAttrName: %s" % conAttrName 151 for i in range(0, currentSig.argCount): 152 currName = currentSig.get_attribute_name(i) 153 if conName == currName: 154 predicate += conAttrName 155 ruleBody += conAttrName 156 lookupVarName[currentSig.predicate + "." + currName] = conAttrName 157 else: 158 vn = vg.next() 159 predicate += vn 160 ruleBody += vn 161 lookupVarName[currentSig.predicate + "." + currName] = vn 162 if not (i == (currentSig.argCount - 1) and node == s.path[-1]): 163 predicate += ", " 164 if i < currentSig.argCount - 1: 165 ruleBody += ", " 166 previousPredicate = currentSig.predicate 167 168 predicate += ")" 169 ruleBody += ")." 170 predicateResolver[subrule['name']] = predicate 171 172 # FIXME: Write to the file 173 print >> sys.stderr, predicate + ruleBody 174 if bWrite: 175 FILE.write(predicate + ruleBody + "\n") 176 177 # The lookup for resolving names in constraints. 178 lookupVarName['HEAD'] = subrule['head'] 179 lookupVarName['TARGET'] = subrule['target'] 180 print >> sys.stderr, "nameRes: %s" % subrule['name'] 181 nameResolver[subrule['name']] = lookupVarName 182 183 # Now write the rule itself: 184 paramCount = len(rule['params']) 185 ruleText = "" 186 ruleText += rule['name'] 187 if paramCount > 0: 188 ruleText += "(" 189 190 paramResolver = {} 191 for i in range(0, paramCount): 192 nName = vg.next() 193 ruleText += nName 194 paramResolver[rule['params'][i]] = nName 195 # TODO: ContextMapping add mapping from PROLOG -> RuleName 196 if (i < paramCount - 1): 197 ruleText += ", " 198 if paramCount > 0: 199 ruleText += ")" 200 201 ruleText += " :- " 202 for key in predicateResolver.keys(): 203 p = predicateResolver[key] 204 ruleText += p 205 if not key == predicateResolver.keys()[-1]: 206 ruleText += ", " 207 added = 0 208 for subrule in rule['subrules']: 209 for constraint in subrule['constraints']: 210 for entry in constraint['entries']: 211 if added == 0: 212 ruleText += ", " 213 else: 214 ruleText += " = " 215 added = -1 216 if entry['type'] == 'parameter': 217 p = paramResolver[entry['name']] 218 ruleText += p 219 added += 1 220 elif entry['type'] == 'reference': 221 r = entry['name'] 222 s = r.split(".") 223 print >> sys.stderr, r 224 print >> sys.stderr, nameResolver 225 res = nameResolver[s[0]] 226 if res == None: 227 r = subrule['name'] + "." + entry['name'] 228 s = r.split(".") 229 res = nameResolver[s[0]] 230 if s[1] == 'HEAD' or s[1] == 'TARGET': 231 s[1] = res[s[1]] 232 search = s[1] 233 234 for k in range(2, len(s)): 235 search += ("." + s[k]) 236 237 try: 238 n = res[search] 239 ruleText += res[search] 240 except: 241 print >> sys.stderr, "Element not found: %s" % search 242 243 added += 1 244 elif entry['type'] == 'value': 245 ruleText += '"%s"' % entry['name'] 246 added += 1 247 248 249 # print >> sys.stderr, ruleText 250 FILE.write(ruleText + ".\n") 251 FILE.close()
252
253 - def __getConName(self, m, head, target):
254 """Get the name of the connection from head to target""" 255 for dep in m['dependencyDefs']: 256 if dep[1] == head and dep[0] == target: 257 return dep[2] 258 return ""
259 # def __findConnectingAttr(self, m, previous, current): 260 # """Find the Attribute that connects the two predicates""" 261 # neighbors = self.__getDepsForClass(m, previous) 262 # for neighbor in neighbors: 263 264 265 # def __getDepsForClass(self, m, name): 266 # """Get all dependencies for a class""" 267 # retVal = [] 268 # for dep in m['dependencyDefs']: 269 # if dep[0] == name: 270 # retval.append(dep[1]) 271 # return retVal 272
273 -class Signature(object):
274 """Create a signature for the given head -> target values.""" 275
276 - def __init__(self, model, head=None, target=None, predicate=None):
277 """Create a new Signature from head to target""" 278 if predicate == None: 279 self.head = head 280 self.isSingle = False 281 self.target = target 282 self.model = model 283 self.__create_dep_graph() 284 self.namedArgumentList = {} 285 self.argumentList = [] 286 self.predicate = head + "_" + target 287 self.path = self.__shortest_path() 288 289 pos = 0 290 for node in self.path: 291 attrs = get_attr_list_from_model(model, node) 292 for a in attrs: 293 self.argumentList.append(self.predicate + "." + a) 294 self.namedArgumentList[self.predicate + "." + a] = pos 295 pos += 1 296 self.argCount = pos 297 else: 298 self.predicate = predicate 299 self.isSingle = True 300 self.argumentList = copy.copy(get_attr_list_from_model(model, predicate)) 301 self.argCount = len(self.argumentList) 302 self.namedArgumentList = {} 303 self.target = None 304 self.head = None 305 self.model = model 306 307 i = 0 308 for node in self.argumentList: 309 self.namedArgumentList["%s.%s" % (predicate, node)] = i 310 i += 1
311 312
313 - def __create_dep_graph(self):
314 """Create a graph with the dependencies of the model""" 315 self.g = Graph() 316 for cd in self.model['classDefs']: 317 # Add a node for every class 318 self.g.add_node(cd['name']) 319 320 for e in self.model['dependencyDefs']: 321 self.g.add_edge(e[0], e[1]) 322 323 # print >> sys.stderr, "Number nodes: %d" % number_of_nodes(g) 324 # print >> sys.stderr, "Number edges: %d" % number_of_edges(g) 325 return self.g
326
327 - def __shortest_path(self):
328 """Search the shortest path between head and target""" 329 return shortest_path(self.g, self.head, self.target)
330
331 - def get_arg_count(self):
332 """get the number of arguments of the predicate""" 333 return self.argCount
334
335 - def get_position(self, attrName):
336 """Get the position of the named attribute""" 337 i = self.namedArgumentList[attrName] 338 if i == None: 339 i = self.namedArgumentList[self.predicate + "." + attrName] 340 if i == None: 341 return 0 342 return i
343
344 - def get_attribute_name(self, pos):
345 """Get the name of the attribute at pos""" 346 return self.argumentList[pos]
347