/usr/share/pyshared/swap/update.py is in python-swap 1.2.1-5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | """ Update for cwm architecture
The update module provides for the deletion as well as the addition of information to
a formula. This module assumes the llyn.py store. It connects intimiately with the
query module.
2004-03-17 written as an extension of query.py
"""
from set_importer import Set, sorted
import diag
from diag import chatty_flag, tracking, progress
from formula import Formula
from query import Query, Rule, seqToString, _substitute
def patch(workingContext, patchFormula):
"""A task of running a set of updates on a knowledge base
This is simpler than an Inference task, in that a patch is only done
once, patches cannot lead to new patches, etc.
"""
if diag.chatty_flag >20:
progress("New Update task, patches from %s applied to %s" %
(patchFormula, workingContext))
store = workingContext.store
true = store.newFormula().close() # {}
universals = Set()
lhs_done = []
agenda = {}
for pred in store.insertion, store.deletion:
for s in patchFormula.statementsMatching(pred=pred):
dict = agenda.get(s.subject(), None)
if dict == None:
dict = {store.insertion: [], store.deletion: []}
agenda[s.subject()] = dict
dict[pred].append(s.object())
for lhs, dict in sorted(agenda.items()):
if diag.chatty_flag > 19: progress("Patches lhs= %s: %s" %(lhs, dict))
if isinstance(lhs, Formula):
if lhs.universals() != Set():
raise RuntimeError("""Cannot query for universally quantified things.
As of 2003/07/28 forAll x ...x cannot be on left hand side of rule.
This/these were: %s\n""" % lhs.universals())
addenda, minuenda = dict[store.insertion], dict[store.deletion]
while addenda or minuenda:
if addenda: conclusion = addenda.pop()
else: conclusion = true
if minuenda: retraction = minuenda.pop()
else: retraction = true
unmatched = lhs.statements[:]
templateExistentials = lhs.existentials().copy()
_substitute({lhs: workingContext}, unmatched) # Change context column
variablesMentioned = lhs.occurringIn(patchFormula.universals())
variablesUsed = conclusion.occurringIn(variablesMentioned) | \
retraction.occurringIn(variablesMentioned)
for x in sorted(variablesMentioned):
if x not in variablesUsed:
templateExistentials.add(x)
if diag.chatty_flag >20:
progress("New Patch =========== applied to %s" %(workingContext) )
for s in lhs.statements: progress(" ", `s`)
progress("+=>")
for s in conclusion.statements: progress(" ", `s`)
progress("-=>")
for s in retraction.statements: progress(" ", `s`)
progress("Universals declared in outer " + seqToString(patchFormula.universals()))
progress(" mentioned in template " + seqToString(variablesMentioned))
progress(" also used in conclusion " + seqToString(variablesUsed))
progress("Existentials in template " + seqToString(templateExistentials))
q = UpdateQuery(store,
unmatched = unmatched,
template = lhs,
variables = patchFormula.universals(),
existentials =templateExistentials,
workingContext = workingContext,
conclusion = conclusion,
retraction = retraction,
rule = None)
q.resolve()
class UpdateQuery(Query):
"Subclass of query for doing patches onto the KB: adding and removing bits. Aka KB Update"
def __init__(self,
store,
unmatched, # List of statements we are trying to match CORRUPTED
template, # formula
variables, # List of variables to match and return CORRUPTED
existentials, # List of variables to match to anything
# Existentials or any kind of variable in subexpression
workingContext,
conclusion, # Things to be added
retraction, # Things to be deleted
rule): # The rule statement
Query.__init__(self, store, unmatched=unmatched, template=template, variables=variables,
existentials= existentials,
workingContext= workingContext,
conclusion=conclusion, targetContext = workingContext, rule=rule)
self.retraction = retraction
def conclude(self, bindings, evidence = [], extraBNodes=Set(), allBindings=None):
"""When a match found in a query, add conclusions to target formula,
and also remove retractions.
Returns the number of statements added."""
if diag.chatty_flag > 25: progress(
"Insertions will now be made into %s. Bindings %s" % (self.workingContext, bindings))
result = Query.conclude(self, bindings, evidence)
# delete statements
if diag.chatty_flag > 25: progress(
"Insertions made, deletions will now be made. Bindings %s" % bindings)
for st in self.retraction:
s, p, o = st.spo()
subj = self.doSubst(s, bindings)
pred = self.doSubst(p, bindings)
obj = self.doSubst(o, bindings)
ss = self.workingContext.statementsMatching(
subj = subj, pred = pred, obj = obj)
if len(ss) != 1:
progress("""Error: %i matches removing statement {%s %s %s}
bound as {%s %s %s} from %s:\n%s\n""" %
(len(ss),s,p,o, subj.uriref(), pred.uriref(), obj.uriref(), self.workingContext, ss
))
progress(self.workingContext.debugString())
raise RuntimeError(
"""Error: %i matches removing statement {%s %s %s}
bound as {%s %s %s} from %s""" %
(len(ss),s,p,o, `subj`, pred.uriref(), `obj`, self.workingContext))
if diag.chatty_flag > 25: progress("Deleting %s" % ss[0])
self.workingContext.removeStatement(ss[0])
self.justOne = 1 # drop out of here when done
return 1 # Success -- behave as a test and drop out
def doSubst(self, x, bindings):
if x.generated() and x not in bindings:
raise ValueError("""Retractions cannot have bnodes in them.
Use explict variables which also occur on the LHS.
Found bnode: %s, bindings are: %s""" % (x, bindings))
return bindings.get(x, x)
# ends
|