Here is some code I wrote to compute FCM. I used this while learning about Fuzzy Systems. Just posted here for storage.
FCM is one of the technologies in field of Soft Computing.
// *************************************************************************
// File: FCM2.H ver. 0.03 Date: September 25, 1993
// By: Josef Betancourt System: Borland C++ ver. 2.0.
// *************************************************************************
/*
Purpose: Illustrate the Fuzzy Cognitive Map computations.
This is a very very simple implementation of the FCM example found in:
"Neural Networks and Fuzzy Systems". Kosko, B. page 154.
"Fuzzy Thinking, the new science of fuzzy logic". Kosko, B. page 222.
"Fuzzy Logic". McNeill D., Freiberger, P. page 237.
I used a very nice matrix class called Beginner's Understandable Matrix Package,
BUMP.ZIP, by Clopper Almon. It is found in the Borland C++ forum on CIS.
This version of my FCM implementation allows the setting of more than one
policy variable in the policy vector. This is accomplished by loading
a state setting i by 2 matrix. If column one is zero than cell i in the
policy vector is not reset by the state vector, else during the reasoning
process that cell is reset to the value in column two.
-------------------------------------------------------------------------
Of course, a general purpose interactive graphical system where the FCM
can be entered graphically by multiple experts and the inference process
is visually presented would be nice. It should be a FCM CAD system!
But are FCMs really useful? How are they used in control systems?
--------------------------------------------------------------------------
USE: This must be compiled and linked with BUMP.CPP. Large memory model.
Example FCM file Policy State
------------------------------------------------------------------
Africa AFRICA.TXT INVEST.TXT INVEST2.TXT
Africa AFRICA.TXT DIVEST.TXT DIVEST2.TXT
Cocaine COCAINE.TXT INTERDIC.TXT INTERDI2.TXT
To test the africa example,
Use the syntax: FCM africa.txt invest.txt invest2.txt 9 .5
or FCM africa.txt divest.txt divest2.txt 9 .5
To test the cocaine example in the book Fuzzy Thinking,
Use the syntax: FCM cocaine.txt interdic.txt interdi2.txt 11 .5
( this example does not result in cocaine supply falling as stated in
the book.)
*/
#ifndef FCM2_H
#define FCM2_H
// -----------------------
// dependencies
#include <iostream.h> // for cout
#include <ctype.h> // for isdigit()
#include <stdio.h> // for fgets()
#include <alloc.h> // for coreleft()
#include <stdlib.h> // for atof()
#include <conio.h> // for cprintf()
#include "bump.h" // for Matrix class
// -----------------------
#define TRUE (1==1)
#define FALSE (!TRUE)
class FCM; // forward reference.
// Prototypes
void Reason( FCM &fcm);
void Again(void);
void ThresholdMF( Matrix & mat, float thresh = .5);
void ConvertMat( Matrix & matDest, Matrix &matSrc);
void ResetPolicy( Matrix & matDest, Matrix &matSrc);
void ShowCondenseMP( Matrix &Mat);
void DrawBorder(void);
class FCM{ // Fuzzy Cognitive Map
protected:
Matrix *pmatFCM; // directed graph.
Matrix *pmatPolicy; // initial policy.
Matrix *pmatState; // policies to reset after epoch.
char *Names[]; // the labels of each node.
int nPolicies; // number of nodes.
float fThreshold;
public:
FCM( int n); // constructor.
// FCM( FCM other); // copy constructor.
// ~FCM(); // destructor.
void SetSizeI( int size){ nPolicies = size;}
void SetThresh( float fthr){ fThreshold = fthr; }
int IGetSize( void){ return nPolicies;}
void SetFCM( Matrix *fcm){ pmatFCM = fcm;}
void SetPolicy( Matrix *Policy){ pmatPolicy = Policy;}
void SetState( Matrix *State){ pmatState = State; }
void ReadFCM( char *psz);
float &Cell( Matrix *pmat, int i, int j);
float GetCell( Matrix *pmat, int i, int j);
void ReasonStep( void);
void ThresholdMF(void);
void ResetPolicy( void );
void DisplayPolicy( char *msg);
Matrix &WhatIsPolicy( void){ return *pmatPolicy ; }
void DumpPolicy(void);
};
// end of file FCM2.H
#endif
// *************************************************************************
// File: FCM2.CPP ver. 0.03 Date: September 25, 1993
// By: Josef Betancourt tcmits1@cs.com System: Borland C++ 4.0
// *************************************************************************
/*
Purpose: Illustrate the Fuzzy Cognitive Map computations.
*/
// dependencies....
#include "fcm2.h"
// -----------------------------------------
// constructor.
FCM::FCM( int size){
SetSizeI(size );
fThreshold = .5;
}
// -----------------------------------------
// get address of Cell.
float &FCM::Cell( Matrix *pmat, int i, int j){
return pmat->operator[](i)[j];
}
// -----------------------------------------
// get cell contents.
float FCM::GetCell( Matrix *pmat, int i, int j){
return pmat->operator[](i)[j];
}
// -----------------------------------------
//
void FCM::ReasonStep( void){
// Matrix multiply. Nice syntax!
*pmatPolicy = (*pmatPolicy)*(*pmatFCM);
//DisplayPolicy( "policy after multiply: ");
ThresholdMF();
//DisplayPolicy( "policy after threshold: ");
ResetPolicy();
//DisplayPolicy( "policy after reset: ");
}
// -----------------------------------------
// threshold policy vector.
void FCM::ThresholdMF( void ){
// apply thresh to policy matrix, default thresh is 0.5.
for( int i = 1; i < nPolicies + 1; i++){
if( GetCell( pmatPolicy, 1, i) >= fThreshold ){
Cell(pmatPolicy, 1, i) = 1.;
}else{
Cell( pmatPolicy, 1, i) = 0;
}
}
}
// -----------------------------------------
// reset policy with state vector.
void FCM::ResetPolicy( void ){
for( int i = 1; i < nPolicies+1; i++){
if( GetCell( pmatState, i,1) == 1){
Cell( pmatPolicy, 1, i) = GetCell(pmatState, i, 2) ;
}
}
}
// -----------------------------------------
// show policy using matrix library display routine.
void FCM::DisplayPolicy( char *message){
pmatPolicy->Display(message);
}
// -----------------------------------------
// dump policy as simple number dump.
void FCM::DumpPolicy(void){
for( int i=1; i < nPolicies+1; i++){
cout << GetCell( pmatPolicy, 1, i);
}
}
// -----------------------
int main(int argc, char * argv[]){
cout << "\n*** Fuzzy Cognitive Map example. By Josef Betancourt ***\n";
if( argc != 6 ){
cerr << "\nUsage: fcm <FCM file> <policy file> <state file>";
cerr << "<matrix size> <thresh>\n";
cerr << " Where cell and value refer to policy vector.\n";
exit (-1);
}
// convert strings to integers...........
int iSize = atoi(argv[4]); // matrix order.
float fThresh = atof( argv[5]); // threshold value.
FCM theFCM( iSize);
// create the helper matrices.
Matrix matFCM(iSize,iSize), matPolicy(1, iSize),
matVPolicy(1,iSize), matState( iSize, 2);
// link them into the FCM
theFCM.SetFCM( &matFCM);
theFCM.SetPolicy( &matPolicy);
theFCM.SetState( &matState);
theFCM.SetThresh( fThresh);
// populate using files
matFCM.ReadA( argv[1] );
matPolicy.ReadA( argv[2] );
matState.ReadA( argv[3] );
// and show matrices ..........
matFCM.Display("This is the FCM matrix:");
matPolicy.Display("This is the policy matrix: ");
matState.Display("This is the state matrix: ");
cout << "test of dump\n" ;
theFCM.DumpPolicy();
Again(); // wait for key tap or escape.
// perform the FCM process using the object.
Reason(theFCM );
return FALSE;
} // end of main.
// -----------------------
void Reason( FCM &fcm ){
// apply simple FCM computation using matrices.
int i = 1; // epoch counter.
while( 1){
cout << "Epoch " << i << '\n';
fcm.ReasonStep();
fcm.DisplayPolicy("New policy vector: ");
// for ease in seeing limit cycles.
ShowCondenseMP( fcm.WhatIsPolicy() );
DrawBorder();
Again(); // wait for key tap or escape.
i++;
}
} // reason end.
// -----------------------
void ShowCondenseMP( Matrix &Mat){
// print policy vector in a more visual pattern.
cout << "\nPattern: ";
char temp ;
for( int i=1; i< Mat.columns()+1; i++){
if( Mat[1][i] > 0 ){
temp = 0x2;
}else{
if( Mat[1][i] < 0){
temp = 0x1F;
}else{
temp = 0x1;
}
}
cout.put( temp);
}
cout << '\n' ;
}
// -----------------------
void DrawBorder(void){
cout << '\n';
for( int i=0; i<75; i++){
cout.put( char(0xDF) );
}
cout << '\n';
}
// -----------------------
void Again(void){
// query user for continuation or end of run.
cerr << "\n\t\t\t< Tap a key to continue. ESC to exit. >\n";
if(getch() == 27){
exit(0);
}
}
// ----------------------------------------------------------------------
/* computing Eigenvectors is similar to computing a FCM without the
thresholding. Here is such an algorithm.
void EigenTest(int size, char *pszName){
// algorithim from Computational Linear Algebra with Models.
// Williams, Gareth. Allyn and Bacon, Massachusetts. 1978. page 449.
float e, s, t;
int i, j, k, M;
Matrix A(size,size), X(size,1),Y(size,1),Z(size,1);
A.ReadA(pszName);
A.Display("Here is the B matrix:");
AllOnes( X);
while(1){
cout << "Iteration " << i << "\n";
Y = A * X;
Y.Display("Here is the Y matrix:");
k=1;
for( j=2; j < Y.rows()+1;j++){
if( fabs( Y[k][1]) >= fabs( Y[j][1]) ){
continue;
}
k= j;
}
Y = ( 1/ fabs( Y[k][1])) * Y;
X = Y;
X.Display("the adjusted vector is:");
Z = A*X;
s=0;
t=0;
for( M=1; M<size + 1; M++){
s += X[M][1] * Z[M][1];
t += X[M][1] * X[M][1];
}
e = s/t;
cout << "Approx eigenvalue is " << e << "\n" ;
Again();
}
}
*/
// -----------------------
// End of file FCM.CPP *********************************
Off topic
There are a lot of examples of connectionist presentations. I wonder if these could be coupled with the FCM technique to create computable structures. For example, look at the work of Mark Lombardi.
Links