Building FCM with input from the experts

The fcmpy is a Python package for automatically generating causal weights for fuzzy cognitive maps based on qualitative inputs (by using fuzzy logic), optimizing the FCM connection matrix via Machine Learning Algorithms, and testing what-if scenarios. The package includes the following submodules:

  • ExpertFcm
  • Simulation
  • Intervention
  • ML

The ExpertFcm module includes methods for deriving causal weights of an FCM based on qualitative data.
The FcmSimulator module provides methods for running simulations on top of a given FCM structure.
The FcmIntervention module allows testing what-if scenarios on top of the specified FCMs.

First import all necessar libraries and fix randomness
In [1]:
import numpy as np
import matplotlib.pylab as plt
import seaborn as sns 
from fcmpy.simulator.transfer import Sigmoid, Bivalent, Trivalent, HyperbolicTangent
import os 
import pandas as pd
In [2]:
# fixed randomness 
import random
random.seed(42) # Set the random number generator to a fixed sequence.

Examples

Below we present the fast implementation of the library. More specifically, how to construct an FCM based on the supplied data using Fuzzy Logic, run simulations on a defined FCMs and test interventions on top of the defined FCM structure.

Building FCMs based on qualitative inputs using Fuzzy Logic

Step 1: Generate Fuzzy Membership Functions

Here we generate triangular fuzzy membership functions for 11 linguistic terms.

In [3]:
from fcmpy import ExpertFcm, FcmSimulator, FcmIntervention 
       # Defining range for each linguistic term, where middle value means where the membership of the linguistic term will have value 1.    

fcm = ExpertFcm()
fcm.linguistic_terms = {
                        '-VH': [-1, -1, -0.75],
                        '-H': [-1, -0.75, -0.50],
                        '-M': [-0.75, -0.5, -0.25], 
                        '-L': [-0.5, -0.25, 0],
                        '-VL': [-0.25, 0, 0],
                        'NA': [-0.001, 0, 0.001],
                        '+VL': [0, 0, 0.25],
                        '+L': [0, 0.25, 0.50],
                        '+M': [0.25, 0.5, 0.75],
                        '+H': [0.5, 0.75, 1],
                        '+VH': [0.75, 1, 1]
                        }
                          

In [4]:
fcm.universe = np.arange(-1, 1.05, .05)
              # Creating "universe" using membership functions defined above. It is necessary to do it, otherwise we won't be able to transform linguistic variables into numeric ones    
fcm.fuzzy_membership = fcm.automf(method='trimf')

```

Let's take a look at the generated membership functions.

plot the membership functions

In [5]:
mfs = fcm.fuzzy_membership
              # Plotting membership functions for each linguistic term    
fig = plt.figure(figsize= (10, 5))
axes = plt.axes()

for i in mfs:
    axes.plot(fcm.universe, mfs[i], linewidth=0.4, label=str(i))
    axes.fill_between(fcm.universe, mfs[i], alpha=0.5)

axes.legend(bbox_to_anchor=(0.95, 0.6))

axes.spines['top'].set_visible(False)
axes.spines['right'].set_visible(False)
axes.get_xaxis().tick_bottom()
axes.get_yaxis().tick_left()
plt.tight_layout()

What you should see in the output

Step 2: Build FCMs based on qualitative input data using Fuzzy Logic

  • Read data from a csv file.
In [6]:
data = fcm.read_data(file_path= os.path.abspath('unittests/test_cases/data_test.csv'), 
                      sep_concept='->', csv_sep=';')
In [7]:
# explore the data 
data
Out[7]:
OrderedDict([('Expert0',
                 -vh  -h  -m  -l  -vl  na  +vl  +l  +m  +h  +vh From  To
              0    1   0   0   0    0   0    0   0   0   0    0   C1  C2
              1    0   0   0   0    0   0    0   0   0   1    0   C2  C1
              2    0   0   0   0    0   0    0   0   0   1    0   C3  C1
              3    0   0   0   0    0   0    1   0   0   0    0   C3  C4),
             ('Expert1',
                 -vh  -h  -m  -l  -vl  na  +vl  +l  +m  +h  +vh From  To
              0    1   0   0   0    0   0    0   0   0   0    0   C1  C2
              1    0   0   0   0    0   0    0   0   0   0    1   C2  C1
              2    0   0   0   0    0   0    0   0   1   0    0   C3  C1
              3    0   0   0   0    0   0    0   1   0   0    0   C3  C4),
             ('Expert2',
                 -vh  -h  -m  -l  -vl  na  +vl  +l  +m  +h  +vh From  To
              0    0   1   0   0    0   0    0   0   0   0    0   C1  C2
              1    0   0   0   0    0   0    0   0   0   1    0   C2  C1
              2    0   0   0   0    0   0    0   0   1   0    0   C3  C1
              3    0   0   0   0    0   0    1   0   0   0    0   C3  C4),
             ('Expert3',
                 -vh  -h  -m  -l  -vl  na  +vl  +l  +m  +h  +vh From  To
              0    0   1   0   0    0   0    0   0   0   0    0   C1  C2
              1    0   0   0   0    0   0    0   0   1   0    0   C2  C1
              2    0   0   0   0    0   0    0   0   1   0    0   C3  C1
              3    0   0   0   0    0   0    1   0   0   0    0   C3  C4),
             ('Expert4',
                 -vh  -h  -m  -l  -vl  na  +vl  +l  +m  +h  +vh From  To  no causality
              0    0   1   0   0    0   0    0   0   0   0    0   C1  C2           0.0
              1    0   0   0   0    0   0    0   0   1   0    0   C2  C1           0.0
              2    0   0   0   0    0   0    0   0   1   0    0   C3  C1           0.0
              3    0   0   0   0    0   0    0   0   0   0    0   C3  C4           1.0),
             ('Expert5',
                 -vh  -h  -m  -l  -vl  na  +vl  +l  +m  +h  +vh From  To  no causality
              0    0   0   1   0    0   0    0   0   0   0    0   C1  C2           0.0
              1    0   0   0   0    0   0    0   0   1   0    0   C2  C1           0.0
              2    0   0   0   0    0   0    0   0   0   0    0   C3  C1           1.0
              3    0   0   0   0    0   0    0   0   0   0    0   C3  C4           1.0)])
In [9]:
# build an fcm using weights
# discover different implication methods, 
# Created weight matrix can be visualized  by printing the variable below


weight_matrix = fcm.build(data=data, implication_method='Larsen')