import numpy as np
from pyFTS.common import FuzzySet, FLR, fts, tree
from pyFTS.models import hofts
from pyFTS.models.nonstationary import common, flrg
[docs]class HighOrderNonStationaryFLRG(flrg.NonStationaryFLRG):
"""First Order NonStationary Fuzzy Logical Relationship Group"""
def __init__(self, order, **kwargs):
super(HighOrderNonStationaryFLRG, self).__init__(order, **kwargs)
self.LHS = []
self.RHS = {}
[docs] def append_rhs(self, c, **kwargs):
if c.name not in self.RHS:
self.RHS[c.name] = c
[docs] def append_lhs(self, c):
self.LHS.append(c)
def __str__(self):
tmp = ""
for c in sorted(self.RHS):
if len(tmp) > 0:
tmp = tmp + ","
tmp = tmp + c
return self.get_key() + " -> " + tmp
[docs]class HighOrderNonStationaryFTS(hofts.HighOrderFTS):
"""NonStationaryFTS Fuzzy Time Series"""
def __init__(self, name, **kwargs):
super(HighOrderNonStationaryFTS, self).__init__("HONSFTS " + name, **kwargs)
self.name = "High Order Non Stationary FTS"
self.detail = ""
self.flrgs = {}
[docs] def generate_flrg(self, data, **kwargs):
l = len(data)
window_size = kwargs.get("window_size", 1)
for k in np.arange(self.order, l):
if self.dump: print("FLR: " + str(k))
sample = data[k - self.order: k]
disp = common.window_index(k, window_size)
rhs = [self.sets[key] for key in self.partitioner.ordered_sets
if self.sets[key].membership(data[k], disp) > 0.0]
if len(rhs) == 0:
rhs = [common.check_bounds(data[k], self.partitioner, disp)]
lags = {}
for o in np.arange(0, self.order):
tdisp = common.window_index(k - (self.order - o), window_size)
lhs = [self.sets[key] for key in self.partitioner.ordered_sets
if self.sets[key].membership(sample[o], tdisp) > 0.0]
if len(lhs) == 0:
lhs = [common.check_bounds(sample[o], self.partitioner, tdisp)]
lags[o] = lhs
root = tree.FLRGTreeNode(None)
tree.build_tree_without_order(root, lags, 0)
# Trace the possible paths
for p in root.paths():
flrg = HighOrderNonStationaryFLRG(self.order)
path = list(reversed(list(filter(None.__ne__, p))))
for c, e in enumerate(path, start=0):
flrg.append_lhs(e)
if flrg.get_key() not in self.flrgs:
self.flrgs[flrg.get_key()] = flrg;
for st in rhs:
self.flrgs[flrg.get_key()].append_rhs(st)
# flrgs = sorted(flrgs, key=lambda flrg: flrg.get_midpoint(0, window_size=1))
[docs] def train(self, data, **kwargs):
if kwargs.get('order', None) is not None:
self.order = kwargs.get('order', 1)
if kwargs.get('sets', None) is not None:
self.sets = kwargs.get('sets', None)
window_size = kwargs.get('parameters', 1)
self.generate_flrg(data, window_size=window_size)
def _affected_flrgs(self, sample, k, time_displacement, window_size):
# print("input: " + str(ndata[k]))
affected_flrgs = []
affected_flrgs_memberships = []
lags = {}
for ct, dat in enumerate(sample):
tdisp = common.window_index((k + time_displacement) - (self.order - ct), window_size)
sel = [ct for ct, key in enumerate(self.partitioner.ordered_sets)
if self.sets[key].membership(dat, tdisp) > 0.0]
if len(sel) == 0:
sel.append(common.check_bounds_index(dat, self.partitioner, tdisp))
lags[ct] = sel
# Build the tree with all possible paths
root = tree.FLRGTreeNode(None)
tree.build_tree_without_order(root, lags, 0)
# Trace the possible paths and build the PFLRG's
for p in root.paths():
path = list(reversed(list(filter(None.__ne__, p))))
flrg = HighOrderNonStationaryFLRG(self.order)
for kk in path:
flrg.append_lhs(self.sets[self.partitioner.ordered_sets[kk]])
affected_flrgs.append(flrg)
# affected_flrgs_memberships.append_rhs(flrg.get_membership(sample, disp))
# print(flrg.get_key())
# the FLRG is here because of the bounds verification
mv = []
for ct, dat in enumerate(sample):
td = common.window_index((k + time_displacement) - (self.order - ct), window_size)
tmp = flrg.LHS[ct].membership(dat, td)
mv.append(tmp)
# print(mv)
affected_flrgs_memberships.append(np.prod(mv))
return [affected_flrgs, affected_flrgs_memberships]
[docs] def forecast(self, ndata, **kwargs):
time_displacement = kwargs.get("time_displacement",0)
window_size = kwargs.get("window_size", 1)
l = len(ndata)
ret = []
for k in np.arange(self.order, l+1):
sample = ndata[k - self.order: k]
affected_flrgs, affected_flrgs_memberships = self._affected_flrgs(sample, k,
time_displacement, window_size)
#print([str(k) for k in affected_flrgs])
#print(affected_flrgs_memberships)
tmp = []
tdisp = common.window_index(k + time_displacement, window_size)
if len(affected_flrgs) == 0:
tmp.append(common.check_bounds(sample[-1], self.sets, tdisp))
elif len(affected_flrgs) == 1:
flrg = affected_flrgs[0]
if flrg.get_key() in self.flrgs:
tmp.append(self.flrgs[flrg.get_key()].get_midpoint(tdisp))
else:
tmp.append(flrg.LHS[-1].get_midpoint(tdisp))
else:
for ct, aset in enumerate(affected_flrgs):
if aset.get_key() in self.flrgs:
tmp.append(self.flrgs[aset.get_key()].get_midpoint(tdisp) *
affected_flrgs_memberships[ct])
else:
tmp.append(aset.LHS[-1].get_midpoint(tdisp)*
affected_flrgs_memberships[ct])
pto = sum(tmp)
#print(pto)
ret.append(pto)
return ret
[docs] def forecast_interval(self, ndata, **kwargs):
time_displacement = kwargs.get("time_displacement", 0)
window_size = kwargs.get("window_size", 1)
l = len(ndata)
ret = []
for k in np.arange(self.order, l + 1):
sample = ndata[k - self.order: k]
affected_flrgs, affected_flrgs_memberships = self._affected_flrgs(sample, k,
time_displacement, window_size)
# print([str(k) for k in affected_flrgs])
# print(affected_flrgs_memberships)
upper = []
lower = []
tdisp = common.window_index(k + time_displacement, window_size)
if len(affected_flrgs) == 0:
aset = common.check_bounds(sample[-1], self.sets, tdisp)
lower.append(aset.get_lower(tdisp))
upper.append(aset.get_upper(tdisp))
elif len(affected_flrgs) == 1:
_flrg = affected_flrgs[0]
if _flrg.get_key() in self.flrgs:
lower.append(self.flrgs[_flrg.get_key()].get_lower(tdisp))
upper.append(self.flrgs[_flrg.get_key()].get_upper(tdisp))
else:
lower.append(_flrg.LHS[-1].get_lower(tdisp))
upper.append(_flrg.LHS[-1].get_upper(tdisp))
else:
for ct, aset in enumerate(affected_flrgs):
if aset.get_key() in self.flrgs:
lower.append(self.flrgs[aset.get_key()].get_lower(tdisp) *
affected_flrgs_memberships[ct])
upper.append(self.flrgs[aset.get_key()].get_upper(tdisp) *
affected_flrgs_memberships[ct])
else:
lower.append(aset.LHS[-1].get_lower(tdisp) *
affected_flrgs_memberships[ct])
upper.append(aset.LHS[-1].get_upper(tdisp) *
affected_flrgs_memberships[ct])
ret.append([sum(lower), sum(upper)])
return ret