aGrUM
0.20.3
a C++ library for (probabilistic) graphical models
DBCell.cpp
Go to the documentation of this file.
1
/**
2
*
3
* Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4
* info_at_agrum_dot_org
5
*
6
* This library is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU Lesser General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public License
17
* along with this library. If not, see <http://www.gnu.org/licenses/>.
18
*
19
*/
20
21
22
/** @file
23
* @brief The implementation of DBCells
24
*
25
* @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
26
*/
27
#
include
<
cstdio
>
28
#
include
<
agrum
/
tools
/
database
/
DBCell
.
h
>
29
30
31
#
ifndef
DOXYGEN_SHOULD_SKIP_THIS
32
33
/// include the inlined functions if necessary
34
#
ifdef
GUM_NO_INLINE
35
#
include
<
agrum
/
tools
/
database
/
DBCell_inl
.
h
>
36
#
endif
/* GUM_NO_INLINE */
37
38
namespace
gum
{
39
40
namespace
learning
{
41
42
// create the static members
43
int
DBCell
::
_string_max_index_
= 0;
44
45
46
Bijection
<
std
::
string
,
int
>&
DBCell
::
_strings_
() {
47
#
ifdef
GUM_DEBUG_MODE
48
static
bool
first_time
=
true
;
49
if
(
first_time
) {
50
first_time
=
false
;
51
__debug__
::
_dec_creation_
(
"Bijection"
,
" __strings"
, 0,
"BCell string bijection"
, 0);
52
__debug__
::
_dec_creation_
(
"BijectionImplementation"
,
53
" __strings"
,
54
0,
55
"BCell string bijection"
,
56
0);
57
__debug__
::
_dec_creation_
(
"HashTable"
,
" __strings"
, 0,
"BCell string bijection"
, 0);
58
__debug__
::
_dec_creation_
(
"HashTable"
,
" __strings"
, 0,
"BCell string bijection"
, 0);
59
}
60
#
endif
61
static
Bijection
<
std
::
string
,
int
>
strings
;
62
return
strings
;
63
}
64
65
66
// determines whether a string corresponds to an integer
67
bool
DBCell
::
isInteger
(
const
std
::
string
&
str
) {
68
if
(
str
.
empty
())
return
false
;
69
70
// trim the string
71
auto
start_iter
=
str
.
begin
() +
str
.
find_first_not_of
(
" \t"
);
72
auto
end_iter
=
str
.
begin
() +
str
.
find_last_not_of
(
" \t\r\n"
) + 1;
73
74
if
(
start_iter
==
end_iter
)
return
false
;
75
76
// if the number is negative, pass the '-' sign
77
if
(*
start_iter
==
'-'
) ++
start_iter
;
78
79
// check wether we have a number
80
for
(;
start_iter
!=
end_iter
; ++
start_iter
) {
81
if
((*
start_iter
<
'0'
) || (*
start_iter
>
'9'
))
return
false
;
82
}
83
84
return
true
;
85
}
86
87
88
// determines whether a string corresponds to an integer
89
bool
DBCell
::
isReal
(
const
std
::
string
&
str
) {
90
if
(
str
.
empty
())
return
false
;
91
92
// trim the string
93
auto
start_iter
=
str
.
begin
() +
str
.
find_first_not_of
(
" \t"
);
94
auto
end_iter
=
str
.
begin
() +
str
.
find_last_not_of
(
" \t\r\n"
) + 1;
95
96
if
(
start_iter
==
end_iter
)
return
false
;
97
98
// check wether we have a number
99
bool
has_dot
=
false
;
100
bool
has_exponent
=
false
;
101
bool
has_digit
=
false
;
102
bool
has_negation
=
false
;
103
for
(;
start_iter
!=
end_iter
; ++
start_iter
) {
104
if
(*
start_iter
==
'-'
) {
105
if
(
has_negation
)
return
false
;
106
}
else
if
(*
start_iter
==
'.'
) {
107
if
(
has_dot
||
has_exponent
)
return
false
;
108
has_dot
=
true
;
109
}
else
if
((*
start_iter
==
'e'
) || (*
start_iter
==
'E'
)) {
110
if
(
has_exponent
|| !
has_digit
)
return
false
;
111
has_exponent
=
true
;
112
has_negation
=
false
;
113
}
else
if
((*
start_iter
<
'0'
) || (*
start_iter
>
'9'
))
114
return
false
;
115
else
116
has_digit
=
true
;
117
}
118
119
return
true
;
120
}
121
122
123
// try to convert the content of the DBCell into another type
124
bool
DBCell
::
convertType
(
const
EltType
new_type
) {
125
if
(
new_type
==
_type_
)
return
true
;
126
switch
(
new_type
) {
127
// ===================================
128
case
EltType
::
REAL
:
129
switch
(
_type_
) {
130
case
EltType
::
INTEGER
:
131
_val_real_
=
float
(
_val_integer_
);
132
_type_
=
EltType
::
REAL
;
133
return
true
;
134
135
case
EltType
::
STRING
:
136
try
{
137
const
std
::
string
&
str
=
_strings_
().
first
(
_val_index_
);
138
if
(!
isReal
(
str
))
return
false
;
139
_val_real_
=
std
::
stof
(
str
);
140
_type_
=
EltType
::
REAL
;
141
return
true
;
142
}
catch
(
std
::
invalid_argument
&) {
return
false
; }
143
144
case
EltType
::
MISSING
:
145
return
false
;
146
147
default
:
148
GUM_ERROR
(
NotImplementedYet
,
"type not supported by DBCell convertType"
)
149
}
150
151
// ===================================
152
case
EltType
::
INTEGER
:
153
switch
(
_type_
) {
154
case
EltType
::
REAL
: {
155
const
int
nb
=
int
(
_val_real_
);
156
if
(
nb
==
_val_real_
) {
157
_val_integer_
=
nb
;
158
_type_
=
EltType
::
INTEGER
;
159
return
true
;
160
}
else
161
return
false
;
162
}
163
164
case
EltType
::
STRING
:
165
try
{
166
const
std
::
string
&
str
=
_strings_
().
first
(
_val_index_
);
167
if
(!
isInteger
(
str
))
return
false
;
168
_val_integer_
=
std
::
stoi
(
str
);
169
_type_
=
EltType
::
INTEGER
;
170
return
true
;
171
}
catch
(
std
::
invalid_argument
&) {
return
false
; }
172
173
case
EltType
::
MISSING
:
174
return
false
;
175
176
default
:
177
GUM_ERROR
(
NotImplementedYet
,
"type not supported by DBCell convertType"
)
178
}
179
180
// ===================================
181
case
EltType
::
STRING
:
182
switch
(
_type_
) {
183
case
EltType
::
REAL
: {
184
char
buffer
[100];
185
sprintf
(
buffer
,
"%g"
,
_val_real_
);
186
const
std
::
string
str
(
buffer
);
187
if
(!
_strings_
().
existsFirst
(
str
)) {
188
_strings_
().
insert
(
str
,
_string_max_index_
);
189
_val_index_
=
_string_max_index_
;
190
++
_string_max_index_
;
191
}
else
{
192
_val_index_
=
_strings_
().
second
(
str
);
193
}
194
}
195
_type_
=
EltType
::
STRING
;
196
return
true
;
197
198
case
EltType
::
INTEGER
: {
199
const
std
::
string
str
=
std
::
to_string
(
_val_integer_
);
200
if
(!
_strings_
().
existsFirst
(
str
)) {
201
_strings_
().
insert
(
str
,
_string_max_index_
);
202
_val_index_
=
_string_max_index_
;
203
++
_string_max_index_
;
204
}
else
{
205
_val_index_
=
_strings_
().
second
(
str
);
206
}
207
}
208
_type_
=
EltType
::
STRING
;
209
return
true
;
210
211
case
EltType
::
MISSING
:
212
return
false
;
213
214
default
:
215
GUM_ERROR
(
NotImplementedYet
,
"type not supported by DBCell convertType"
)
216
}
217
218
// ===================================
219
case
EltType
::
MISSING
:
220
_type_
=
EltType
::
MISSING
;
221
return
true
;
222
223
default
:
224
GUM_ERROR
(
NotImplementedYet
,
"type not supported by DBCell convertType"
)
225
}
226
227
return
false
;
228
}
229
230
231
// raises an appropriate exception when encountering a type error
232
std
::
string
DBCell
::
_typeErrorMsg_
(
const
std
::
string
&
true_type
)
const
{
233
std
::
stringstream
str
;
234
switch
(
_type_
) {
235
case
EltType
::
REAL
:
236
str
<<
"The DBCell contains a real number instead of "
<<
true_type
;
237
break
;
238
239
case
EltType
::
INTEGER
:
240
str
<<
"The DBCell contains an integer instead of "
<<
true_type
;
241
break
;
242
243
case
EltType
::
STRING
:
244
str
<<
"The DBCell contains a string instead of "
<<
true_type
;
245
break
;
246
247
case
EltType
::
MISSING
:
248
str
<<
"The DBCell contains a missing value instead of "
<<
true_type
;
249
break
;
250
251
default
:
252
GUM_ERROR
(
NotImplementedYet
,
"DBCell type not implemented yet"
)
253
}
254
255
return
str
.
str
();
256
}
257
258
}
/* namespace learning */
259
260
}
/* namespace gum */
261
262
#
endif
/* DOXYGEN_SHOULD_SKIP_THIS */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643
gum::learning::genericBNLearner::Database::Database
Database(const std::string &filename, const BayesNet< GUM_SCALAR > &bn, const std::vector< std::string > &missing_symbols)
Definition:
genericBNLearner_tpl.h:31