root/vtcross/trunk/src/cognitive_engines/CBR.cpp @ 544

Revision 544, 8.1 KB (checked in by bhilburn, 14 years ago)

Moved the implementation for the CBR into its own file, now compiling it
into a static archive for linking into other CEs.

Line 
1/*
2 Copyright 2009 Virginia Polytechnic Institute and State University 
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/*! This file contains the default implementation of the CBR class, defined in
18 * the cbr.h include file.  This implementation is compiled into a static
19 * library which can be used as as backend for any cognitive engine. */
20
21
22#include "vtcross/cbr.h"
23
24
25using namespace std;
26
27
28/* This is an internal debugging function used by some sqlite3 function calls.
29 *  It is not used otherwise in the CROSS codebase. */
30int32_t
31callback(void *notUsed, int32_t argc, char **argv, char **azColName)
32{
33    for(size_t i = 0; i < argc; i++) {
34        LOG("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
35    }
36    LOG("\n");
37
38    return 0;
39}
40
41
42CBR::CBR(string _filename, string _tablename, string _cols[], uint32_t _len)
43{
44    /* Store database properties. */
45    filename = _filename;
46    tablename = _tablename;
47    numColumns = _len;
48
49    /* Create the database (or open it if it already exists). */
50    OpenDatabase();
51
52    /* Generate the command that will create the initial table within the
53     * CROSS database. */
54    command = "CREATE TABLE " + tablename + "(";
55    for(size_t i = 0; i < numColumns; i++) {
56        command += _cols[i] + " FLOAT";
57
58        /* If this column is not the last entry, add a comma to the command in
59         * preperation for the next entry. */
60        if(i != numColumns - 1)
61            command += ", ";
62    }
63    command += ");";
64
65    /* Execute the generated command. At this point, the database is ready for
66     * use. */
67    ExecuteCommand();
68}
69
70
71CBR::CBR(string _filename, string _tablename, string _cols[], \
72        string _primcols[], uint32_t _len, uint32_t _primlen)
73{
74    /* Store database properties. */
75    filename = _filename;
76    tablename = _tablename;
77    numColumns = _len;
78
79    /* Create the database (or open it if it already exists). */
80    OpenDatabase();
81
82    /* Generate the command that will create the initial table within the
83     * CROSS database with primary keys. */
84    command = "CREATE TABLE " + tablename + "(";
85    for(size_t i = 0; i < numColumns; i++) {
86        command += _cols[i] + " FLOAT, ";
87    }
88
89    command += "PRIMARY KEY (";
90    for(size_t j = 0; j < _primlen; j++) {
91        command += _primcols[j];
92
93        /* If this column is not the last entry, add a comma to the command in
94         * preperation for the next entry. */
95        if(j != _primlen - 1)
96            command += ", ";
97    }
98    command += "));";
99
100    /* Execute the generated command. At this point, the database is ready for
101     * use. */
102    ExecuteCommand();
103}
104
105
106CBR::~CBR()
107
108    /* Generate the sqlite command to delete a table and all of its contents,
109     * and then execute it. */
110    command = "drop table " + tablename;
111    ExecuteCommand();
112
113    /* Tell sqlite to clean up the database. */
114    command = "vacuum";
115    ExecuteCommand();
116}
117
118
119int32_t
120CBR::OpenDatabase()
121{
122    int32_t rc = sqlite3_open(filename.c_str(), &db);
123    if(rc) {
124        WARNING("Can't open database: %s\n", sqlite3_errmsg(db));
125        sqlite3_close(db);
126        exit(1);
127    }
128
129    return rc;
130}
131
132
133int32_t
134CBR::ExecuteCommand()
135{
136    char *zErrMsg = 0;
137
138    int32_t rc = sqlite3_exec(db, command.c_str(), callback, 0, &zErrMsg);
139    if(rc != SQLITE_OK) {
140        WARNING("SQL error: %s: %s\n", zErrMsg, command.c_str());
141        sqlite3_free(zErrMsg);
142    }
143
144    return rc;
145}
146
147
148int32_t
149CBR::ExecuteSearchCommand(float *_retvals)
150{
151    sqlite3_stmt *pStatement;
152
153    int32_t rc = sqlite3_prepare_v2(db, command.c_str(), -1, &pStatement, NULL);
154    if(rc == SQLITE_OK) {
155        if(sqlite3_step(pStatement) == SQLITE_ROW) {
156            for(size_t i = 0; i < numColumns; ++i) {
157                _retvals[i] = sqlite3_column_double(pStatement, i);
158            }
159        } else {
160                    LOG("CBR:: No matched results returning default.\n");
161                        rc = 31337;
162                }
163    } else {
164                WARNING("CBR:: Error executing SQL statement. rc = %i\n%s\n", rc, command.c_str());
165    }
166
167    sqlite3_finalize(pStatement);
168   
169    return rc;
170}
171
172
173void
174CBR::Print()
175{
176    /* Generate the sqlite command to print the database, which is effectively a
177     * 'select all elements' command, and then execute it. */
178    command = "select " + tablename + ".* from " + tablename + ";";
179
180    ExecuteCommand();
181    LOG("database %s, table %s:\n", filename.c_str(), tablename.c_str());
182}
183
184
185int32_t
186CBR::Search(string _names[], int32_t *_ops, float *_vals, uint32_t _n, \
187        float *_retvals)
188{   
189    char str_buffer[64];
190    const string ops_str[] = {"==", "!=", ">", ">=", "<", "<="};
191
192    command = "select " + tablename + ".* from " + tablename + " where ";
193
194    for(size_t i = 0; i < _n; i++) {
195        /* Make sure that the passed ops value is valid. */
196        if((_ops[i] < 0) || (_ops[i] > 5)) {
197            ERROR(1, "Error: cbr_search(), invalid ops id : %d\n", _ops[i]);
198        }
199
200        command += _names[i] + ops_str[_ops[i]];
201
202
203        sprintf(str_buffer, "%E", _vals[i]);
204        command += string(str_buffer);
205
206        if(i < _n - 1)
207            command += " AND ";
208        else
209            command += " order by utility desc;";
210       
211    }
212    //LOG("CBR::Search - command: %s\n", command.c_str());
213
214    return ExecuteSearchCommand(_retvals);
215}
216
217
218int32_t
219CBR::SearchSum(string _name, float *_retvals)
220{   
221    command = "select SUM(" + tablename + "." + _name + ") from " + tablename + ";";
222
223    return ExecuteSearchCommand(_retvals);
224}
225
226
227int32_t
228CBR::SearchRand(string _names[], int32_t *_ops, float *_vals, uint32_t _n, \
229        float *_retvals)
230{   
231    char str_buffer[64];
232    const char *ops_str[] = {"==", "!=", ">", ">=", "<", "<="};
233
234    command = "select " + tablename + ".* from " + tablename + " where ";
235
236    for(size_t i = 0; i < _n; i++) {
237        /* Make sure that the passed ops value is valid. */
238        if((_ops[i] < 0) || (_ops[i] > 5)) {
239            ERROR(1, "Error: cbr_search(), invalid ops id : %d\n", _ops[i]);
240        }
241
242        command += _names[i] + ops_str[_ops[i]];
243
244        sprintf(str_buffer, "%E", _vals[i]);
245        command += str_buffer;
246
247        if(i < _n - 1)
248            command += " AND ";
249        else
250            command += " order by RAND();";
251    }
252
253    return ExecuteSearchCommand(_retvals);
254}
255
256
257int32_t
258CBR::Update(string _where[], string _set[], float *_wherevals, float *_setvals,
259                uint32_t _wherelen, uint32_t _setlen)
260{
261    char str_buffer[64];
262
263    /* Generate the command to update the table. */
264    command = "UPDATE " + tablename + " SET ";
265
266    for(size_t i = 0; i < _setlen; i++) {
267        command += _set[i] + " = ";
268        sprintf(str_buffer, "%f", _setvals[i]);
269        command += string(str_buffer) + "  ";
270
271        if(i != _setlen - 1)
272            command += ", ";
273    }
274    command += " WHERE ";
275
276    for(size_t j = 0; j < _wherelen; j++) {
277        command += _where[j] + " = ";
278        sprintf(str_buffer, "%f", _wherevals[j]);
279        command += string(str_buffer) + "  ";
280
281        if(j != _wherelen - 1)
282            command += "AND ";
283    }
284    command += ";";
285   
286    return ExecuteCommand();
287}
288
289
290int32_t
291CBR::AddRow(string _cols[], float *_vals, uint32_t _len)
292{
293    char str_buffer[64];
294
295    command = "insert into " + tablename + " (";
296
297    for(size_t i = 0; i < _len; i++) {
298        command += _cols[i];
299
300        if(i != numColumns - 1)
301            command += ", ";
302    }
303    command += ") values(";
304
305    for(size_t j = 0; j < _len; j++) {
306        // TODO I have no idea what the below question is about.
307        // ???? how to fill the values if numColumns != _len
308        // assume = in the following
309        sprintf(str_buffer, "%f", _vals[j]);
310        command += str_buffer;
311
312        if(j != numColumns - 1)
313            command += ", ";
314    }
315    command += ");";
316   
317    return ExecuteCommand();
318}
319
Note: See TracBrowser for help on using the browser.