Skip to content

Commit bca1336

Browse files
committed
add graph with maps and create function
1 parent cb3dd64 commit bca1336

File tree

5 files changed

+189
-48
lines changed

5 files changed

+189
-48
lines changed

src/.merlin

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
EXCLUDE_QUERY_DIR
22
B ../_build/default/src/.words.eobjs/byte
33
S .
4-
FLG -w @[email protected]@30..39@[email protected]@[email protected] -strict-sequence -strict-formats -short-paths -keep-locs
4+
FLG -open Dune__exe -w @[email protected]@30..39@[email protected]@[email protected] -strict-sequence -strict-formats -short-paths -keep-locs

src/concept.ml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
1+
(** A graph representation of a DL-like knowledge base. *)
22

33
module StrMap = Map.Make(String)
44

@@ -8,10 +8,10 @@ let find_list s map =
88
| Some l -> l
99
| None -> []
1010

11-
(* need separate types for role type and relation instance?
12-
* or a role instance can just be a (role * concept) in the concept *)
11+
1312
type concept = {
1413
cid: string;
14+
(* Map from role name to list of role instances of that type. *)
1515
mutable roles: role_inst_concept list StrMap.t
1616
}
1717
and role = { (* a role /type/. *)
@@ -69,20 +69,33 @@ let add_role c1 role c2 =
6969
)
7070

7171
module ConceptGraph = struct
72-
type t = concept list
72+
type t = {
73+
cmap: concept StrMap.t;
74+
rmap: role StrMap.t;
75+
}
76+
77+
let create clist rlist = {
78+
cmap = List.fold_left
79+
(fun map concept ->
80+
StrMap.add concept.cid concept map)
81+
StrMap.empty
82+
clist;
83+
rmap = List.fold_left
84+
(fun map role ->
85+
StrMap.add role.rid role map)
86+
StrMap.empty
87+
rlist;
88+
}
89+
(* Yay, now I can add inferences corresponding to questions. *)
7390
(* function to add concept, check for duplicate name *)
7491
(* function to add relation between concepts, check restrictions *)
75-
let add_concept (g: t) c =
76-
c :: g
92+
(* let add_concept (g: t) c =
93+
c :: g *)
7794
end
7895

79-
(* oh. it's meaningless to make restrictions on the subclass relation,
80-
* because subclass itself is the terms in which restrictions are stated. *)
81-
8296
(* need a concept-maker and a relation-adder that checks everything.
8397
* ...and makes indexes of relations by type *)
8498

85-
(* a concept is a node in a graph *)
8699

87100
(* Can i encode in the type system that superclass/subclass relations are
88101
* only allowed between node of same category? *)

src/ontoOne.ml renamed to src/upperOnto.ml

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
(** Upper ontology
2+
* These concepts and roles may be assumed in inference methods. *)
13

24
open Concept
35

4-
(* start by specifying the root ontology in code.*)
56
let universal_concept: concept = { cid="Concept"; roles=StrMap.empty }
7+
let entity: concept = { cid="Entity"; roles=StrMap.empty }
68
let physical_object: concept = { cid="Physical_object"; roles=StrMap.empty }
79
let abstract_object: concept = { cid="Abstract_object"; roles=StrMap.empty }
810
let property: concept = { cid="Property"; roles=StrMap.empty }
@@ -21,22 +23,37 @@ and superclass: role = {
2123
range = universal_concept;
2224
transitive = true;
2325
inverse = Some subclass
24-
}
26+
}
2527

