summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornitromaster101 <nitromaster101@5914aa95-5b3a-0410-a3b5-7b719e7fe9b2>2009-06-30 02:16:16 +0000
committernitromaster101 <nitromaster101@5914aa95-5b3a-0410-a3b5-7b719e7fe9b2>2009-06-30 02:16:16 +0000
commit14b05bd56551d1d0be3bec691e4d42eb23afc044 (patch)
treeafe0d8e106ced3f5a9ef6b5867295d3f9848d3da
parent7429ace6367e348641fbf82d5dcbf224c079999b (diff)
schema manipulation
git-svn-id: http://freebase-python.googlecode.com/svn/trunk@153 5914aa95-5b3a-0410-a3b5-7b719e7fe9b2
-rw-r--r--schema-manipulation/get_type.py262
-rw-r--r--schema-manipulation/type_creation.py247
2 files changed, 509 insertions, 0 deletions
diff --git a/schema-manipulation/get_type.py b/schema-manipulation/get_type.py
new file mode 100644
index 0000000..af4554e
--- /dev/null
+++ b/schema-manipulation/get_type.py
@@ -0,0 +1,262 @@
+# TODO: copy /freebase/type_hints junk
+
+from pprint import pprint
+import random
+
+from type_creation import create_type, create_property, delegate_property, reciprocate_property
+
+from freebase.api import HTTPMetawebSession, MetawebError
+
+s = HTTPMetawebSession("http://sandbox-freebase.com")
+s.login("username", "password")
+
+import time
+
+def create_type_dependencies(s, base_id=None, type_id=None):
+
+ if base_id:
+ q = {"id" : base_id, "/type/domain/types" : [{"id" : None}] }
+ results = s.mqlread(q)
+ types = map(lambda x: x["id"], results["/type/domain/types"])
+ #pprint(types)
+
+ if type_id:
+ types = [type_id]
+ base_id = "/".join(type_id.split("/")[:-1])
+ print base_id
+
+ if not base_id and not type_id:
+ raise Exception("You need to supply either a base_id or a type_id")
+
+ graph = {}
+ to_update = set(types)
+ done = set()
+ while len(to_update) > 0:
+ new = to_update.pop()
+ graph[new] = get_needed(s, new)
+ [to_update.add(b) for b in graph[new]["related"] if b not in done]
+ done.update(graph[new]["related"])
+
+ # find distinct subgraphs (looking at needs)
+ subgraphs = []
+ unknown = set(graph.keys())
+ while len(unknown) > 0:
+ visited = set()
+ to_visit = set([list(unknown)[0]])
+ while len(to_visit) > 0:
+ new = to_visit.pop()
+ visited.add(new)
+ try:
+ unknown.remove(new)
+ except KeyError:
+ pass
+ [to_visit.add(b) for b in graph[new]["related"] if b not in visited]
+ subgraphs.append(list(visited))
+ #pprint(subgraphs)
+
+ pprint(graph)
+ return
+
+ # create type dependencies
+ typegraph = {}
+ for tid, idres in graph.items():
+ typegraph[tid] = idres["needs"]
+
+ least_needy_type = map(lambda (name, x): (len(x), name), typegraph.items())
+ least_needy_type.sort()
+
+ types_to_create = create_what(least_needy_type, typegraph)
+
+ # create property dependencies
+ propgraph = {}
+ proptotype = {}
+ for tid, idres in graph.items():
+ for prop in idres["properties"]:
+ propgraph[prop["id"]] = prop["needs"]
+ proptotype[prop["id"]] = tid
+ least_needy = map(lambda (name, x): (len(x), name), propgraph.items())
+ least_needy.sort()
+
+ props_to_create = create_what(least_needy, propgraph)
+
+ domainname = "awesome" + str(int(random.random() * 1e10))
+ print "\ndomainid", domainname
+ print "--------------------------"
+ dn = s.create_private_domain(domainname, domainname + "!")
+ domain_id = dn.domain_id
+
+ better_id = s.mqlread({"id" : domain_id, "a:id" : None})
+ domain_id = better_id["a:id"]
+
+ for type in types_to_create:
+ print type
+ key = ""
+ if len(graph[type]["key"]) == 1:
+ key = graph[type]["key"][0]["value"]
+ else:
+ expectedname = graph[type]["id"].split("/")[-1]
+ if base_id:
+ for group in graph[type]["key"]:
+ if group["namespace"] == base_id:
+ key = group["value"]
+ continue
+ if key is None:
+ key = expectedname
+ tip = None
+ if graph[type]["/freebase/documented_object/tip"]:
+ tip = graph[type]["/freebase/documented_object/tip"]["value"]
+ create_type(s, graph[type]["name"]["value"], key, domain_id,
+ included=map(lambda x: convert_name(x["id"], base_id, domain_id), graph[type]["/freebase/type_hints/included_types"]),
+ cvt=graph[type]["/freebase/type_hints/mediator"],
+ enum=graph[type]["/freebase/type_hints/enumeration"],
+ tip=tip)
+
+ print "--------------------------"
+
+ for prop in props_to_create:
+ info = graph[proptotype[prop]]["properties"]
+ for i in info:
+ if i["id"] == prop:
+ schema = convert_name(proptotype[prop], base_id, domain_id)
+ print prop
+ expected = None
+ if i["expected_type"]:
+ expected = convert_name(i["expected_type"]["id"], base_id, domain_id)
+ for k in i["key"]:
+ if k.namespace == proptotype[prop]:
+ key = k.value
+ if i["/freebase/documented_object/tip"]:
+ tip = graph[type]["/freebase/documented_object/tip"]
+
+ if i['master_property']:
+ reciprocate_property(s, i["name"], key, convert_name(i["master_property"]["id"], base_id, domain_id),
+ i["unique"], disambig=i["/freebase/property_hints/disambiguator"], tip=tip)
+ elif i['delegated']:
+ delegate_property(s, convert_name(i['delegated']['id'], base_id, domain_id), schema,
+ expected=expected, tip=tip)
+ else:
+ create_property(s, i["name"], key, schema, expected, i["unique"],
+ disambig=i["/freebase/property_hints/disambiguator"], tip=tip)
+
+
+
+
+ print "\ndomain id was", domainname
+
+
+def convert_name(old_name, operating_base, new_base):
+ if old_name.startswith(operating_base):
+ return new_base + old_name.replace(operating_base, "", 1)
+ else:
+ return old_name
+
+def create_what(deps, graph):
+ create_list = []
+ while len(deps) > 0:
+ neediness, id = deps.pop(0)
+ if neediness == 0:
+ create_list.append(id)
+ continue
+ else:
+ work = True
+ for req in graph[id]:
+ if req not in create_list:
+ work = False
+ continue
+ if work:
+ create_list.append(id)
+ else:
+ deps.append((neediness, id))
+ return create_list
+
+
+
+def get_needed(s, type_id):
+ #print type_id
+ q = {
+ "type" : "/type/type",
+ "id" : type_id,
+ "domain" : [{}],
+ "expected_by" : [{}],
+ "key" : [{"namespace" : None, "value" : None}],
+ "name" : {"value" : None, "lang" : "/lang/en", "optional":True},
+ "/freebase/type_hints/included_types" : [{}],
+ "/freebase/type_hints/mediator" : None,
+ "/freebase/type_hints/enumeration" : None,
+ "/freebase/documented_object/tip" : {"value" : None, "limit":1, "optional":True},
+ "properties" : [{
+ "optional" : True,
+ "delegated" : {},
+ "enumeration" : None,
+ "expected_type" : {},
+ "id" : None,
+ "key" : [{
+ "namespace" : None,
+ "value" : None
+ }],
+ #"link" : [{}],
+ "master_property" : {},
+ "name" : {"value" : None, "lang" : "/lang/en", "optional":True},
+ "reverse_property" : {},
+ "schema" : {"id" : None, "name" : None},
+ "unique" : None,
+ "unit" : None,
+ "/freebase/documented_object/tip" : {"value" : None, "limit":1, "optional" : True},
+ "/freebase/property_hints/disambiguator" : None
+ }]
+ }
+
+ r = s.mqlread(q)
+ properties = r.properties
+
+ #print "************************************************" + type_id
+ #pprint(r)
+ #print "************************************************" + type_id
+ # hopefully there's only one domain
+ fathers = map(lambda x: x["id"], r["domain"])
+
+ brothers = set()
+ included_types = map(lambda x: x["id"], r["/freebase/type_hints/included_types"])
+ brothers.update(included_types)
+ for prop in properties:
+ if prop["expected_type"]:
+ brothers.add(prop["expected_type"]["id"])
+
+
+ family = return_relevant(brothers, fathers)
+ needed = return_relevant(included_types, fathers)
+
+ # get property information
+ properties = r["properties"]
+ for prop in properties:
+ needs = set()
+ if prop["master_property"]:
+ needs.add(prop["master_property"]["id"])
+ if prop["delegated"]:
+ needs.add(prop["delegated"]["id"])
+
+ prop["needs"] = return_relevant(needs, fathers)
+
+ answer = r
+ answer.update(related=family, needs=needed, properties=properties)
+
+ return answer
+
+
+def return_relevant(start_list, fathers):
+ final = []
+ for item in start_list:
+ indomain = False
+ for father in fathers:
+ if item.startswith(father):
+ indomain = True
+ continue
+ if indomain:
+ final.append(item)
+ return final
+
+if __name__ == '__main__':
+
+ create_type_dependencies(s, base_id="/people")
+
+
diff --git a/schema-manipulation/type_creation.py b/schema-manipulation/type_creation.py
new file mode 100644
index 0000000..c29eb5d
--- /dev/null
+++ b/schema-manipulation/type_creation.py
@@ -0,0 +1,247 @@
+try:
+ import simplejson as json
+except ImportError:
+ import json
+
+import urllib
+from freebase.api import HTTPMetawebSession, MetawebError
+
+from freebase.api import LITERAL_TYPE_IDS
+
+mss = HTTPMetawebSession('sandbox.freebase.com', USERNAME, PASSWORD)
+mss.login()
+
+def key_exists( s, k ):
+ q = {
+ "id" : k,
+ "guid" : None }
+ return not None == s.mqlread( q )
+
+def create_type( s, name, key, ns, cvt=None, tip=None, enum=None, included=[]):
+ if key_exists( s, ns + "/" + key ):
+ return
+ q = {
+ "create" : "unconditional",
+ "type" : "/type/type",
+ "/type/type/domain" : { "connect" : "insert", "id" : ns },
+ "name" : {"connect" : "insert", "value" : name, "lang" : "/lang/en" },
+ "key" : {
+ "connect" : "insert",
+ "value" : key,
+ "namespace" : ns }
+ }
+
+ if included:
+ q['/freebase/type_hints/included_types'] = \
+ [ {"connect":"insert",
+ "id":included_id}
+ for included_id in included ]
+
+ if enum:
+ pass # TODO. What is enumerator?
+
+ if cvt:
+ q['/freebase/type_hints/mediator'] = { "connect" : "update", "value" : True }
+ if tip:
+ q['/freebase/documented_object/tip'] = { "connect" : "update", "value" : tip, "lang" : "/lang/en" }
+ s.mqlwrite( q )
+
+def create_property( s, name, key, schema, expected, unique, disambig=False, tip=None, extra=None ):
+ if key_exists( s, schema + "/" + key ):
+ return
+ q = {
+ "create" : "unconditional",
+ "type" : "/type/property",
+ "name" : name,
+ "key" : {
+ "connect" : "insert",
+ "value" : key,
+ "namespace" : { "id" : schema },
+ },
+ "schema" : { "connect" : "insert", "id" : schema },
+ "expected_type" : { "connect" : "insert", "id" : expected }
+ }
+ if unique:
+ q['unique'] = { "connect" : "update", "value" : unique }
+ if tip:
+ q['/freebase/documented_object/tip'] = { "connect" : "update", "value" : tip, "lang" : "/lang/en" }
+ if disambig:
+ q['/freebase/property_hints/disambiguator'] = { "connect" : "update", "value" : True }
+ if extra:
+ q.update(extra)
+ #print json.dumps(q, indent=2)
+ s.mqlwrite(q)
+
+def delegate_property( s, p, schema, name=None, key=None, expected=None, tip=None):
+ q = {
+ "id" : p,
+ "type" : "/type/property",
+ "name" : None,
+ "unique" : None,
+ "expected_type" : {"id" : None},
+ "key" : None,
+ "/freebase/documented_object/tip" : None,
+ "/freebase/property_hints/disambiguator" : None }
+ r = s.mqlread(q)
+
+ # If the expected_type of the delegator(master) is a primitive, the delegated's
+ # expected_type must be the same
+ if r["expected_type"]["id"] in LITERAL_TYPE_IDS:
+ if expected:
+ print "You can't set the expected_type if the expected_type of the delegated(master) is a primitive"
+ expected = r["expected_type"]["id"]
+ # If the expected_type of the delegator(master) is not a primitive, the delegated's
+ # expected_type can be different
+ elif expected is None:
+ expected = r["expected_type"]["id"]
+
+
+ if not tip and r["/freebase/documented_object/tip"]:
+ tip = r["/freebase/documented_object/tip"]
+
+ if name is None:
+ name = r["name"]
+ if key is None:
+ key = r["key"]
+
+ create_property(s, name, key, schema, expected, r['unique'],
+ r["/freebase/property_hints/disambiguator"],
+ tip,
+ { "/type/property/delegated" : p } )
+
+
+def reciprocate_property( s, name, key, master, unique, disambig=False, tip=None, extra=None ):
+ """ We're creating a reciprocate property of the master property. Let's illustrate
+ the idea behind the function with an example.
+
+ Say we examine the /visual_art/art_period_movement/associated_artworks property.
+ An example of an art_period_movement is the Renaissance, and once associated_artworks
+ could be the /en/mona_lisa. In this example, /visual_art/art_period_movement/associated_artworks
+ will be the master property, and /visual_art/artwork/period_or_movement will be the reciprocal.
+
+ In order to determine the characterists of the reciprocal property, we must examine the master.
+ associated_artworks property's schema is /visual_art/art_period_movement and its expected
+ type is /visual_art/artwork. Notice the similarity to /visual_art/artwork/period_or_movement.
+ period_or_movement's schema is /visual_art/artwork -- art_period_movement's expected type.
+ period_or_movement's expected type is /visual_art/art_period_movement -- art_period_movement's
+ schema!
+
+ So, given a master, the reciprocal's schema is the master's expected type and the reciprocal's
+ expected type is the master's schema. """
+
+
+ q = {
+ "id" : master,
+ "/type/property/expected_type" : None,
+ "/type/property/schema" : None }
+ r = s.mqlread(q)
+ ect = r["/type/property/expected_type"]
+ schema = r["/type/property/schema"]
+ create_property(s, name, key, ect, schema, unique, disambig, tip,
+ extra = { "master_property" : master })
+
+def make_subclass(s, sub, super):
+ q = {
+ "id" : super,
+ "type" : "/type/type",
+ "properties" : [{"id" : None}] }
+ r = s.mqlread( q )
+ for p in map(lambda x: x['id'], r['properties'] ):
+ delegate_property(s, p, sub)
+ w = {
+ "id" : sub,
+ "/freebase/type_hints/included_types" : { "connect" : "insert", "id" : super }}
+ s.mqlwrite(w)
+
+def gogo(s, base="/base/bingbase"):
+
+ create_type(s, "Bridge Player", "bridge_player", base, tip="A bridge player", included=["/people/person", "/common/topic", base+"/topic"])
+ create_type(s, "Bridge Tournament", "bridge_tournament", base, tip="A bridge tournament", included=["/event/event", "/common/topic", base+"/topic"])
+ create_type(s, "Bridge Tournament Standings", "bridge_tournament_standings", base, cvt=True, tip="Bridge Tournamen Results")
+
+ player = base + "/bridge_player"
+ tourney = base + "/bridge_tournament"
+ standing = base + "/bridge_tournament_standings"
+
+ # tournament standings
+ # ideas: create a cvt could be a function, disambig always True, same schema, iono, whatever
+ create_property(s, "Year", "year", standing, "/type/datetime", True, disambig=True, tip="Year")
+ create_property(s, "First Place", "first_place", standing, player, False, disambig=True)
+ create_property(s, "Second Place", "second_place", standing, player, False, disambig=True)
+ create_property(s, "Tournament", "tournament", standing, tourney, True, disambig=True)
+
+
+ # tournament
+ reciprocate_property(s, "Standing", "standing", standing + "/tournament", False, disambig=True)
+ create_property(s, "Location", "location", tourney, "/location/citytown", False, disambig=True)
+
+ # bridge player
+ # standings must be reverses!
+ reciprocate_property(s, "First Place Finish", "first_place_finish", standing + "/first_place", False, False)
+ reciprocate_property(s, "Second Place Finish", "second_place_finish", standing + "/second_place", False, False)
+
+ #delegator property test
+ delegate_property(mss, "/people/person/date_of_birth", player, "Date of Birth", "db")
+
+ # for cvt: expected_type: cvt, reciprocated property is the property on the cvt
+
+
+
+def create_chapter( s ):
+ create_type( s, "Chapter", "chapter", "/base/testy", True, "A chapter in one of the books" )
+ print "created book!"
+ create_property( s, "Book", "book", "/base/testy/chapter",
+ "/base/testy/book", True, True, "The book of which this chapter is a part" )
+ print "created property!"
+ reciprocate_property( s, "/base/testy/chapter/book",
+ "Chapters", "chapters", "/base/testy/book", False, False, "Chapters in this book" )
+
+def create_edition( s ):
+ create_type( s, "Edition", "edition", "/base/testy", True, "An edition of the Aubrey-Maturin series" )
+ create_property( s, "Examples", "examples", "/base/testy/edition",
+ "/book/book_edition", False, False, "Book editions in this series" )
+ w = {
+ "id" : "/base/testy/edition",
+ "/freebase/type_hints/enumeration" : { "value" : True, "connect" : "update" }}
+ s.mqlwrite( w )
+ w = {
+ "create" : "unless_exists",
+ "type" :"/base/testy/edition",
+ "name" : "W. W. Norton Paperback" }
+ s.mqlwrite( w )
+
+def create_page_ref( s ):
+ create_type( s, "Page Reference", "page_ref", "/base/testy", True,
+ "A reference to a page in a particular edition" )
+ t = "/base/testy/page_ref"
+ create_property( s, "Page Number", "page", t, "/type/int", True, True )
+ create_property( s, "Edition", "edition", t, "/base/testy/edition", True, True )
+
+def create_mention_properties( s, t ):
+ create_property( s, "Circumstances", "circumstances", t, "/type/text", True, True,
+ "Describe the circumstances of the mention" )
+ create_property( s, "Quote", "quote", t, "/type/text", True, True,
+ "A short quote from the mentioned location" )
+ create_property( s, "Chapter", "chapter", t, "/base/testy/chapter", True, True,
+ "The chapter in which the mention takes place" )
+ create_property( s, "Page", "page", t, "/base/testy/page_ref", False, True,
+ "Page number and Edition" )
+ create_property( s, "What", "what", t, "/base/testy/topic", True, True,
+ "What is being mentioned" )
+
+#def delegate_mention_properties( s ):
+# t = '/base/testy/mention'
+# delegate_property( s, '/base/testy/character_mention/character', t )
+# delegate_property( s, '/base/testy/dish_mention/dish', t )
+# delegate_property( s, '/base/testy/historical_event_mention/event', t )
+# delegate_property( s, '/base/testy/place_mention/place', t )
+# delegate_property( s, '/base/testy/ship_mention/ship', t )
+# delegate_property( s, '/base/testy/species_mention/species', t )
+# delegate_property( s, '/base/testy/written_work_mention/written_work', t )
+ # nothing for surgical instruments
+
+
+'''
+create_type( s, "Brew Pub", "brew_pub", "/base/brew_pubs", False, "A brew pub is a pub which brews its own beer on the premises" )
+delegate_property( s, '/food/brewery_brand_of_beer/beers_produced', '/base/brewpubs/brew_pub', None, 'Beers produced on the premises' )
+'''