From a89ec9dd46b0be482c7332bc914cc8fb2c99fd1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=C3=B4nio=20C=C3=A2ndido?= Date: Fri, 6 Oct 2017 14:08:46 -0300 Subject: [PATCH] - Introducing new superclass FLRG and general refactoring --- pyFTS/chen.py | 13 ++-- pyFTS/cheng.py | 2 +- pyFTS/flrg.py | 17 ++++ pyFTS/hofts.py | 8 +- pyFTS/ismailefendi.py | 7 +- pyFTS/nonstationary/flrg.py | 34 ++++++++ pyFTS/nonstationary/honsfts.py | 138 +++++++++++++++++++++++++++++++++ pyFTS/nonstationary/nsfts.py | 43 ++++------ pyFTS/sadaei.py | 9 ++- pyFTS/yu.py | 5 +- 10 files changed, 228 insertions(+), 48 deletions(-) create mode 100644 pyFTS/flrg.py create mode 100644 pyFTS/nonstationary/flrg.py create mode 100644 pyFTS/nonstationary/honsfts.py diff --git a/pyFTS/chen.py b/pyFTS/chen.py index ce0ad0c..385e143 100644 --- a/pyFTS/chen.py +++ b/pyFTS/chen.py @@ -6,17 +6,15 @@ S.-M. Chen, “Forecasting enrollments based on fuzzy time series,” Fuzzy Sets import numpy as np from pyFTS.common import FuzzySet, FLR -from pyFTS import fts +from pyFTS import fts,flrg -class ConventionalFLRG(object): +class ConventionalFLRG(flrg.FLRG): """First Order Conventional Fuzzy Logical Relationship Group""" - def __init__(self, LHS): + def __init__(self, LHS, **kwargs): + super(ConventionalFLRG, self).__init__(1, **kwargs) self.LHS = LHS self.RHS = set() - self.midpoint = None - self.lower = None - self.upper = None def append(self, c): self.RHS.add(c) @@ -30,8 +28,7 @@ class ConventionalFLRG(object): tmp2 = tmp2 + c.name return tmp + tmp2 - def __len__(self): - return len(self.RHS) + class ConventionalFTS(fts.FTS): diff --git a/pyFTS/cheng.py b/pyFTS/cheng.py index 3efa5a2..4a6f7f5 100644 --- a/pyFTS/cheng.py +++ b/pyFTS/cheng.py @@ -15,7 +15,7 @@ class TrendWeightedFLRG(yu.WeightedFLRG): First Order Trend Weighted Fuzzy Logical Relationship Group """ def __init__(self, LHS, **kwargs): - super(TrendWeightedFLRG, self).__init__(LHS) + super(TrendWeightedFLRG, self).__init__(LHS, **kwargs) def weights(self): count_nochange = 0.0 diff --git a/pyFTS/flrg.py b/pyFTS/flrg.py new file mode 100644 index 0000000..10bcaf8 --- /dev/null +++ b/pyFTS/flrg.py @@ -0,0 +1,17 @@ + + +class FLRG(object): + + def __init__(self, order, **kwargs): + self.LHS = None + self.RHS = None + self.order = order + self.midpoint = None + self.lower = None + self.upper = None + + def __len__(self): + return len(self.RHS) + + + diff --git a/pyFTS/hofts.py b/pyFTS/hofts.py index 4aedc84..6f0f0d4 100644 --- a/pyFTS/hofts.py +++ b/pyFTS/hofts.py @@ -7,15 +7,15 @@ Fuzzy Sets Syst., vol. 81, no. 3, pp. 311–319, 1996. import numpy as np from pyFTS.common import FuzzySet,FLR -from pyFTS import fts +from pyFTS import fts, flrg -class HighOrderFLRG(object): +class HighOrderFLRG(flrg.FLRG): """Conventional High Order Fuzzy Logical Relationship Group""" - def __init__(self, order): + def __init__(self, order, **kwargs): + super(HighOrderFLRG, self).__init__(order, **kwargs) self.LHS = [] self.RHS = {} - self.order = order self.strlhs = "" def appendRHS(self, c): diff --git a/pyFTS/ismailefendi.py b/pyFTS/ismailefendi.py index d794d91..2031105 100644 --- a/pyFTS/ismailefendi.py +++ b/pyFTS/ismailefendi.py @@ -7,12 +7,13 @@ US Dollar to Ringgit Malaysia,” Int. J. Comput. Intell. Appl., vol. 12, no. 1, import numpy as np from pyFTS.common import FuzzySet,FLR -from pyFTS import fts +from pyFTS import fts, flrg -class ImprovedWeightedFLRG(object): +class ImprovedWeightedFLRG(flrg.FLRG): """First Order Improved Weighted Fuzzy Logical Relationship Group""" - def __init__(self, LHS): + def __init__(self, LHS, **kwargs): + super(ImprovedWeightedFLRG, self).__init__(1, **kwargs) self.LHS = LHS self.RHS = {} self.count = 0.0 diff --git a/pyFTS/nonstationary/flrg.py b/pyFTS/nonstationary/flrg.py new file mode 100644 index 0000000..c026871 --- /dev/null +++ b/pyFTS/nonstationary/flrg.py @@ -0,0 +1,34 @@ + +from pyFTS import flrg + + +class NonStationaryFLRG(flrg.FLRG): + + def __init__(self, LHS, **kwargs): + super(NonStationaryFLRG, self).__init__(1, **kwargs) + self.LHS = LHS + self.RHS = set() + + def get_midpoint(self, t): + if self.midpoint is None: + tmp = [] + for r in self.RHS: + tmp.append(r.get_midpoint(t)) + self.midpoint = sum(tmp) / len(tmp) + return self.midpoint + + def get_lower(self, t): + if self.lower is None: + tmp = [] + for r in self.RHS: + tmp.append(r.get_midpoint(t)) + self.lower = min(tmp) + return self.lower + + def get_upper(self, t): + if self.upper is None: + tmp = [] + for r in self.RHS: + tmp.append(r.get_midpoint(t)) + self.upper = max(tmp) + return self.upper \ No newline at end of file diff --git a/pyFTS/nonstationary/honsfts.py b/pyFTS/nonstationary/honsfts.py new file mode 100644 index 0000000..bec087c --- /dev/null +++ b/pyFTS/nonstationary/honsfts.py @@ -0,0 +1,138 @@ +import numpy as np +from pyFTS.common import FuzzySet, FLR +from pyFTS import fts, hofts +from pyFTS.nonstationary import common + + +class HighOrderNonStationaryFLRG(hofts.HighOrderFLRG): + """First Order NonStationary Fuzzy Logical Relationship Group""" + def __init__(self, order): + super(HighOrderNonStationaryFLRG, self).__init__(order) + + def get_midpoint(self, t): + if self.midpoint is None: + tmp = [] + for r in self.RHS: + tmp.append(r.get_midpoint(t)) + self.midpoint = sum(tmp)/len(tmp) + return self.midpoint + + def get_lower(self, t): + if self.lower is None: + tmp = [] + for r in self.RHS: + tmp.append(r.get_midpoint(t)) + self.lower = min(tmp) + return self.lower + + def get_upper(self, t): + if self.upper is None: + tmp = [] + for r in self.RHS: + tmp.append(r.get_midpoint(t)) + self.upper = max(tmp) + return self.upper + + +class NonStationaryFTS(fts.FTS): + """NonStationaryFTS Fuzzy Time Series""" + def __init__(self, name, **kwargs): + super(NonStationaryFTS, self).__init__(1, "NSFTS " + name, **kwargs) + self.name = "Non Stationary FTS" + self.detail = "" + self.flrgs = {} + + def generateFLRG(self, flrs): + flrgs = {} + for flr in flrs: + if flr.LHS.name in flrgs: + flrgs[flr.LHS.name].append(flr.RHS) + else: + flrgs[flr.LHS.name] = NonStationaryFLRG(flr.LHS) + flrgs[flr.LHS.name].append(flr.RHS) + return (flrgs) + + def train(self, data, sets=None,order=1,parameters=None): + + if sets is not None: + self.sets = sets + else: + self.sets = self.partitioner.sets + + ndata = self.doTransformations(data) + tmpdata = common.fuzzySeries(ndata, self.sets) + flrs = FLR.generateNonRecurrentFLRs(tmpdata) + self.flrgs = self.generateFLRG(flrs) + + def forecast(self, data, **kwargs): + + time_displacement = kwargs.get("time_displacement",0) + + ndata = np.array(self.doTransformations(data)) + + l = len(ndata) + + ret = [] + + for k in np.arange(0, l): + + #print("input: " + str(ndata[k])) + + tdisp = k + time_displacement + + affected_sets = [ [set, set.membership(ndata[k], tdisp)] + for set in self.sets if set.membership(ndata[k], tdisp) > 0.0] + + if len(affected_sets) == 0: + if self.sets[0].get_lower(tdisp) > ndata[k]: + affected_sets.append([self.sets[0], 1.0]) + elif self.sets[-1].get_upper(tdisp) < ndata[k]: + affected_sets.append([self.sets[-1], 1.0]) + + #print(affected_sets) + + tmp = [] + for aset in affected_sets: + if aset[0] in self.flrgs: + tmp.append(self.flrgs[aset[0].name].get_midpoint(tdisp) * aset[1]) + else: + tmp.append(aset[0].get_midpoint(tdisp) * aset[1]) + + pto = sum(tmp) + + #print(pto) + + ret.append(pto) + + ret = self.doInverseTransformations(ret, params=[data[self.order - 1:]]) + + return ret + + def forecastInterval(self, data, **kwargs): + + time_displacement = kwargs.get("time_displacement",0) + + ndata = np.array(self.doTransformations(data)) + + l = len(ndata) + + ret = [] + + for k in np.arange(0, l): + + tdisp = k + time_displacement + + affected_sets = [ [set.name, set.membership(ndata[k], tdisp)] + for set in self.sets if set.membership(ndata[k], tdisp) > 0.0] + + upper = [] + lower = [] + for aset in affected_sets: + lower.append(self.flrgs[aset[0]].get_lower(tdisp) * aset[1]) + upper.append(self.flrgs[aset[0]].get_upper(tdisp) * aset[1]) + + ret.append([sum(lower), sum(upper)]) + + ret = self.doInverseTransformations(ret, params=[data[self.order - 1:]]) + + return ret \ No newline at end of file diff --git a/pyFTS/nonstationary/nsfts.py b/pyFTS/nonstationary/nsfts.py index 65a0c42..616733f 100644 --- a/pyFTS/nonstationary/nsfts.py +++ b/pyFTS/nonstationary/nsfts.py @@ -1,37 +1,28 @@ import numpy as np from pyFTS.common import FuzzySet, FLR from pyFTS import fts, chen -from pyFTS.nonstationary import common +from pyFTS.nonstationary import common, flrg -class NonStationaryFLRG(chen.ConventionalFLRG): +class ConventionalNonStationaryFLRG(flrg.NonStationaryFLRG): """First Order NonStationary Fuzzy Logical Relationship Group""" - def __init__(self, LHS): - super(NonStationaryFLRG, self).__init__(LHS) - def get_midpoint(self, t): - if self.midpoint is None: - tmp = [] - for r in self.RHS: - tmp.append(r.get_midpoint(t)) - self.midpoint = sum(tmp)/len(tmp) - return self.midpoint + def __init__(self, LHS, **kwargs): + super(ConventionalNonStationaryFLRG, self).__init__(1, **kwargs) + self.LHS = LHS + self.RHS = set() - def get_lower(self, t): - if self.lower is None: - tmp = [] - for r in self.RHS: - tmp.append(r.get_midpoint(t)) - self.lower = min(tmp) - return self.lower + def append(self, c): + self.RHS.add(c) - def get_upper(self, t): - if self.upper is None: - tmp = [] - for r in self.RHS: - tmp.append(r.get_midpoint(t)) - self.upper = max(tmp) - return self.upper + def __str__(self): + tmp = self.LHS.name + " -> " + tmp2 = "" + for c in sorted(self.RHS, key=lambda s: s.name): + if len(tmp2) > 0: + tmp2 = tmp2 + "," + tmp2 = tmp2 + c.name + return tmp + tmp2 class NonStationaryFTS(fts.FTS): @@ -48,7 +39,7 @@ class NonStationaryFTS(fts.FTS): if flr.LHS.name in flrgs: flrgs[flr.LHS.name].append(flr.RHS) else: - flrgs[flr.LHS.name] = NonStationaryFLRG(flr.LHS) + flrgs[flr.LHS.name] = ConventionalNonStationaryFLRG(flr.LHS) flrgs[flr.LHS.name].append(flr.RHS) return (flrgs) diff --git a/pyFTS/sadaei.py b/pyFTS/sadaei.py index 7200c99..9162132 100644 --- a/pyFTS/sadaei.py +++ b/pyFTS/sadaei.py @@ -7,16 +7,17 @@ refined exponentially weighted fuzzy time series and an improved harmony search, import numpy as np from pyFTS.common import FuzzySet,FLR -from pyFTS import fts +from pyFTS import fts, flrg -class ExponentialyWeightedFLRG(object): +class ExponentialyWeightedFLRG(flrg.FLRG): """First Order Exponentialy Weighted Fuzzy Logical Relationship Group""" - def __init__(self, LHS, c): + def __init__(self, LHS, **kwargs): + super(ExponentialyWeightedFLRG, self).__init__(1, **kwargs) self.LHS = LHS self.RHS = [] self.count = 0.0 - self.c = c + self.c = kwargs.get("c",2.0) def append(self, c): self.RHS.append(c) diff --git a/pyFTS/yu.py b/pyFTS/yu.py index d7b1a47..2cba7bf 100644 --- a/pyFTS/yu.py +++ b/pyFTS/yu.py @@ -7,12 +7,13 @@ Phys. A Stat. Mech. its Appl., vol. 349, no. 3, pp. 609–624, 2005. import numpy as np from pyFTS.common import FuzzySet,FLR -from pyFTS import fts +from pyFTS import fts, flrg, chen -class WeightedFLRG(object): +class WeightedFLRG(flrg.FLRG): """First Order Weighted Fuzzy Logical Relationship Group""" def __init__(self, LHS, **kwargs): + super(WeightedFLRG, self).__init__(1, **kwargs) self.LHS = LHS self.RHS = [] self.count = 1.0