pyFTS/pyFTS/models/hofts.py
2018-02-27 18:30:20 -03:00

169 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Simple High Order extension of Conventional FTS by Chen (1996)
[1] S.-M. Chen, “Forecasting enrollments based on fuzzy time series,”
Fuzzy Sets Syst., vol. 81, no. 3, pp. 311319, 1996.
"""
import numpy as np
from pyFTS.common import FuzzySet, FLR, fts, flrg, tree
class HighOrderFLRG(flrg.FLRG):
"""Conventional High Order Fuzzy Logical Relationship Group"""
def __init__(self, order, **kwargs):
super(HighOrderFLRG, self).__init__(order, **kwargs)
self.LHS = []
self.RHS = {}
self.strlhs = ""
def append_rhs(self, c):
if c.name not in self.RHS:
self.RHS[c.name] = c
def str_lhs(self):
if len(self.strlhs) == 0:
for c in self.LHS:
if len(self.strlhs) > 0:
self.strlhs += ", "
self.strlhs = self.strlhs + str(c.name)
return self.strlhs
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.str_lhs() + " -> " + tmp
def __len__(self):
return len(self.RHS)
class HighOrderFTS(fts.FTS):
"""Conventional High Order Fuzzy Time Series"""
def __init__(self, name, **kwargs):
super(HighOrderFTS, self).__init__(1, name="HOFTS" + name, **kwargs)
self.name = "High Order FTS"
self.shortname = "HOFTS" + name
self.detail = "Chen"
self.order = kwargs.get('order',1)
self.setsDict = {}
self.is_high_order = True
def build_tree(self, node, lags, level):
if level >= self.order:
return
for s in lags[level]:
node.appendChild(tree.FLRGTreeNode(s))
for child in node.getChildren():
self.build_tree(child, lags, level + 1)
def build_tree_without_order(self, node, lags, level):
if level not in lags:
return
for s in lags[level]:
node.appendChild(tree.FLRGTreeNode(s))
for child in node.getChildren():
self.build_tree_without_order(child, lags, level + 1)
def generateFLRG(self, flrs):
flrgs = {}
l = len(flrs)
for k in np.arange(self.order + 1, l):
flrg = HighOrderFLRG(self.order)
for kk in np.arange(k - self.order, k):
flrg.append_lhs(flrs[kk].LHS)
if flrg.str_lhs() in flrgs:
flrgs[flrg.str_lhs()].append_rhs(flrs[k].RHS)
else:
flrgs[flrg.str_lhs()] = flrg;
flrgs[flrg.str_lhs()].append_rhs(flrs[k].RHS)
return (flrgs)
def generate_flrg(self, data):
flrgs = {}
l = len(data)
for k in np.arange(self.order, l):
if self.dump: print("FLR: " + str(k))
sample = data[k - self.order: k]
rhs = [set for set in self.sets if set.membership(data[k]) > 0.0]
lags = {}
for o in np.arange(0, self.order):
lhs = [set for set in self.sets if set.membership(sample[o]) > 0.0]
lags[o] = lhs
root = tree.FLRGTreeNode(None)
self.build_tree_without_order(root, lags, 0)
# Trace the possible paths
for p in root.paths():
flrg = HighOrderFLRG(self.order)
path = list(reversed(list(filter(None.__ne__, p))))
for lhs in path:
flrg.append_lhs(lhs)
if flrg.str_lhs() not in flrgs:
flrgs[flrg.str_lhs()] = flrg;
for st in rhs:
flrgs[flrg.str_lhs()].append_rhs(st)
return flrgs
def train(self, data, **kwargs):
data = self.apply_transformations(data, updateUoD=True)
self.order = kwargs.get('order',2)
if kwargs.get('sets', None) is not None:
self.sets = kwargs.get('sets', None)
for s in self.sets: self.setsDict[s.name] = s
self.flrgs = self.generate_flrg(data)
def forecast(self, data, **kwargs):
ret = []
l = len(data)
if l <= self.order:
return data
ndata = self.apply_transformations(data)
for k in np.arange(self.order, l+1):
tmpdata = FuzzySet.fuzzyfy_series_old(ndata[k - self.order: k], self.sets)
tmpflrg = HighOrderFLRG(self.order)
for s in tmpdata: tmpflrg.append_lhs(s)
if tmpflrg.str_lhs() not in self.flrgs:
ret.append(tmpdata[-1].centroid)
else:
flrg = self.flrgs[tmpflrg.str_lhs()]
ret.append(flrg.get_midpoint())
ret = self.apply_inverse_transformations(ret, params=[data[self.order - 1:]])
return ret