cycr 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +0 -0
- data/Rakefile +23 -0
- data/cycr.gemspec +20 -0
- data/lib/cycr/assertion.rb +14 -0
- data/lib/cycr/client.rb +208 -0
- data/lib/cycr/collection.rb +76 -0
- data/lib/cycr/constants.rb +8 -0
- data/lib/cycr/domains.lisp +584 -0
- data/lib/cycr/extensions.rb +26 -0
- data/lib/cycr/nart.rb +21 -0
- data/lib/cycr/parser.rb +63 -0
- data/lib/cycr/sexpr.flex +74 -0
- data/lib/cycr/sexpr.rex +55 -0
- data/lib/cycr/sexpr.rex.rb +136 -0
- data/lib/cycr/words_reader.lisp +204 -0
- data/lib/cycr.rb +1 -0
- data/spec/assertion.rb +36 -0
- data/spec/client.rb +39 -0
- metadata +101 -0
data/README.txt
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
task :default => [:install]
|
2
|
+
|
3
|
+
$gem_name = "cycr"
|
4
|
+
|
5
|
+
desc "Build the gem"
|
6
|
+
task :build do
|
7
|
+
sh "gem build #$gem_name.gemspec"
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Install the library at local machnie"
|
11
|
+
task :install => :build do
|
12
|
+
sh "sudo gem install #$gem_name -l"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Uninstall the library from local machnie"
|
16
|
+
task :uninstall do
|
17
|
+
sh "sudo gem uninstall #$gem_name"
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "Clean"
|
21
|
+
task :clean do
|
22
|
+
sh "rm #$gem_name*.gem"
|
23
|
+
end
|
data/cycr.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "cycr"
|
3
|
+
s.version = "0.0.3"
|
4
|
+
s.date = "2010-10-19"
|
5
|
+
s.summary = "Ruby client for the (Open)Cyc server"
|
6
|
+
s.email = "apohllo@o2.pl"
|
7
|
+
s.homepage = "http://www.opencyc.org"
|
8
|
+
s.require_path = "lib"
|
9
|
+
s.description = "Ruby wrapper for (Open)Cyc server and ontology"
|
10
|
+
s.has_rdoc = false
|
11
|
+
s.authors = ['Aleksander Pohl']
|
12
|
+
s.files = ["Rakefile", "cycr.gemspec", 'lib/cycr.rb'] +
|
13
|
+
Dir.glob("lib/**/*")
|
14
|
+
s.test_files = Dir.glob("spec/**/*")
|
15
|
+
s.rdoc_options = ["--main", "README.txt"]
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.extra_rdoc_files = ["README.txt"]
|
18
|
+
s.add_dependency("rspec", [">= 1.2.9"])
|
19
|
+
end
|
20
|
+
|
data/lib/cycr/client.rb
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'net/telnet'
|
2
|
+
|
3
|
+
module Cyc
|
4
|
+
# Author:: Aleksander Pohl (mailto:apohllo@o2.pl)
|
5
|
+
# License:: MIT License
|
6
|
+
#
|
7
|
+
# This class is the implementation of the Cyc server client.
|
8
|
+
class Client
|
9
|
+
# If set to true, all communication with the server is logged
|
10
|
+
# to standard output
|
11
|
+
attr_accessor :debug
|
12
|
+
attr_reader :host, :port
|
13
|
+
# Creates new Client.
|
14
|
+
def initialize(host="localhost",port="3601",debug=false)
|
15
|
+
@debug = debug
|
16
|
+
@host = host
|
17
|
+
@port = port
|
18
|
+
@pid = Process.pid
|
19
|
+
@parser = Parser.new
|
20
|
+
@mts_cache = {}
|
21
|
+
|
22
|
+
# read domains mapings
|
23
|
+
# talk(File.read(File.join(
|
24
|
+
# File.dirname(__FILE__), 'domains.lisp')))
|
25
|
+
|
26
|
+
# read utility functions
|
27
|
+
talk(File.read(File.join(
|
28
|
+
File.dirname(__FILE__), 'words_reader.lisp')))
|
29
|
+
|
30
|
+
# wait untill files are processed
|
31
|
+
send_message("(define end-of-routines () ())")
|
32
|
+
while answer = receive_answer do
|
33
|
+
break if answer =~ /END-OF-ROUTINES/
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# (Re)connects to the cyc server.
|
38
|
+
def reconnect
|
39
|
+
@pid = Process.pid
|
40
|
+
@conn = Net::Telnet.new("Port" => @port, "Telnetmode" => false,
|
41
|
+
"Timeout" => 600, "Host" => @host)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the connection object. Ensures that the pid of current
|
45
|
+
# process is the same as the pid, the connection was initialized with.
|
46
|
+
#
|
47
|
+
# If the block is given, the command is guarded by assertion, that
|
48
|
+
# it will be performed, even if the connection was reset.
|
49
|
+
def connection
|
50
|
+
#puts "#{@pid} #{Process.pid}"
|
51
|
+
if @conn.nil? or @pid != Process.pid
|
52
|
+
reconnect
|
53
|
+
end
|
54
|
+
if block_given?
|
55
|
+
begin
|
56
|
+
yield @conn
|
57
|
+
rescue Errno::ECONNRESET
|
58
|
+
reconnect
|
59
|
+
yield @conn
|
60
|
+
end
|
61
|
+
else
|
62
|
+
@conn
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
protected :connection, :reconnect
|
67
|
+
|
68
|
+
def clear_cache
|
69
|
+
@mts_cache = {}
|
70
|
+
end
|
71
|
+
|
72
|
+
# Closes connection with the server
|
73
|
+
def close
|
74
|
+
connection{|c| c.puts("(api-quit)")}
|
75
|
+
@conn = nil
|
76
|
+
end
|
77
|
+
|
78
|
+
NART_QUERY =<<-END
|
79
|
+
(clet ((result ())
|
80
|
+
(call-value :call))
|
81
|
+
(pif (listp call-value)
|
82
|
+
(cdolist (el call-value)
|
83
|
+
(pif (nart-p el)
|
84
|
+
(cpush (nart-id el) result)
|
85
|
+
(cpush el result)))
|
86
|
+
(pif (nart-p call-value)
|
87
|
+
(cpush (nart-id call-value) result)
|
88
|
+
(cpush call-value result)))
|
89
|
+
result)
|
90
|
+
END
|
91
|
+
|
92
|
+
|
93
|
+
# Sends message +msg+ directly to the Cyc server and receives
|
94
|
+
# the answer.
|
95
|
+
def talk(msg, options={})
|
96
|
+
#conn.puts(msg.respond_to?(:to_cyc) ? msg.to_cyc : msg)
|
97
|
+
msg = NART_QUERY.sub(/:call/,msg) if options[:nart]
|
98
|
+
|
99
|
+
send_message(msg)
|
100
|
+
receive_answer(options)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Send the raw message.
|
104
|
+
def send_message(msg)
|
105
|
+
@last_message = msg
|
106
|
+
puts "Send: #{msg}" if @debug
|
107
|
+
connection{|c| c.puts(msg)}
|
108
|
+
end
|
109
|
+
|
110
|
+
# Receive answer from server.
|
111
|
+
def receive_answer(options={})
|
112
|
+
answer = connection{|c| c.waitfor(/./)}
|
113
|
+
puts "Recv: #{answer}" if @debug
|
114
|
+
if answer.nil?
|
115
|
+
raise "Unknwon error occured. " +
|
116
|
+
"Check the submitted query in detail!"
|
117
|
+
end
|
118
|
+
while not answer =~ /\n/ do
|
119
|
+
next_answer = connection{|c| c.waitfor(/./)}
|
120
|
+
puts "Recv: #{next_answer}" if @debug
|
121
|
+
if answer.nil?
|
122
|
+
answer = next_answer
|
123
|
+
else
|
124
|
+
answer += next_answer
|
125
|
+
end
|
126
|
+
end
|
127
|
+
# XXX ignore some potential asynchronous answers
|
128
|
+
answer = answer.split("\n")[-1]
|
129
|
+
answer = answer.sub(/(\d\d\d) (.*)/,"\\2")
|
130
|
+
if($1.to_i == 200)
|
131
|
+
begin
|
132
|
+
result = @parser.parse(answer,options[:stack])
|
133
|
+
result = options[:nart] ? substitute_narts(result) : result
|
134
|
+
rescue Parser::ContinueParsing => ex
|
135
|
+
result = ex.stack
|
136
|
+
current_result = result
|
137
|
+
last_message = @last_message
|
138
|
+
while current_result.size == 100 do
|
139
|
+
send_message("(subseq #{last_message} #{result.size} " +
|
140
|
+
"#{result.size + 100})")
|
141
|
+
current_result = receive_answer(options)
|
142
|
+
result.concat(current_result)
|
143
|
+
end
|
144
|
+
result
|
145
|
+
end
|
146
|
+
else
|
147
|
+
unless $2.nil?
|
148
|
+
puts $2.sub(/^"/,"").sub(/"$/,"") + "\n" +
|
149
|
+
@last_message
|
150
|
+
else
|
151
|
+
puts "unknown error!"
|
152
|
+
end
|
153
|
+
nil
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def method_missing(name,*args)
|
159
|
+
#"_missing_method_#{name}"
|
160
|
+
method_name = name.to_s.gsub("_","-").sub(/-nart$/,"")
|
161
|
+
options = {}
|
162
|
+
def method_name.to_cyc(quote=false)
|
163
|
+
self
|
164
|
+
end
|
165
|
+
options[:nart] = true if name.to_s =~ /_nart$/
|
166
|
+
talk(([method_name] + args).to_cyc,options)
|
167
|
+
end
|
168
|
+
|
169
|
+
DENOTATION_QUERY =<<-END
|
170
|
+
(nart-denotation-mapper ":word")
|
171
|
+
END
|
172
|
+
|
173
|
+
def denotation_mapper(name)
|
174
|
+
send_message(DENOTATION_QUERY.sub(/:word/,name))
|
175
|
+
receive_answer(:nart => true)
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
# Finds collection with given name. The name has to
|
180
|
+
# be the name of the exact name of the constant.
|
181
|
+
def find_collection(name)
|
182
|
+
term = self.find_constant(name)
|
183
|
+
Collection.new(term, self) unless term.nil?
|
184
|
+
end
|
185
|
+
|
186
|
+
protected
|
187
|
+
|
188
|
+
def substitute_narts(terms)
|
189
|
+
unless terms.nil?
|
190
|
+
terms.collect{|t| t.is_a?(String) ? Cyc::Nart.new(t,self) : t}
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def relevant_mts(term)
|
195
|
+
@mts_cache[term] ||=
|
196
|
+
(mts = self.term_mts(term)
|
197
|
+
if mts
|
198
|
+
mts.select{|mt| mt.is_a? Symbol}.
|
199
|
+
reject{|mt| IRRELEVANT_MTS.include?(mt)}
|
200
|
+
else
|
201
|
+
[]
|
202
|
+
end)
|
203
|
+
end
|
204
|
+
|
205
|
+
def with_reconnect
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Cyc
|
2
|
+
class Collection
|
3
|
+
attr_reader :symbol
|
4
|
+
|
5
|
+
def initialize(symbol, cyc)
|
6
|
+
@symbol = symbol
|
7
|
+
@cyc = cyc
|
8
|
+
@printed = false
|
9
|
+
end
|
10
|
+
|
11
|
+
def printed?
|
12
|
+
@printed
|
13
|
+
end
|
14
|
+
|
15
|
+
def parents
|
16
|
+
unless @parents
|
17
|
+
parents = @cyc.min_genls(symbol)
|
18
|
+
@parents = if parents
|
19
|
+
parents.map{|p| Collection.new(p,@cyc)}
|
20
|
+
else
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
@parents
|
25
|
+
end
|
26
|
+
|
27
|
+
def children
|
28
|
+
unless @children
|
29
|
+
children = @cyc.max_specs(symbol)
|
30
|
+
if children
|
31
|
+
@children = children.map{|p| Collection.new(p,@cyc)}
|
32
|
+
else
|
33
|
+
@children = []
|
34
|
+
end
|
35
|
+
end
|
36
|
+
@children
|
37
|
+
end
|
38
|
+
|
39
|
+
def comment
|
40
|
+
@cyc.comment(@symbol)
|
41
|
+
end
|
42
|
+
|
43
|
+
def lexemes()
|
44
|
+
default_str = [@cyc.symbol_str(symbol)]
|
45
|
+
aux_strs = @cyc.symbol_strs(symbol) || []
|
46
|
+
(default_str + aux_strs).uniq.compact.join(", ")
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_s
|
50
|
+
@symbol.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def ==(other)
|
54
|
+
return false unless other.is_a? Collection
|
55
|
+
self.symbol == other.symbol
|
56
|
+
end
|
57
|
+
|
58
|
+
def =~(other)
|
59
|
+
return false unless other.is_a? Collection
|
60
|
+
self.parents - other.parents == [] &&
|
61
|
+
other.parents - self.parents == []
|
62
|
+
end
|
63
|
+
|
64
|
+
def ancestor?(node)
|
65
|
+
return true if node == :Thing
|
66
|
+
ancestors = @parents.dup
|
67
|
+
while !ancestors.empty?
|
68
|
+
ancestor = ancestors.shift
|
69
|
+
return true if ancestor == node
|
70
|
+
ancestors += ancestor.parents
|
71
|
+
ancestors.uniq!
|
72
|
+
end
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end # Node
|
76
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module Cyc
|
2
|
+
# These Microteories contain non-ontological assertions.
|
3
|
+
IRRELEVANT_MTS = [:WordNetMappingMt, :EnglishMt, :UniversalVocabularyMt,
|
4
|
+
:BaseKB, :CycHistoricalPossibilityTheoryMt, :SENSUSMappingMt,
|
5
|
+
:GeneralLexiconMt, :BookkeepingMt, :CycNounLearnerMt, :HPKBVocabMt,
|
6
|
+
:SKSIMt, :TopicMt, :SNOMEDMappingMt, :MeSHMappingMt, :CycNounLearnerMt,
|
7
|
+
:TheMotleyFoolUKCorpusMt, :AnalystDatabaseMt, :CyclistsMt ]
|
8
|
+
end
|