home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 02 Useful Techniques / 08 Zarozinski / src / ffllapi / FFLLAPI.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-13  |  10.4 KB  |  447 lines

  1. //
  2. // File:    FFLLAPI.cpp
  3. //
  4. // Purpose:    API for FFLL
  5. //
  6. // Copyright ⌐ 2001 Louder Than A Bomb! Software
  7. //
  8. // This file is part of the FFLL (Free Fuzzy Logic Library) project (http://ffll.sourceforge.net)
  9. // It is released under the BSD license, see http://ffll.sourceforge.net/license.txt for the full text.
  10. //
  11.  
  12. // include files
  13. #include "FFLLAPI.h"
  14. #include "FFLLBase.h"
  15. #include "FuzzyModelBase.h"
  16. #include "FuzzyOutVariable.h"
  17. #include "MemberFuncBase.h"
  18. #include <vector>
  19.  
  20. class ModelContainer;    // forward declaration
  21.  
  22. // local function
  23. ModelContainer* get_model(int idx);
  24.  
  25. #ifdef _DEBUG
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29.  
  30. // Declare the classes here, rather than in a .h so everything is in one place
  31. // 
  32. // Class:    ModelChild
  33. //
  34. // This class represents a child of the FFLL model. Each child maintains
  35. // an array of indexes into the values[] array for each input variable and
  36. // an array of DOM (Degree of Membership) for the sets in the output variable.
  37. // This allows each child to be thread-safe and can pass this information to 
  38. // the FuzzyModelBase object to perform calcuations and get the defuzzified value.
  39. //
  40. // NOTE: This class currently is NOT thread-safe.
  41. //
  42.  
  43. class ModelChild
  44. {
  45.     // everything is public cuz these are only used in this file.
  46.     public:
  47.         ModelChild(const FuzzyModelBase* model)
  48.             {
  49.             assert(model != NULL);  
  50.  
  51.             int num_vars = model->get_input_var_count();
  52.             int num_out_sets = model->get_num_of_sets(OUTPUT_IDX);
  53.  
  54.             out_set_dom_arr = new DOMType[num_out_sets];
  55.              var_idx_arr = new short[num_vars];
  56.  
  57.             int i;    // counter
  58.  
  59.             for (i = 0; i < num_vars; i++)
  60.                   var_idx_arr[i] = 0;  
  61.  
  62.             for (i = 0; i < num_out_sets; i++)
  63.                    out_set_dom_arr[i] = 0; 
  64.  
  65.             }; // end constructor
  66.         virtual ~ModelChild()
  67.             {
  68.              if (var_idx_arr)
  69.                  delete[] var_idx_arr;
  70.             if (out_set_dom_arr)
  71.                 delete[] out_set_dom_arr;
  72.             };
  73.  
  74.         DOMType    *out_set_dom_arr;    // array of that holds the DOM for each set in the output variable
  75.         short  *var_idx_arr;        // array that holds the index into the values[] array for each input variable
  76.     
  77. }; // end class ModelChild
  78.  
  79. // 
  80. // Class:    ModelContainer
  81. //
  82. // This is a "container" for a model. It holds a pointer to a FuzzyModelBase
  83. // object and a list of children that can use the model. Each model can have multiple
  84. // children because model constains information that is common to all children and does
  85. // not change. 
  86. //
  87.  
  88. class ModelContainer
  89. {
  90.     // everything is public cuz these are only used in this file.
  91.     public:
  92.         ModelContainer()
  93.             {
  94.             model = NULL;
  95.             }    
  96.         
  97.         void init()
  98.             {
  99.             model = new FuzzyModelBase();
  100.             model->init();
  101.             };
  102.  
  103.         ModelContainer(const ModelContainer& copy_from)    
  104.             {
  105.             // raise an error if we have a model allocated. We shouldn't
  106.             // get here after the model was allocated, if we did the destrcutor
  107.             // is gonna be called and the model is going bye-bye.
  108.             assert(copy_from.model == NULL);
  109.             model = copy_from.model;
  110.             };
  111.  
  112.         virtual ~ModelContainer()
  113.             {
  114.               if (model)
  115.                 {
  116.                 delete model;
  117.                 model = NULL;
  118.                 }
  119.  
  120.             // free the memory we allocated for the children
  121.  
  122.             std::vector<ModelChild*>::iterator it = child_list.begin();
  123.             for (int i=0; it < child_list.end(); ++i, it++)
  124.                 {
  125.                 delete child_list[i];
  126.                 }
  127.  
  128.             }; // end destructor
  129.  
  130.          std::vector<ModelChild*> child_list;    // list of the children for this fuzzy model
  131.         FuzzyModelBase* model;                    // model this container holds
  132.  
  133. }; // end class ModelContainer
  134.  
  135.  
  136. // using a vector array to hold open models. It holds the actual object 
  137. // (as opposed to a pointer to it) so the destructor is called when the program ends
  138. // and we don't have to require the user to call a "close_model" type function to free memory.
  139.  
  140. std::vector<ModelContainer> model_list; // list of the fuzzy models being used
  141.  
  142. //
  143. // Function:    ffll_new_child()
  144. // 
  145. // Purpose:        Create a new child for the model passed in.
  146. //
  147. // Arguments:    
  148. //
  149. //        int        model_idx    - index of the model 
  150. //
  151. // Returns:
  152. //
  153. //        The index of the child for the model
  154. //        non-zero - failure
  155. //
  156. // Author:    Michael Zarozinski
  157. // Date:    9/01
  158. // 
  159. // Modification History
  160. // Author    Date        Modification
  161. // ------    ----        ------------
  162. //
  163. //  
  164. int __stdcall ffll_new_child(int model_idx)
  165. {
  166.     ModelContainer* container = get_model(model_idx);
  167.  
  168.     assert(container->model != NULL); // make sure you call ffll_load_fcl_file() before this func.
  169.  
  170.     ModelChild* child = new ModelChild(container->model);
  171.  
  172.     container->child_list.push_back(child);
  173.  
  174.     return container->child_list.size() - 1;
  175.  
  176. }; // end ffll_get_child()
  177.  
  178. //
  179. // Function:    ffll_set_value()
  180. // 
  181. // Purpose:        Set the variable's index for the value passed in.
  182. //
  183. // Arguments:    
  184. //
  185. //        int            model_idx    - index of the model 
  186. //        int            child_idx    - index of the child
  187. //        int            var_idx        - index of the variable
  188. //        RealType    value        - value to set the variable to
  189. //
  190. // Returns:
  191. //
  192. //        0 - success
  193. //        non-zero - failure
  194. //
  195. // Author:    Michael Zarozinski
  196. // Date:    9/01
  197. // 
  198. // Modification History
  199. // Author    Date        Modification
  200. // ------    ----        ------------
  201. //
  202. //  
  203. int __stdcall ffll_set_value(int model_idx, int child_idx, int var_idx, double value)
  204. {
  205.     ModelContainer* container = get_model(model_idx);
  206.  
  207.     ModelChild* child = container->child_list[child_idx];
  208.  
  209.     // convert value to an index into the values[] array
  210.     ValuesArrCountType idx = container->model->convert_value_to_idx(var_idx, value);
  211.          
  212.     child->var_idx_arr[var_idx] = idx;
  213.  
  214.     return 0;
  215.  
  216. }; // end ffll_set_value()
  217.  
  218. //
  219. // Function:    ffll_get_output_value()
  220. // 
  221. // Purpose:        Gets the defuzzified output value for
  222. //                the model/child pair passed in
  223. //
  224. // Arguments:    
  225. //
  226. //        int    model_idx    - index of the model 
  227. //        int    child_idx    - index of the child
  228. //
  229. // Returns:
  230. //
  231. //        Output value for the model (FLT_MIN is returned if no
  232. //        output sets are active)
  233. //
  234. // Author:    Michael Zarozinski
  235. // Date:    9/01
  236. // 
  237. // Modification History
  238. // Author    Date        Modification
  239. // ------    ----        ------------
  240. //
  241. // 
  242.  
  243. double __stdcall ffll_get_output_value(int model_idx, int child_idx)
  244. {
  245.     ModelContainer* container = get_model(model_idx);
  246.  
  247.     // get the child
  248.     ModelChild* child = container->child_list[child_idx];
  249.  
  250.     // pass in the input value for each input variable and the array
  251.     // of DOMs for the output sets
  252.     RealType out_val = container->model->calc_output(child->var_idx_arr, child->out_set_dom_arr); 
  253.  
  254.     return out_val;
  255.  
  256. }; // end ffll_get_output_value()
  257.  
  258.  
  259. //
  260. // Function:    ffll_load_fcl_file()
  261. // 
  262. // Purpose:        This function initializes the model and
  263. //                loads the FCL file passed in
  264. //
  265. // Arguments:    
  266. //
  267. //        int            model_idx    - index of the model 
  268. //        const char*    file        - file name and path of the file to load
  269. //
  270. // Returns:
  271. //
  272. //        The index of the model on success
  273. //        -1 on error
  274. //
  275. // Author:    Michael Zarozinski
  276. // Date:    9/01
  277. // 
  278. // Modification History
  279. // Author    Date        Modification
  280. // ------    ----        ------------
  281. //
  282. // 
  283.  
  284. int __stdcall ffll_load_fcl_file(int model_idx, const char* file)
  285. {
  286.     ModelContainer* container = get_model(model_idx);
  287.  
  288.     // we have a pointer to the container, so any modifications we
  289.     // make will be in the list. If we used the [] operator here,
  290.     // we'd get a COPY of the model and any changes wouldn't be permanent.
  291.  
  292.     // perform initialization
  293.     container->init();
  294.  
  295.     // load the FCL file passed in
  296.     if (container->model->load_from_fcl_file(file))
  297.          return -1;
  298.  
  299.     return model_idx;
  300.  
  301. }; // end ffll_load_fcl_file()
  302.  
  303.  
  304.  
  305. //
  306. // Function:    ffll_get_msg_textA()
  307. // 
  308. // Purpose:        Get the ascii character version of the msg_txt
  309. //                for the model.
  310. //
  311. // Arguments:    
  312. //
  313. //        int model_idx - index of the model to get the msg_txt for
  314. //
  315. // Returns:
  316. //
  317. //        const char* - pointer to the msg_txt string
  318. //
  319. // Author:    Michael Zarozinski
  320. // Date:    9/01
  321. // 
  322. // Modification History
  323. // Author    Date        Modification
  324. // ------    ----        ------------
  325. //
  326. // 
  327.  
  328. const char* __stdcall ffll_get_msg_textA(int model_idx)
  329. {
  330.     ModelContainer* container = get_model(model_idx);
  331.  
  332.     return container->model->get_msg_textA();
  333.  
  334. }; // end ffll_get_msg_textA()
  335.  
  336.  
  337. //
  338. // Function:    ffll_get_msg_textW()
  339. // 
  340. // Purpose:        Get the wide character version of the msg_txt
  341. //                for the model.
  342. //
  343. // Arguments:    
  344. //
  345. //        int model_idx - index of the model to get the msg_txt for
  346. //
  347. // Returns:
  348. //
  349. //        const wchar_t* - pointer to the msg_txt string
  350. //
  351. // Author:    Michael Zarozinski
  352. // Date:    9/01
  353. // 
  354. // Modification History
  355. // Author    Date        Modification
  356. // ------    ----        ------------
  357. //
  358. // 
  359. const wchar_t* __stdcall ffll_get_msg_textW(int model_idx)
  360. {
  361.     ModelContainer* container = get_model(model_idx);
  362.  
  363.     return container->model->get_msg_text();
  364.  
  365. }; // end ffll_get_msg_textW()
  366.  
  367.  
  368. //
  369. // Function:    ffll_new_model()
  370. // 
  371. // Purpose:        This function creates a new FuzzyModleBase object, inserts
  372. //                it into the managment list and returns the index of the new
  373. //                model into the list
  374. //
  375. // Arguments:    
  376. //
  377. //        none
  378. //
  379. // Returns:
  380. //
  381. //        The index of the model in the list
  382. //
  383. // Author:    Michael Zarozinski
  384. // Date:    9/01
  385. // 
  386. // Modification History
  387. // Author    Date        Modification
  388. // ------    ----        ------------
  389. //
  390. // 
  391. int __stdcall ffll_new_model()
  392. {
  393.     // create an empty container and put it at the back
  394.     // of our list. 
  395.     ModelContainer container;  
  396.   
  397.     // add it to the list of open models
  398.     model_list.push_back(container); // new_model);
  399.  
  400.     return model_list.size() - 1;
  401.  
  402. }; // end ffll_new_model()
  403.  
  404. //
  405. // Function:    get_model()
  406. // 
  407. // Purpose:        Returns a pointer to the model container at
  408. //                the index passed in. This is a LOCAL function
  409. //                and is not exported.
  410. //
  411. // Arguments:    
  412. //
  413. //        int idx - index of the model to return
  414. //
  415. // Returns:
  416. //
  417. //        ModelContainer*  - pointer to the model
  418. //
  419. // Author:    Michael Zarozinski
  420. // Date:    9/01
  421. // 
  422. // Modification History
  423. // Author    Date        Modification
  424. // ------    ----        ------------
  425. //
  426. //
  427. ModelContainer* get_model(int idx)
  428. {
  429.     // we have to use an interator (as opposed to just 
  430.     // using model_list[idx]) so we can return a pointer
  431.     // to the container. If we used the [] operator we'd
  432.     // get a copy and writing a "deep copy" for that object
  433.     // would introduce far more places things can go wrong.
  434.    
  435.     std::vector<ModelContainer>::iterator it;
  436.  
  437.     int tmp_idx = idx;
  438.  
  439.     it = model_list.begin();
  440.  
  441.     while(tmp_idx--)
  442.         it++;
  443.  
  444.     return it;
  445.                 
  446. } // end get_model()
  447.