bayesnet 0.0.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +6 -29
- data/README.md +5 -2
- data/Rakefile +5 -2
- data/bayesnet.gemspec +0 -1
- data/doc/morning-mood-model.png +0 -0
- data/lib/bayesnet/dsl.rb +4 -0
- data/lib/bayesnet/error.rb +2 -0
- data/lib/bayesnet/factor.rb +138 -41
- data/lib/bayesnet/graph.rb +114 -13
- data/lib/bayesnet/logging.rb +13 -0
- data/lib/bayesnet/node.rb +25 -9
- data/lib/bayesnet/parsers/bif.rb +2484 -0
- data/lib/bayesnet/parsers/bif.treetop +250 -0
- data/lib/bayesnet/parsers/builder.rb +37 -0
- data/lib/bayesnet/version.rb +1 -1
- data/lib/bayesnet.rb +7 -0
- metadata +6 -16
@@ -0,0 +1,250 @@
|
|
1
|
+
require "treetop"
|
2
|
+
|
3
|
+
module Bayesnet
|
4
|
+
module Parsers
|
5
|
+
grammar Bif
|
6
|
+
include Bayesnet::Parsers::Builder
|
7
|
+
|
8
|
+
rule CompilationUnit
|
9
|
+
SEP NetworkDeclaration list:( VariableDeclaration / ProbabilityDeclaration )* SEP {
|
10
|
+
def nodes
|
11
|
+
list.elements.select { |e| e.respond_to?(:node) }.map(&:node)
|
12
|
+
end
|
13
|
+
|
14
|
+
def cpts
|
15
|
+
list.elements.select { |e| e.respond_to?(:cpt) }.map(&:cpt)
|
16
|
+
end
|
17
|
+
}
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
rule NetworkDeclaration
|
22
|
+
SEP NETWORK SEP WORD SEP NetworkContent SEP
|
23
|
+
end
|
24
|
+
|
25
|
+
rule NetworkContent
|
26
|
+
SEP "{" ( SEP Property )* SEP "}" SEP
|
27
|
+
end
|
28
|
+
|
29
|
+
rule VariableDeclaration
|
30
|
+
SEP VARIABLE SEP probabilityVariableName SEP variableContent SEP {
|
31
|
+
def node
|
32
|
+
values = variableContent.values
|
33
|
+
[probabilityVariableName.text_value.to_sym, values]
|
34
|
+
end
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
rule variableContent
|
39
|
+
SEP "{" list:(SEP Property / variableDiscrete )* SEP "}" SEP {
|
40
|
+
def values
|
41
|
+
list.elements.select { |e| e.respond_to?(:values) }.map(&:values).flatten
|
42
|
+
end
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
rule variableDiscrete
|
47
|
+
SEP VARIABLETYPE SEP DISCRETE SEP "[" SEP DECIMAL_LITERAL SEP "]" SEP "{" SEP variableValuesList SEP "}" SEP ";" SEP {
|
48
|
+
def values
|
49
|
+
variableValuesList.values
|
50
|
+
end
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
rule variableValuesList
|
55
|
+
SEP probabilityVariableValue list:( SEP probabilityVariableValue )* {
|
56
|
+
def values
|
57
|
+
[probabilityVariableValue.value] + list.elements.map { |e| e.elements[1].value }.flatten
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
rule probabilityVariableValue
|
63
|
+
VALUE {
|
64
|
+
def value
|
65
|
+
self.text_value.to_sym
|
66
|
+
end
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
rule ProbabilityDeclaration
|
71
|
+
SEP PROBABILITY SEP probabilityVariablesList SEP probabilityContent SEP {
|
72
|
+
def cpt
|
73
|
+
{ variable: probabilityVariablesList.value,
|
74
|
+
parents: probabilityVariablesList.parents,
|
75
|
+
cpt: probabilityContent.cpt}
|
76
|
+
end
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
rule probabilityVariablesList
|
81
|
+
SEP "(" SEP probabilityVariableName list:( SEP probabilityVariableName )* SEP ")" SEP {
|
82
|
+
def value
|
83
|
+
probabilityVariableName.value
|
84
|
+
end
|
85
|
+
|
86
|
+
def parents
|
87
|
+
list.elements.map { |e| e.elements[1].value }.flatten
|
88
|
+
end
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
rule probabilityVariableName
|
93
|
+
WORD {
|
94
|
+
def value
|
95
|
+
self.text_value.to_sym
|
96
|
+
end
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
rule probabilityContent
|
101
|
+
SEP "{" SEP list:( SEP Property / ProbabilityDefaultEntry / ProbabilityEntry / ProbabilityTable )* SEP "}" SEP {
|
102
|
+
def cpt
|
103
|
+
distributions = list.elements.select { |e| e.respond_to?(:given) }.map do |e|
|
104
|
+
{given: e.given,
|
105
|
+
distribution: e.distribution}
|
106
|
+
end
|
107
|
+
table = list.elements.select { |e| e.respond_to?(:table) }.map do |e|
|
108
|
+
{table: e.table}
|
109
|
+
end
|
110
|
+
if distributions.empty? && !table.empty?
|
111
|
+
return table.first
|
112
|
+
elsif !distributions.empty? && table.empty?
|
113
|
+
return distributions
|
114
|
+
elsif distributions.empty? && table.empty?
|
115
|
+
raise "Either distributions or table must be provided"
|
116
|
+
else
|
117
|
+
raise "Both - distributions or table cannot be provided at the same time"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
rule ProbabilityEntry
|
124
|
+
SEP probabilityValuesList SEP floatingPointList SEP ";" SEP {
|
125
|
+
def given
|
126
|
+
probabilityValuesList.values
|
127
|
+
end
|
128
|
+
def distribution
|
129
|
+
floatingPointList.values
|
130
|
+
end
|
131
|
+
}
|
132
|
+
end
|
133
|
+
|
134
|
+
rule probabilityValuesList
|
135
|
+
SEP "(" SEP probabilityVariableValue list:( SEP probabilityVariableValue )* SEP ")" {
|
136
|
+
def values
|
137
|
+
[probabilityVariableValue.value] + list.elements.map { |e| e.elements[1].value }
|
138
|
+
end
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
rule ProbabilityDefaultEntry
|
143
|
+
SEP floatingPointList SEP ";" SEP {
|
144
|
+
def values
|
145
|
+
floatingPointList.values
|
146
|
+
end
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
rule ProbabilityTable
|
151
|
+
SEP TABLEVALUE SEP floatingPointList SEP ";" SEP {
|
152
|
+
def table
|
153
|
+
floatingPointList.values
|
154
|
+
end
|
155
|
+
}
|
156
|
+
end
|
157
|
+
|
158
|
+
rule floatingPointList
|
159
|
+
SEP floatingPointToken list:( SEP floatingPointToken )* {
|
160
|
+
def values
|
161
|
+
[floatingPointToken.value] + list.elements.map {|e| e.elements[1]}.select { |e| e.respond_to?(:value) }.map(&:value)
|
162
|
+
end
|
163
|
+
}
|
164
|
+
end
|
165
|
+
|
166
|
+
rule floatingPointToken
|
167
|
+
FLOATING_POINT_LITERAL {
|
168
|
+
def value
|
169
|
+
self.text_value.to_f
|
170
|
+
end
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
rule Property
|
175
|
+
PROPERTYSTRING
|
176
|
+
end
|
177
|
+
|
178
|
+
rule NETWORK
|
179
|
+
'network'
|
180
|
+
end
|
181
|
+
|
182
|
+
rule VARIABLE
|
183
|
+
'variable'
|
184
|
+
end
|
185
|
+
|
186
|
+
rule PROBABILITY
|
187
|
+
'probability'
|
188
|
+
end
|
189
|
+
|
190
|
+
rule PROPERTY
|
191
|
+
'property'
|
192
|
+
end
|
193
|
+
|
194
|
+
rule VARIABLETYPE
|
195
|
+
'type'
|
196
|
+
end
|
197
|
+
|
198
|
+
rule DISCRETE
|
199
|
+
'discrete'
|
200
|
+
end
|
201
|
+
|
202
|
+
rule DEFAULTVALUE
|
203
|
+
'default'
|
204
|
+
end
|
205
|
+
|
206
|
+
rule TABLEVALUE
|
207
|
+
'table'
|
208
|
+
end
|
209
|
+
|
210
|
+
rule WORD
|
211
|
+
LETTER (LETTER / DIGIT)*
|
212
|
+
end
|
213
|
+
|
214
|
+
rule LETTER
|
215
|
+
[a-zA-Z_-]
|
216
|
+
end
|
217
|
+
|
218
|
+
rule VALUE
|
219
|
+
[/<>=.+a-zA-Z_0-9-]+
|
220
|
+
end
|
221
|
+
|
222
|
+
rule DIGIT
|
223
|
+
[0-9]
|
224
|
+
end
|
225
|
+
|
226
|
+
rule DECIMAL_LITERAL
|
227
|
+
DIGIT DIGIT*
|
228
|
+
end
|
229
|
+
|
230
|
+
rule FLOATING_POINT_LITERAL
|
231
|
+
DIGIT+ '.' DIGIT* EXPONENT?
|
232
|
+
/ '.' DIGIT+ EXPONENT?
|
233
|
+
/ DIGIT+ EXPONENT
|
234
|
+
end
|
235
|
+
|
236
|
+
rule EXPONENT
|
237
|
+
[eE] [+-]? DIGIT+
|
238
|
+
end
|
239
|
+
|
240
|
+
rule PROPERTYSTRING
|
241
|
+
PROPERTY .* ';'
|
242
|
+
end
|
243
|
+
|
244
|
+
rule SEP
|
245
|
+
[\r\n\t ,|]*
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# lib/builder.rb
|
2
|
+
|
3
|
+
module Bayesnet::Parsers
|
4
|
+
module Builder
|
5
|
+
def build(input)
|
6
|
+
parsed = parse(input)
|
7
|
+
nodes = parsed.nodes.to_h
|
8
|
+
|
9
|
+
net = Bayesnet.define do
|
10
|
+
end
|
11
|
+
|
12
|
+
parsed.cpts.each do |cpt|
|
13
|
+
variable = cpt[:variable]
|
14
|
+
case cpt[:cpt]
|
15
|
+
when Array
|
16
|
+
net.node(variable, parents: cpt[:parents]) do
|
17
|
+
values nodes[variable] do
|
18
|
+
cpt[:cpt].each do |entry|
|
19
|
+
as entry[:distribution], given: entry[:given]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
when Hash
|
24
|
+
raise 'Table CPT for variable with parents is not supported' unless cpt[:parents].empty?
|
25
|
+
|
26
|
+
table = cpt[:cpt][:table]
|
27
|
+
net.node(variable, parents: []) do
|
28
|
+
values nodes[variable].zip(table).to_h
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
net.resolve_factors
|
34
|
+
net
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/bayesnet/version.rb
CHANGED
data/lib/bayesnet.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "set"
|
4
|
+
require "logger"
|
4
5
|
|
6
|
+
# net
|
7
|
+
require_relative "bayesnet/logging"
|
5
8
|
require_relative "bayesnet/dsl"
|
6
9
|
require_relative "bayesnet/error"
|
7
10
|
require_relative "bayesnet/factor"
|
8
11
|
require_relative "bayesnet/version"
|
9
12
|
|
13
|
+
# parsing
|
14
|
+
require_relative "bayesnet/parsers/builder"
|
15
|
+
require_relative "bayesnet/parsers/bif"
|
16
|
+
|
10
17
|
module Bayesnet
|
11
18
|
extend Bayesnet::DSL
|
12
19
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bayesnet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aleksandr Furmanov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: m
|
@@ -52,20 +52,6 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 3.9.0
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: standard
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.3'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '1.3'
|
69
55
|
description:
|
70
56
|
email:
|
71
57
|
- aleksandr.furmanov@gmail.com
|
@@ -91,7 +77,11 @@ files:
|
|
91
77
|
- lib/bayesnet/error.rb
|
92
78
|
- lib/bayesnet/factor.rb
|
93
79
|
- lib/bayesnet/graph.rb
|
80
|
+
- lib/bayesnet/logging.rb
|
94
81
|
- lib/bayesnet/node.rb
|
82
|
+
- lib/bayesnet/parsers/bif.rb
|
83
|
+
- lib/bayesnet/parsers/bif.treetop
|
84
|
+
- lib/bayesnet/parsers/builder.rb
|
95
85
|
- lib/bayesnet/version.rb
|
96
86
|
homepage: https://github.com/afurmanov/bayesnet
|
97
87
|
licenses:
|