2628
let rec disjoint_with: role = {
27-
rid = "disjoint_with";
29+
rid = "disjointWith";
2830
domain = universal_concept;
2931
range = universal_concept;
3032
transitive = false;
3133
inverse = Some disjoint_with (* it's own inverse! Yeah! *)
3234
}
3335

34-
let () = add_role universal_concept superclass physical_object
35-
let () = add_role physical_object subclass universal_concept
36+
let has_property: role = {
37+
rid = "hasProperty";
38+
domain = entity;
39+
range = property;
40+
transitive = false;
41+
inverse = None
42+
}
43+
44+
(* entity <-> universal *)
45+
let () = add_role universal_concept superclass entity
46+
let () = add_role entity subclass universal_concept
3647

37-
let () = add_role universal_concept superclass abstract_object
38-
let () = add_role abstract_object subclass universal_concept
48+
(* physical <-> entity *)
49+
let () = add_role entity superclass physical_object
50+
let () = add_role physical_object subclass entity
3951

52+
(* abstract <-> entity *)
53+
let () = add_role entity superclass abstract_object
54+
let () = add_role abstract_object subclass entity
55+
56+
(* property <-> universal *)
4057
let () = add_role universal_concept superclass property
4158
let () = add_role property subclass universal_concept
4259

@@ -49,3 +66,18 @@ let () = add_role physical_object disjoint_with property
4966

5067
let () = add_role property disjoint_with abstract_object
5168
let () = add_role abstract_object disjoint_with property
69+
70+
let upper_ontology =
71+
ConceptGraph.create
72+
[ universal_concept;
73+
entity;
74+
physical_object;
75+
abstract_object;
76+
property
77+
]
78+
[ superclass;
79+
subclass;
80+
disjoint_with;
81+
has_property
82+
]
83+

src/vocab.ml

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,41 @@
11

22
open Words
33

4-
let st = StringyString.of_string
5-
6-
let walk = StrWord.create ~baseform:(st "walk") ~posdata:[
7-
Vb {tag="VB"; vbs=S; prespart=Ing; past=Ed; pastpart=Ed}
8-
]
4+
let st = StringEx.of_string
5+
6+
let person = StrWord.create ~baseform:(st "person") ~lexdata:[
7+
Nn {countable=true; plural=Irreg(st "people")}
8+
]
9+
10+
let walk = StrWord.create ~baseform:(st "walk") ~lexdata:[
11+
Vb {vbs=S; prespart=Ing; past=Ed; pastpart=Ed};
12+
Nn {countable=true; plural=S}
13+
]
14+
15+
let ride = StrWord.create ~baseform:(st "ride") ~lexdata:[
16+
Vb {vbs=S; prespart=Eing;
17+
past=Irreg (st "rode"); pastpart=Edden};
18+
Nn {countable=true; plural=S}
19+
]
20+
21+
let hide = StrWord.create ~baseform:(st "hide") ~lexdata:[
22+
Vb {vbs=S; prespart=Eing;
23+
past=Irreg (st "hid"); pastpart=Edden};
24+
Nn {countable=true; plural=S}
25+
]
26+
27+
let have = StrWord.create ~baseform:(st "have") ~lexdata:[
28+
Vb {vbs=Irreg (st "has"); prespart=Eing;
29+
past=Irreg (st "had"); pastpart=Irreg (st "had")}
30+
]
31+
32+
(* maybe add a "fullconj" option, but for terminological knowledge,
33+
* we can do without first and second person for now. *)
34+
let be = StrWord.create ~baseform:(st "be") ~lexdata:[
35+
Vb {vbs=Irreg (st "is"); prespart=Ing;
36+
past=Irreg (st "was"); pastpart=Irreg (st "been")}
37+
]
38+
39+
let all_words = [ person; walk; ride; hide; have; be ]
40+
41+
module VocabMap = Map.Make(StringEx)

src/words.ml

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ type 's pluralform =
1010

1111
type 's pastform =
1212
| Ed
13-
| Dded (* consonant doubling *)
14-
| Yied
13+
| Dded (* consonant doubling: "clapped" *)
14+
| Yied (* change y to i *)
15+
| Edden (* for the past participle "ridden" *)
1516
| Irreg of 's
1617

1718
type 's ingform =
1819
| Ing
19-
| Dding
20-
| Eing (* what was this for? *)
20+
| Dding (* consonant doubling *)
21+
| Eing (* drop the e *)
2122
| Irreg of 's
2223

2324
(* Need to store noun and verb /types/ also: transitive/intransitive,
@@ -33,24 +34,26 @@ type 's ingform =
3334
(* Just put the tag string in the record, and when I make the map, I just
3435
* pull it out and add the tag separately. That's how a map works anyway. *)
3536

36-
type 's nouninfo = { tag: string;
37-
countable: bool;
37+
type 's nouninfo = { countable: bool;
3838
plural: 's pluralform } (* Gerund? Infinitive? *)
3939

4040
(* thinking that different forms of a verb can be in one record. *)
41-
type 's verbinfo = { tag: string;
42-
vbs: 's pluralform;
41+
type 's verbinfo = { vbs: 's pluralform;
4342
prespart: 's ingform;
4443
past: 's pastform;
4544
pastpart: 's pastform }
4645

4746
(* Still need a dictionary to POS lookup of a word *)
4847
(* Actually, a datatype for a word with specific POS *)
49-
type 's posinfo =
48+
type 's lexinfo =
5049
| Nn of 's nouninfo
5150
| Vb of 's verbinfo
5251
| Jj
5352
| Rb
53+
| Prep
54+
| Pron
55+
| Conj
56+
| Det
5457

5558
(* idea: word module parameterized by a module that has a
5659
* "string" type that supports character indexing. This way we can support
@@ -65,7 +68,9 @@ module type STRINGY = sig
6568
val length : t -> int
6669
val sub : t -> int -> int -> t
6770
val of_string : string -> t
71+
val show : t -> string
6872
val append : t -> t -> t
73+
val append_r : t -> t -> t
6974
val compare : t -> t -> int
7075
end
7176

@@ -76,39 +81,97 @@ module Word = functor (St: STRINGY) -> struct
7681
module StSet = Set.Make(St)
7782
type t = {
7883
baseform: St.t;
79-
posdata: St.t posinfo list;
80-
posdict: St.t posinfo PosMap.t;
81-
allforms: StSet.t
84+
lexdata: St.t lexinfo list;
85+
(* posdict: St.t lexinfo PosMap.t; (* gen_entry takes care... *)
86+
allforms: StSet.t *)
8287
}
8388
type sentence = (St.t * t) list
84-
let create ~baseform ~posdata = {
85-
baseform; posdata;
86-
posdict = PosMap.empty;
87-
allforms = StSet.empty
89+
let create ~baseform ~lexdata = {
90+
baseform;
91+
lexdata;
92+
(* posdict = PosMap.empty;
93+
allforms = StSet.empty *)
8894
}
8995
(* Parse from JSON/Xml? *)
9096
let rtrim s n = St.sub s 0 (St.length s - n)
91-
let to_string w = w.baseform (* maybe not actual string *)
92-
(* let add_plural w pl = match pl with
93-
| S -> { w with plural = St.append w.baseform (St.of_string "s") }
94-
| Es -> { w with plural = St.append w.baseform (St.of_string "es") }
95-
| Yies -> { w with
96-
plural = St.append (rtrim w.baseform 1) (St.of_string "ies") }
97-
| Irreg s -> { w with plural = s } *)
97+
let to_string w = w.baseform (* just a hack to print the base form *)
98+
let pluralize baseform pltype = match pltype with
99+
| S -> St.append baseform (St.of_string "s")
100+
| Es -> St.append baseform (St.of_string "es")
101+
| Yies -> St.append (rtrim baseform 1) (St.of_string "ies")
102+
| Irreg s -> s
103+
let add_ing baseform ingtype = match ingtype with
104+
| Ing -> St.append baseform (St.of_string "ing")
105+
| Dding ->
106+
let dcons = St.sub baseform (St.length baseform - 1) 1
107+
in
108+
St.append baseform dcons
109+
|> St.append_r (St.of_string "ing")
110+
| Eing -> St.append (rtrim baseform 1) (St.of_string "ing")
111+
| Irreg s -> s
112+
let add_past baseform pastform = match pastform with
113+
| Ed -> St.append baseform (St.of_string "ed")
114+
| Dded ->
115+
let dcons = St.sub baseform (St.length baseform - 1) 1
116+
in
117+
St.append baseform dcons
118+
|> St.append_r (St.of_string "ed")
119+
| Yied -> rtrim baseform 1
120+
|> St.append_r (St.of_string "ied")
121+
| Edden ->
122+
let len = St.length baseform in
123+
let dcons = St.sub baseform (len-2) 1
124+
in
125+
St.append (rtrim baseform 1) dcons
126+
|> St.append_r (St.of_string "en")
127+
| Irreg s -> s
128+
(* Generate all lexicon entries from string to (string, POS, t) triples
129+
* (originally just lexinfo, but t has the base in it too, so good) *)
130+
let gen_entry w =
131+
w.lexdata
132+
|> List.map (function
133+
| Nn { countable; plural } ->
134+
if countable then [
135+
(w.baseform, "NN-S", w);
136+
(pluralize w.baseform plural, "NN-P", w)
137+
]
138+
else []
139+
| Vb { vbs; prespart; past; pastpart } -> [
140+
(w.baseform, "VP-S", w);
141+
(pluralize w.baseform vbs, "VB-P", w);
142+
(add_ing w.baseform prespart, "VB-G", w);
143+
(add_past w.baseform past, "VB-D", w);
144+
(add_past w.baseform pastpart, "VB-N", w)
145+
]
146+
| Jj -> [ (w.baseform, "JJ-S", w) ]
147+
| Rb -> [ (w.baseform, "RB-S", w) ]
148+
| Conj -> [ (w.baseform, "CJ", w) ]
149+
| Det -> [ (w.baseform, "DT", w) ]
150+
| Prep -> [ (w.baseform, "IN", w) ]
151+
| Pron -> [ (w.baseform, "PN", w) ]
152+
)
153+
|> List.concat
98154
end
99155

100156
(* String-specific module implementations start here. *)
101157

102-
module StringyString : STRINGY = struct
158+
module StringEx : STRINGY = struct
103159
include String
104160
type c = char
105161
let of_string s = s
162+
let show s = s
106163
let append s1 s2 = s1 ^ s2
164+
let append_r s1 s2 = s2 ^ s1
107165
end
108166

167+
(* For the toplevel pretty-printer *)
168+
let format_stringex fmt ss =
169+
Format.fprintf fmt "\"%s\"" (StringEx.show ss)
170+
171+
109172
(* Eventually want to parameterize by the language too...or,
110173
* Just have a different Word module of same signature *)
111-
module StrWord = Word(StringyString)
174+
module StrWord = Word(StringEx)
112175

113176
(* Assumes word also includes punctuation. *)
114177
type sentence = (string * StrWord.t) list

0 commit comments

Comments
 (0)