3
from cslib import Repository
4
from cslib.fd import FiniteDomain as fd
5
print 'using pypy.lib.cslib'
7
print 'using logilab.constraint'
8
from logilab.constraint import Repository
9
from logilab.constraint.fd import FiniteDomain as fd
10
from logilab.constraint.propagation import AbstractDomain, AbstractConstraint,\
12
from sparql_grammar import SPARQLGrammar as SP # name clash ?
13
from constraint_classes import *
15
Expression = MyExpression
18
from urllib2 import URLError
19
log = py.log.Producer("Pyontology")
20
from pypy.tool.ansi_print import ansi_log
21
py.log.setconsumer("Pyontology", None)
22
#py.log.setconsumer("Pyontology", ansi_log)
24
from rdflib import Graph, URIRef, BNode, Literal as rdflib_literal
28
'rdf' : 'http://www.w3.org/1999/02/22-rdf-syntax-ns',
29
'rdfs' : 'http://www.w3.org/2000/01/rdf-schema',
30
'xmlns' : 'http://www.w3.org/1999/xhtml',
31
'xmlschema' : 'http://www.w3.org/2001/XMLSchema',
32
'owl' : 'http://www.w3.org/2002/07/owl',
36
for k,v in namespaces.items():
39
Class = URIRef(u'http://www.w3.org/2002/07/owl#Class')
40
Thing_uri = URIRef(u'http://www.w3.org/2002/07/owl#Thing')
41
Nothing_uri = URIRef(u'http://www.w3.org/2002/07/owl#Nothing')
42
rdf_type = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#type')
43
rdf_rest = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest')
44
rdf_first = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#first')
45
rdf_nil = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil')
49
def getUriref(ns, obj):
50
return URIRef(namespaces[ns]+'#'+obj)
55
elif hasattr(f, 'open'):
67
""" In OWL there are Classes, Properties, Individuals and Literals.
68
Properties creates relations between Classes, Classes and Individuals, Individuals and Individuals and Literals. There are a inheritance tree of Properties. We record instances of Properies in the class variable "prop_instance".
70
Classes are defined as the set of Individuals belonging to the Class. We record these as the Values of the Classdomain.
71
We record the instances of a Classtype in the Class variable "cls_inst". The class instances shall "buble" up the inheritance tree.
74
class ClassDomain(AbstractDomain, object):
76
# Class domain is intended as a (abstract/virtual) domain for implementing
77
# Class axioms. Working on class descriptions the class domain should allow
78
# creation of classes through axioms.
79
# The instances of a class can be represented as a FiniteDomain in values (not always see Disjointwith)
80
# Properties of a class is in the dictionary "properties"
81
# The bases of a class is in the list "bases"
85
def __init__(self, name='', uri=None, values = [], bases = []):
86
AbstractDomain.__init__(self)
90
self.setValues(values)
93
self.un_constraint = []
94
self.in_constraint = []
100
self.setValues(values)
102
def finish(self, variables, glob_constraints):
103
# The finish method constructs the constraints
104
if not self.finished:
105
log.finish("%s" % self.name)
106
# Try to initialise constraints for this class
107
if len(self.type) > 1:
108
#try to merge the domains of the types
110
for typ in self.type:
111
expr +=[ "%s == %s" % (self.name, typ)]
112
expr = ' and '.join(expr)
113
self.in_constraint.append(Expression([self.name]+self.type, expr))
114
prop = getattr(self, 'property')
115
val = getattr(self, 'value')
117
prop = variables[prop]
118
for constraint in self.un_constraint:
119
dom, constraints = constraint(self.name, prop, val)
121
self.domains.update(dom)
122
self.in_constraint.extend(constraints)
123
# Initialise constraints from the base classes
125
for cls in self.bases:
127
dom,constraint = cls.finish(variables, glob_constraints)
129
# if the base class is a Restriction we shouldnt add the constraints to the store
130
if not isinstance(cls, Restriction):
131
self.domains.update(dom)
132
self.constraint.extend(constraint)
133
# initialise the constraint with this class as the first argument
134
for constraint in cls.un_constraint:
135
dom, constraints = constraint(self.name, variables[cls.property], cls.value)
136
self.domains.update(dom)
137
self.in_constraint.extend(constraints)
140
variables[self.name].setValues([v[0] for v in prop.getValues()])
141
elif ('owl_Thing' in variables.keys() and isinstance(self, ClassDomain)
142
and self.size() == 0):
143
variables[self.name].setValues(list(variables['owl_Thing'].getValues()))
144
variables.update(self.domains)
145
glob_constraints.extend(self.in_constraint)
146
# assert self.size() != 0
147
assert len([x for x in glob_constraints if type(x)==list])==0
148
return self.domains, self.un_constraint
151
return "<%s %s>" % (self.__class__, str(self.name))
153
def __contains__(self, item):
154
return item in self.values
157
return self.__class__(self.name, self.uri, self.getValues())
160
return len(self.values)
162
def removeValues(self, values):
164
self.removeValue(val)
166
def removeValue(self, value):
167
if value in self.values:
168
self.values.pop(value)
170
raise ConsistencyFailure("Removed the lastvalue of the Domain %r" % self)
175
def setBases(self, bases):
176
assert self.name != 'owl_Class'
179
def addValue(self, value):
180
self.values[value] = True
183
for key in self.values:
185
#return self.values.keys()
188
return iter(self.values.keys())
190
def setValues(self, values):
194
class FixedClassDomain(ClassDomain):
198
def __init__(self, name='', uri=None, values = [], bases = []):
199
ClassDomain.__init__(self, name, uri, values, bases)
202
def addValue(self, value):
204
raise ValueError("Fixed classes can only add vulues during initialisation")
206
ClassDomain.addValue(self, value)
208
# def removeValues(self, values):
209
# raise ConsistencyFailure("Cannot remove values from a FixedClassDomain")
211
# def removeValue(self, value):
212
# raise ConsistencyFailure("Cannot remove values from a FixedClassDomain")
214
# def setValues(self, values):
215
# if not self.values:
216
# self.values = dict.fromkeys(values)
218
#raise ConsistencyFailure
220
class Thing(ClassDomain):
221
uri = URIRef(namespaces['owl'] + "#Thing")
224
class Individual(Thing):
225
def __init__(self, name, uri=None, values=[], bases=[]):
226
Thing.__init__(self, name, uri, values, bases)
230
self.differentfrom = set()
233
return "<%s( %s, %s)>"%(self.__class__.__name__, self.name, self.uri)
236
return hash(self.uri)
238
def __eq__(self, other):
239
#log("CMP %r,%r %i"%(self.name,other, len(self.differentfrom)))
240
#assert isinstance(other, ClassDomain)
241
if hasattr(other,'uri'):
242
if self.uri == other.uri:
244
elif other in self.sameas:
247
if self.uri == other:
249
if not other or other in self.differentfrom:
256
class List(ClassDomain):
257
uri = URIRef(namespaces['rdf'] + "#List")
259
def __init__(self, name='', values=[], bases = []):
260
ClassDomain.__init__(self, name, values, bases)
262
class Property(AbstractDomain, object):
263
# Property contains the relationship between a class instance and a value
264
# - a pair. To accomodate global assertions like 'range' and 'domain' attributes
265
# for range and domain must be filled in by rdfs:range and rdfs:domain
266
uri = URIRef(namespaces['rdf'] + "#Property")
268
def __init__(self, name='', uri='', values=[], bases = []):
269
super(Property, self).__init__()
274
self.un_constraint = []
275
self.in_constraint = []
279
self.setValues(values)
282
return Property(self.name, self.uri, list(self.getValues()))
284
def finish(self, var, constraints):
285
return var, constraints
288
return len(self._dict)
291
items = self._dict.items()
297
def getValuesPrKey(self, key= None):
299
return self._dict.get(key,[])
300
return self._dict.items()
302
def addValue(self, key, val):
303
self._dict.setdefault(key, [])
304
self._dict[key].append(val)
306
def setValues(self, values):
308
for key, val in values:
309
self.addValue(key, val)
311
def removeValues(self, values):
317
self._dict[k] = [ x for x in vals if x != v]
318
if not self._dict[k]:
321
raise ConsistencyFailure("Removed the last value of %s" % self.name)
324
return iter(self.getValues())
326
def __contains__(self, (cls, val)):
327
if not cls in self._dict:
329
vals = self._dict[cls]
334
class ObjectProperty(Property):
335
uri = URIRef(namespaces['owl'] + "#ObjectProperty")
339
class DatatypeProperty(Property):
340
uri = URIRef(namespaces['owl'] + "#DatatypeProperty")
343
class DataRange(ClassDomain):
346
class AllDifferent(ClassDomain):
347
uri = URIRef(namespaces['owl'] + "#AllDifferent")
348
# A special class whose members are distinct
352
class Nothing(ClassDomain):
353
uri = URIRef(namespaces['owl'] + "#Nothing")
354
def __init__(self, name='', values=[], bases = []):
355
ClassDomain.__init__(self, name, values, bases)
356
self.constraint = [NothingConstraint(name)]
359
class FunctionalProperty(Property):
360
uri = URIRef(namespaces['owl'] + "#FunctionalProperty")
362
def __init__(self, name='', values=[], bases = []):
363
Property.__init__(self, name, values, bases)
364
self.constraint = [FunctionalCardinality(name)]
366
class InverseFunctionalProperty(ObjectProperty):
367
uri = URIRef(namespaces['owl'] + "#InverseFunctionalProperty")
369
def __init__(self, name='', values=[], bases = []):
370
Property.__init__(self, name, values, bases)
371
self.constraint = [InverseFunctionalCardinality(name)]
373
def addValue(self, key, val):
374
Property.addValue(self, key, val)
375
valuelist = [set(x) for x in self._dict.values()]
377
for vals in valuelist:
379
raise ConsistencyFailure("Only unique values in InverseFunctionalProperties")
382
class TransitiveProperty(ObjectProperty):
383
uri = URIRef(namespaces['owl'] + "#TransitiveProperty")
385
def __init__(self, name='', values=[], bases = []):
386
Property.__init__(self, name, values, bases)
387
#self.constraint = TransitiveConstraint(name)
389
def addValue(self, key, val):
390
Property.addValue(self, key, val)
391
if val in self._dict.keys():
392
for v in self._dict[val]:
393
Property.addValue(self, key, v)
394
for k in self._dict.keys():
395
if key in self._dict[k]:
396
Property.addValue(self, k, val)
398
class SymmetricProperty(ObjectProperty):
399
uri = URIRef(namespaces['owl'] + "#SymmetricProperty")
401
def __init__(self, name='', values=[], bases = []):
402
Property.__init__(self, name, values, bases)
403
# self.constraint = SymmetricConstraint(name)
405
def addValue(self, key, val):
406
Property.addValue(self, key, val)
407
Property.addValue(self, val, key)
409
class Restriction(ClassDomain):
410
""" A owl:restriction is an anonymous class that links a class to a restriction on a property
411
The restriction is only applied to the property in the conntext of the specific task. In order
412
to construct a constraint to check the restriction three things are thus needed :
413
1. The property to which the restriction applies - this comes from the onProperty tripple.
414
the property is saved in the Restriction class' property attribute
415
2. The restriction itself. This comes from one of the property restrictions triples (oneOf,
416
maxCardinality ....). It adds a constraint class
417
3. The class in which context the restriction should be applied. This comes from subClassOf, type...
418
The class is saved in the restrictions cls attribute
420
uri = URIRef(namespaces['owl'] + "#Restriction")
421
def __init__(self, name='', uri='', values=[], bases = []):
422
ClassDomain.__init__(self, name, uri, values, bases)
426
cc = ClassDomain.copy(self)
427
cc.property = self.property
430
class Literal(ClassDomain):
435
def __contains__(self, item):
436
if isinstance(item, rdflib_literal):
437
return item.datatype is None or item.datatype == self.Type
439
return XMLTypes[self.Type.split("#")[-1]] == type(item)
446
getUriref('owl', 'Thing') : Thing,
447
getUriref('owl', 'Class') : ClassDomain,
448
getUriref('rdf', 'Property') : Property,
449
getUriref('owl', 'ObjectProperty') : ObjectProperty,
450
getUriref('owl', 'AllDifferent') : AllDifferent ,
451
getUriref('owl', 'AnnotationProperty') : Property, #XXX AnnotationProperty,
452
getUriref('owl', 'DataRange') : DataRange,
453
getUriref('owl', 'DatatypeProperty') : DatatypeProperty,
454
## getUriref('owl', 'DeprecatedClass') : DeprecatedClass,
455
## getUriref('owl', 'DeprecatedProperty') : DeprecatedProperty,
456
getUriref('owl', 'FunctionalProperty') : FunctionalProperty,
457
getUriref('owl', 'InverseFunctionalProperty') : InverseFunctionalProperty,
458
getUriref('owl', 'Nothing') : Nothing,
459
## getUriref('owl', 'Ontology') : Ontology,
460
## getUriref('owl', 'OntologyProperty') : OntologyProperty,
461
getUriref('owl', 'Restriction') : Restriction,
462
getUriref('owl', 'SymmetricProperty') : SymmetricProperty,
463
getUriref('owl', 'TransitiveProperty') : TransitiveProperty,
464
getUriref('rdf', 'List') : List,
465
getUriref('rdf', 'Literal') : Literal,
466
# getUriref('rdf', 'type') : Property,
468
#XMLTypes = ['string', 'float', 'integer', 'date']
469
XMLTypes = {'string': str, 'float': float, 'integer': int,
470
'date': lambda x: datetime.date(*[int(v) for v in x.split('-')])}
473
uri = getUriref('xmlschema', typ)
474
builtin_voc[uri] = Types(uri)
478
def __init__(self, store = 'default'):
479
self.graph = Graph(store)
481
if store != 'default':
482
self.graph.open(py.path.local().join("db").strpath)
483
self.store_path = py.path.local().join("db").strpath
485
self.constraints = []
486
self.variables['owl_Thing'] = Thing('owl_Thing')
487
self.variables['owl_Literal'] = Literal('owl_Literal')
490
self.nr_of_triples = 0
491
# self.time = time.time()
492
# for pr in builtin_voc:
493
# name = self.mangle_name(pr)
494
# Instantiate ClassDomains to record instances of the types
495
# name = name + "_type"
496
# self.variables[name] = ClassDomain(name, pr)
498
def add(self, triple):
499
self.graph.add(triple)
501
def add_file(self, f, format=None):
502
tmp = Graph('default')
504
format = check_format(f)
505
tmp.load(f, format=format)
506
for triple in tmp.triples((None,)*3):
508
# self.consider_triple(triple)
510
def load_file(self, f, format=None):
512
format = check_format(f)
513
self.graph.load(f, format=format)
516
for (s, p, o) in (self.graph.triples((None,)*3)):
517
self.consider_triple((s, p, o))
520
cons = [(c.cost,c) for c in self.constraints if hasattr(c, 'cost')]
522
for i,constraint in cons:
523
log.ontfinish("Trying %r of %d/%d " %(constraint,cons.index((i, constraint)),len(cons)))
524
for key in constraint.affectedVariables():
525
if not ( self.variables.get(key)):
527
if isinstance( self.variables[key], fd):
529
self.variables[key].finish(self.variables, self.constraints)
532
constraint.narrow(self.variables)
533
# except ConsistencyFailure, e:
535
things = list(self.variables['owl_Thing'].getValues())
536
things += list(self.variables['owl_Literal'].getValues())
537
self.variables['owl_Thing'].setValues(things)
539
def _sparql(self, query):
540
qe = SP.Query.parseString(query)
541
prefixes = qe.Prefix[0]
544
for v in qe.SelectQuery[0].VARNAME:
547
where = qe.SelectQuery[0].WhereClause[0]
549
triples = where.GroupGraphPattern[0].Triples
556
trip_ = [trip.Subject[0], trip.Verb[0], trip.Object[0]]
558
if isinstance(item[0], rdflib_literal):
560
if o.datatype in builtin_voc:
561
o = XMLTypes[o.datatype.split('#')[-1]](o)
562
self.variables['owl_Literal'].addValue(o)
564
elif item[0].NCNAME_PREFIX:
565
uri = prefixes[item[0].NCNAME_PREFIX[0]] + item[0].NCNAME[0]
566
newtrip.append(URIRef(uri))
568
var_uri = URIRef('query_'+item.VAR1[0][0])
569
newtrip.append(var_uri)
571
case += trip_.index(item) + inc
577
newtrip.append(item[0][0])
580
constrain = where.GroupGraphPattern[0].Constraint
581
return new, prefixes, resvars, constrain, vars
583
# There are 8 ways of having the triples in the query, if predicate is not a builtin owl predicate
587
# 0 bound bound bound ; Check if this triple entails
588
# 1 var bound bound ; add a hasvalue constraint
589
# 2 bound var bound ; for all p's return p if p[0]==s and p[1]==o
590
# 3 bound bound var ; search for s in p
591
# 4 var var bound ; for all p's return p[0] if p[1]==o
592
# 5 var bound var ; return the values of p
593
# 6 bound var var ; for all p's return p[1] if p[0]==s
594
# 7 var var var ; for all p's return p.getvalues
597
def sparql(self, query):
598
new, prefixes, resvars, constrain, vars = self._sparql(query)
604
# Check if this triple entails
605
sub = self.mangle_name(trip[0])
606
prop = self.mangle_name(trip[1])
607
obj = self.mangle_name(trip[2])
608
if not obj in self.variables[prop].getValuesPrKey(sub):
609
raise ConsistencyFailure
611
# Add a HasValue constraint
612
ns,pred = trip[1].split("#")
613
if ns in namespaces.values():
614
self.consider_triple(trip)
616
var = self.make_var(Restriction, URIRef(trip[0]))
617
self.onProperty(var, URIRef(trip[1]))
618
self.hasValue(var, trip[2])
620
# for all p's return p if p[0]==s and p[1]==o
622
prop_name = self.make_var(ClassDomain, URIRef(trip[1]))
623
indi_name = self.mangle_name(trip[0])
624
indi = Individual(indi_name, trip[0])
625
obj_name = self.mangle_name(trip[2])
626
if obj_name in self.variables:
627
obj = self.variables[self.mangle_name(trip[2])]
630
prop = self.variables[prop_name]
631
# Get all properties by looking at 'rdf_Property'
632
props = list(self.variables['rdf_Property'].getValues())
633
prop.setValues(props)
635
query_dom[p] = self.variables[p]
636
# add a constraint trip[0] in domains[prop] and trip[2] in domains[prop].getValuesPrKey(trip[0])
637
query_constr.append(PropertyConstrain(prop_name, indi, obj))
641
prop = self.make_var(None, trip[1])
642
#indi = self.variables[self.make_var(
643
indi = Individual( self.mangle_name(trip[0]), trip[0])
644
p_vals = self.variables[prop].getValuesPrKey(indi)
645
var = self.make_var(Thing, trip[2])
646
self.variables[var].setValues((p_vals))
648
# for all p's return p[0] if p[1]==o
650
sub_name = self.make_var(ClassDomain, URIRef(trip[0]))
651
prop_name = self.make_var(ClassDomain, URIRef(trip[1]))
652
sub = self.variables[sub_name]
653
sub.setValues(list(self.variables['owl_Thing'].getValues()))
654
prop = self.variables[prop_name]
655
props = list(self.variables['rdf_Property'].getValues())
656
prop.setValues(props)
658
query_dom[p] = self.variables[p]
659
obj_name = self.mangle_name(trip[2])
660
if obj_name in self.variables:
661
obj = self.variables[self.mangle_name(trip[2])]
664
query_constr.append(PropertyConstrain2(prop_name, sub_name, obj))
666
# return the values of p
667
prop = self.make_var(Property, URIRef(trip[1]))
668
query_dom[prop] = self.variables[prop]
669
p_vals = list(self.variables[prop].getValues())
670
sub = self.make_var(Thing, trip[0])
671
vals = set([v[0] for v in p_vals])
672
if self.variables[sub].size():
673
vals &= set(self.variables[sub].getValues())
674
self.variables[sub].setValues(vals)
675
obj = self.make_var(Thing, trip[2])
676
vals = set([v[1] for v in p_vals])
677
if self.variables[obj].size():
678
vals &= set(self.variables[obj].getValues())
679
self.variables[obj].setValues(vals)
680
con = PropertyConstrain3(prop, sub, obj)
681
# con = Expression([sub,prop,obj], "%s == (%s, %s)" %(prop, sub, obj))
682
query_constr.append(con)
685
# 6 bound var var ; for all p's return p[1] if p[0]==s
686
# for all p's return p[1] if p[0]==s
687
prop = self.make_var(Property, URIRef(trip[1]))
691
# for all p's return p.getvalues
693
for p in self.variables['rdf_Property'].getValues():
694
p_vals += self.variables[p].getValues()
696
prop = self.make_var(Property, URIRef(trip[1]))
697
self.variables[prop].setValues(p_vals)
698
sub = self.make_var(Thing, trip[0])
699
obj = self.make_var(Thing, trip[2])
700
con = Expression([sub,prop,obj], "%s[0] == %s and %s[1] == %s" %(prop, sub, prop, obj))
701
query_constr.append(con)
702
# call finish on the variables in the query
704
_dom, _ = self.variables[self.mangle_name(v)].finish(self.variables, query_constr) #query_dom, query_constr)
705
query_dom.update(_dom)
706
# Build a repository with the variables in the query
707
dom = dict([(self.mangle_name(v),self.variables[self.mangle_name(v)])
710
dom.update(query_dom)
711
# solve the repository and return the solution
712
rep = Repository(dom.keys(), dom, query_constr)
713
res_s = Solver(MyDistributor()).solve(rep, verbose=0)
715
query_vars = dict([('query_%s_'%name,name) for name in resvars])
718
for k,v in d.items():
725
res_dict[query_vars[k]] = (val)
729
def consider_triple(self,(s, p, o)):
730
if (s, p, o) in self.seen:
732
self.nr_of_triples += 1
733
log("Doing triple nr %i: %r" % (self.nr_of_triples,(s, p, o)))
735
# log.considerTriple("Triples per second %f" %(1./(tim-self.time)))
737
self.seen[(s, p, o)] = True
738
if p.find('#') != -1:
739
ns, func = p.split('#')
743
if ns in namespaces.values() and hasattr(self, func):
744
#predicate is one of builtin OWL or rdf predicates
745
pred = getattr(self, func)
747
#avar = self.make_var(ClassDomain, s)
749
pvar = self.make_var(Property, p)
750
# Set the values of the property p to o
751
self.type(s, Thing_uri)
752
sub = self.mangle_name(s)
753
if type(o) == URIRef:
754
obj = self.mangle_name(o)
755
if obj in self.variables:
756
val = self.variables[obj]
758
val = Individual(obj, o)
759
elif type(o) == rdflib_literal:
760
# self.variables.setdefault('owl_Literal', ClassDomain('owl_Literal',u''))
761
if o.datatype in builtin_voc:
762
o = XMLTypes[o.datatype.split('#')[-1]](o)
763
self.variables['owl_Literal'].addValue(o)
767
propdom = self.variables[pvar]
768
res = propdom.addValue(Individual(sub,s), val)
770
def resolve_item(self, item):
771
item_as_subject = self.graph.triples((item, None, None))
772
for triple in item_as_subject:
773
self.consider_triple(triple)
775
def resolve_predicate(self, item):
776
item_as_predicate = self.graph.triples(( None, item, None))
777
for triple in item_as_predicate:
778
self.consider_triple(triple)
780
def get_individuals_of(self, item):
781
item_as_object = self.graph.triples(( None, rdf_type, item))
782
for triple in item_as_object:
783
self.consider_triple(triple)
785
def mangle_name(self, a):
787
if type(a) == URIRef:
788
if a.find('#') != -1:
789
ns,name = a.split('#')
792
if ns not in uris.keys():
793
uris[ns] = ns.split('/')[-1]
794
var = uris[ns] + '_' + name
795
var = str(var.replace('.','_'))
796
var = str(var.replace('-','_'))
797
elif type(a) == BNode:
803
def make_var(self, cls=fd, a=''):
804
var = self.mangle_name(a)
807
if not var in self.variables:
808
if a in builtin_voc and issubclass(builtin_voc[a], ClassDomain):
810
cls = self.variables[var] = cls(var, a)
812
self.constraints.extend(cls.constraint)
813
elif not cls == self.variables[var].__class__ and issubclass(cls, self.variables[var].__class__):
814
vals = self.variables[var].getValues()
816
tmp.setValues(list(vals))
817
tmp.property = self.variables[var].property
819
self.constraints.extend(tmp.constraint)
820
self.variables[var] = tmp
823
def solve(self,verbose=0):
824
rep = Repository(self.variables.keys(), self.variables, self.constraints)
825
return Solver().solve(rep, verbose)
827
def consistency(self, verbose=0):
828
log("BEFORE FINISH %r" % self.variables)
830
self.rep = Repository(self.variables.keys(), self.variables, self.constraints)
831
self.rep.consistency(verbose)
833
def flatten_rdf_list(self, rdf_list):
835
if not type(rdf_list) == list:
836
avar = self.make_var(List, rdf_list)
837
lis = list(self.graph.objects(rdf_list, rdf_first))
841
lis = list(self.graph.objects(rdf_list, rdf_rest))[0]
842
while lis != rdf_nil:
843
res.append(list(self.graph.objects(lis, rdf_first))[0])
844
lis = list(self.graph.objects(lis, rdf_rest))[0]
845
self.variables[avar].setValues(res)
848
avar = self.make_var(List, BNode('anon_%r'%rdf_list))
849
if type(rdf_list[0]) == list:
850
res = [tuple(x) for x in rdf_list]
853
self.variables[avar].setValues(res)
856
#---------------- Implementation ----------------
858
def comment(self, s, var):
861
def label(self, s, var):
864
def type(self, s, var):
865
if not var in builtin_voc :
866
# var is not one of the builtin classes -> it is a Class
867
avar = self.make_var(ClassDomain, var)
868
#self.type(s, Thing_uri)
869
svar = self.mangle_name(s)
870
s_type = Individual(svar, s)
871
self.variables[svar] = s_type
872
if type(self.variables[avar]) != FixedClassDomain:
873
self.variables[avar].addValue(s_type)
874
self.constraints.append(MemberConstraint(svar, avar))
876
# var is a builtin class
877
cls = builtin_voc[var]
878
avar = self.make_var(ClassDomain, var)
880
svar = self.mangle_name(s)
881
self.variables[avar].addValue(Individual(svar, s))
883
svar = self.make_var(cls, s)
884
for parent in cls.__mro__[1:]:
885
if not hasattr(parent, 'uri'):
887
typ_name = self.make_var(ClassDomain, parent.uri)
888
self.variables[typ_name].addValue(svar)
891
cls = self.variables[svar]
893
self.constraints.extend(cls.constraint)
894
# if not isinstance(self.variables[avar], Property):
895
if isinstance(self.variables[avar], Thing):
896
self.variables[avar].addValue(Individual(svar, s))
898
self.variables[avar].addValue(svar)
900
def first(self, s, var):
903
def rest(self, s, var):
906
def onProperty(self, s, var):
907
svar =self.make_var(Restriction, s)
908
avar =self.make_var(Property, var)
909
restr = self.variables[svar]
910
restr.property = avar
912
#---Class Axioms---#000000#FFFFFF-----------------------------------------------
914
def subClassOf(self, s, var):
915
# s is a subclass of var means that the
916
# class extension of s is a subset of the
917
# class extension of var, ie if a indiviual is in
918
# the extension of s it must be in the extension of
921
avar = self.make_var(ClassDomain, var)
922
svar = self.make_var(ClassDomain, s)
923
self.variables[svar].bases.append(avar)
924
self.variables[svar].bases.extend(self.variables[avar].bases)
925
self.constraints.append(SubClassConstraint(svar, avar))
927
def equivalentClass(self, s, var):
928
self.subClassOf(s, var)
929
self.subClassOf(var, s)
931
def disjointWith(self, s, var):
933
self.resolve_item(var)
934
avar = self.make_var(None, var)
935
svar = self.make_var(None, s)
936
constrain = DisjointClassConstraint(svar, avar)
937
self.constraints.append(constrain)
939
def complementOf(self, s, var):
940
# add constraint of not var
941
# i.e. the extension of s shall contain all individuals not in var
942
# We need to know all elements and subtract the elements of var
944
self.resolve_item(var)
945
avar = self.make_var(ClassDomain, var)
946
svar = self.make_var(ClassDomain, s)
947
self.constraints.append(ComplementOfConstraint(svar, avar))
949
def oneOf(self, s, var):
950
# Oneof is used to generate a fixed class. The elements of the class
951
# are exactly the ones in the list.
952
# Can be used to define an enumerated datatype as well.
953
# The memebers of the list can be Urirefs (Individuals) or Literals
954
var = self.flatten_rdf_list(var)
955
svar = self.mangle_name(s)
956
res = list(self.variables[var].getValues())
957
# For Individuals (datatypes handled differently ?) XXX
958
s_cls = FixedClassDomain(svar, s, [Individual(self.mangle_name(x), x) for x in res])
959
self.variables[svar] = s_cls
961
def unionOf(self,s, var):
962
avar = self.flatten_rdf_list(var)
963
res = [self.mangle_name(x) for x in self.variables[avar]]
964
self.variables[avar] = ClassDomain(avar, var, res)
965
svar = self.make_var(ClassDomain, s)
966
cons = UnionofConstraint(svar, avar)
967
self.constraints.append(cons)
969
def intersectionOf(self, s, var):
970
avar = self.flatten_rdf_list(var)
971
res = [self.mangle_name(x) for x in self.variables[avar]]
972
self.variables[avar] = ClassDomain(avar, var, res)
973
svar = self.make_var(ClassDomain, s)
974
cons = IntersectionofConstraint(svar, avar)
975
self.constraints.append(cons)
977
#---Property Axioms---#000000#FFFFFF--------------------------------------------
979
def range(self, s, var):
980
avar = self.make_var(ClassDomain, var)
981
svar = self.make_var(Property, s)
982
cons = RangeConstraint(svar, avar)
983
self.constraints.append(cons)
985
def domain(self, s, var):
986
# The classes that has this property (s) must belong to the class extension of var
987
avar = self.make_var(ClassDomain, var)
988
svar = self.make_var(Property, s)
989
cons = DomainConstraint(svar, avar)
990
self.constraints.append(cons)
992
def subPropertyOf(self, s, var):
993
# s is a subproperty of var
994
self.resolve_predicate(var)
995
self.resolve_predicate(s)
996
avar = self.make_var(Property, var)
997
svar = self.make_var(Property, s)
998
avals = self.variables[avar]
999
for pair in self.variables[svar].getValues():
1000
if not pair in avals:
1001
self.variables[avar].addValue(pair[0], pair[1])
1003
def equivalentProperty(self, s, var):
1004
avar = self.make_var(Property, var)
1005
svar = self.make_var(Property, s)
1006
cons = EquivalentPropertyConstraint( svar, avar)
1007
self.constraints.append(cons)
1009
def inverseOf(self, s, var):
1010
avar = self.make_var(Property, var)
1011
svar = self.make_var(Property, s)
1012
con = InverseofConstraint(svar, avar)
1013
self.constraints.append(con)
1015
#---Property restrictions------------------------------------------------------
1017
def cardinality_helper(self, s, var, card):
1019
svar =self.make_var(Restriction, s)
1020
scls = self.variables[svar]
1021
scls.un_constraint.append(card)
1024
def maxCardinality(self, s, var):
1025
""" Len of finite domain of the property shall be less than or equal to var"""
1026
def maxCard(cls , prop, val):
1027
dom = {"%s_%s_card" %(cls, prop.name) : fd(range(val+1))}
1028
return dom,[CardinalityConstraint( prop.name, cls, val, '<')]
1029
self.cardinality_helper(s, int(var), maxCard)
1031
def minCardinality(self, s, var):
1032
""" Len of finite domain of the property shall be greater than or equal to var"""
1033
def minCard(cls , prop, val):
1034
var = "%s_%s_card" %(cls, prop.name)
1035
con = Expression([var], "%s >= %i" % (var, val))
1036
return {},[con, CardinalityConstraint(prop.name, cls, val , '>')]
1037
self.cardinality_helper(s, int(var), minCard)
1039
def cardinality(self, s, var):
1040
""" Len of finite domain of the property shall be equal to var"""
1041
def Card(cls , prop, val):
1042
dom = {"%s_%s_card" %(cls, prop.name) : fd([val])}
1043
return dom,[CardinalityConstraint( prop.name, cls, val, '=')]
1044
self.cardinality_helper(s, int(var), Card)
1046
def value_helper(self, s, var, constraint):
1047
svar = self.make_var(Restriction, s)
1048
avar = self.make_var(None, var)
1049
scls = self.variables[svar]
1050
scls.un_constraint.append(constraint)
1053
def hasValue(self, s, var):
1054
""" The hasValue restriction defines a class having as an extension all
1055
Individuals that have a property with the value of var.
1056
To make an assertion we need to know for which class the restriction applies"""
1057
sub = self.make_var(Restriction, s)
1058
cons = HasvalueConstraint(sub, var)
1059
self.constraints.append(cons)
1061
def allValuesFrom(self, s, var):
1062
sub = self.make_var(Restriction, s)
1063
obj = self.make_var(ClassDomain, var)
1064
cons = AllValueConstraint(sub, obj)
1065
self.constraints.append(cons)
1067
def someValuesFrom(self, s, var):
1068
sub = self.make_var(Restriction, s)
1069
obj = self.make_var(ClassDomain, var)
1070
cons = SomeValueConstraint(sub, obj)
1071
self.constraints.append(cons)
1073
# ----------------- ----------------
1075
def imports(self, s, var):
1078
# add the triples to the graph
1082
for trip in tmp.triples((None,)*3):
1087
def sameAs(self, s, var):
1088
s_var = self.make_var(Thing, s)
1089
var_var = self.make_var(Thing, var)
1090
constrain = SameasConstraint(s_var, var_var)
1091
self.constraints.append(constrain)
1093
def differentFrom(self, s, var):
1094
s_var = self.make_var(Thing, s)
1095
var_var = self.make_var(Thing, var)
1096
constrain = DifferentfromConstraint(s_var, var_var)
1097
self.constraints.append(constrain)
1099
def distinctMembers(self, s, var):
1100
s_var = self.make_var(AllDifferent, s)
1101
var_var = self.flatten_rdf_list(var)
1102
diff_list = self.variables[var_var].getValues()
1104
indx = diff_list.index(v)
1105
for other in diff_list[indx+1:]:
1106
self.differentFrom(v, other)
1108
if __name__ == "__main__":
1109
import SimpleXMLRPCServer
1116
rdffile = sys.argv[-1]
1121
server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 9000))
1122
server.register_instance(O)
1123
server.register_function(ok)
1124
server.serve_forever()