# Time_series_fuzzy

Last updated: May 3rd, 2021
In [ ]:
!pip install networks
!pip install scikit-fuzzy
!pip install more-itertools

In [ ]:
# import packages
import networkx as nx
import skfuzzy as fuzz
import numpy as np

from itertools import combinations
from numpy import array
from matplotlib import pyplot
from math import log2
from skfuzzy import control as ctrl

In [ ]:
def visibility_graph(series):

g = nx.Graph()

# convert list of magnitudes into list of tuples that hold the index
tseries = []
n = 0
for magnitude in series:
tseries.append( (n, magnitude ) )
n += 1

# contiguous time points always have visibility
for n in range(0,len(tseries)-1):
(ta, ya) = tseries[n]
(tb, yb) = tseries[n+1]

for a,b in combinations(tseries, 2):
# two points, maybe connect
(ta, ya) = a
(tb, yb) = b

connect = True

# let's see all other points in the series
for tc, yc in tseries:
# other points, not a or b
if ta < tc < tb and tc != ta and tc != tb:
# does c obstruct?
if yc >= yb + (ya - yb) * ( (tb - tc) / (tb - ta) ):
connect = False

if connect and tb-ta > 1:

nx.write_pajek(g, "graph.net")

In [ ]:
def link_pred():

# import generated network

# build similarity rank
sim = nx.simrank_similarity(G)
lol = [[sim[u][v] for v in sorted(sim[u])] for u in sorted(sim)]
sim_array = array(lol)

return sim_array, G

In [ ]:
def init_pred(sim_array):

# get point with the highest similarity
l = list(sim_array[:-1,-1])
sim_pos = len(l) - l[::-1].index(max(l)) - 1

# do initial forecast
dx = len(series) - sim_pos - 1
dy = series[-1] - series[sim_pos]
pred_init = dy/dx + series[-1]

return pred_init, sim_pos, dx

In [ ]:
def plot_init_forecast(series, pred_init, sim_pos):

pyplot.plot(series, color='red')
pyplot.scatter(len(series), pred_init, color='blue')
pyplot.scatter(sim_pos, series[sim_pos], color='blue')
pyplot.plot([sim_pos, len(series)], [series[sim_pos], pred_init], 'g--')

In [ ]:
def plot_forecast(series, pred_init):

pyplot.plot(series, color='red')
pyplot.scatter(len(series), pred_init, color='blue')
pyplot.plot([len(series)-1, len(series)], [series[-1], pred_init], 'r--')

In [ ]:
def fuzzy_pred(dx):

# calculate fuzzy variable r
r = log2(abs(dx))

# create fuzzy sets p and q
p = ctrl.Antecedent(np.arange(0, 5, 1), 'p')
q = ctrl.Antecedent(np.linspace(0, 1, 10000), 'q')

# Pythonic API
P1 = fuzz.trimf(p.universe, [0, 0, 1])
P2 = fuzz.trimf(p.universe, [0, 1, 2])
P3 = fuzz.trimf(p.universe, [1, 2, 3])
P4 = fuzz.trimf(p.universe, [2, 3, 4])
P5 = fuzz.trimf(p.universe, [3, 4, 4])

Q1 = fuzz.trapmf(q.universe, [0, 0, .1, .2])
Q2 = fuzz.trimf(q.universe, [.1, .2, .3])
Q3 = fuzz.trimf(q.universe, [.2, .4, .6])
Q4 = fuzz.trimf(q.universe, [.3, .6, .9])
Q5 = fuzz.trimf(q.universe, [.7, .8, .9])
Q6 = fuzz.trapmf(q.universe, [.8, .9, 1, 1])

# create fuzzy rules
Q1_fac = round(fuzz.defuzz(q.universe, Q1, 'lom'), 3)
Q2_fac = round(fuzz.defuzz(q.universe, Q2, 'centroid'), 3)
Q3_fac = round(fuzz.defuzz(q.universe, Q3, 'centroid'), 3)
Q4_fac = round(fuzz.defuzz(q.universe, Q4, 'centroid'), 3)
Q5_fac = round(fuzz.defuzz(q.universe, Q5, 'centroid'), 3)
Q6_fac = round(fuzz.defuzz(q.universe, Q6, 'som'), 3)

mu_p1 = fuzz.interp_membership(p.universe, P1, r)
mu_p2 = fuzz.interp_membership(p.universe, P2, r)
mu_p3 = fuzz.interp_membership(p.universe, P3, r)
mu_p4 = fuzz.interp_membership(p.universe, P4, r)
mu_p5 = fuzz.interp_membership(p.universe, P5, r)

# calculate real number of f and g
f = (Q1_fac*mu_p1 + Q2_fac*mu_p2 + Q3_fac*mu_p3 + Q5_fac*mu_p4 + Q6_fac*mu_p5) / (mu_p1 + mu_p2 + mu_p3 + mu_p4 + mu_p5)
g = (Q6_fac*mu_p1 + Q5_fac*mu_p2 + Q4_fac*mu_p3 + Q2_fac*mu_p4 + Q1_fac*mu_p5) / (mu_p1 + mu_p2 + mu_p3 + mu_p4 + mu_p5)

return f, g

In [ ]:
def forecast(f, g, pred_init, series):

return f*pred_init + g*series[-1]

In [ ]:
# INPUT time series
series = [20, 40, 48, 70, 40, 60, 40, 100, 40, 80]
# series = [10, 20, 30, 20, 10, 20, 30, 20, 10, 20]
# series = [20, 40, 30, 50, 60, 40, 50, 55]

# create visibililty graph
visibility_graph(series)

# get link prediction with highest similarity

# calculate initial forecast
pred_init, sim_pos, dx = init_pred(sim_array)

# get f and g
f, g = fuzzy_pred(dx)

# do the forecasting
y_pred = forecast(f, g, pred_init, series)

In [ ]:
# plot initial prediction
plot_init_forecast(series, pred_init, sim_pos)

In [ ]:
# plot forecast
plot_forecast(series, pred_init)

In [ ]:
# nx.draw(G, with_labels=True, font_weight='bold')
nx.draw_networkx(G)