summaryrefslogtreecommitdiff
path: root/fuzzylite/src/activation/Lowest.cpp
blob: 52e7e85cbf3042668695ee85a72a10b1480c6f0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
 fuzzylite (R), a fuzzy logic control library in C++.
 Copyright (C) 2010-2017 FuzzyLite Limited. All rights reserved.
 Author: Juan Rada-Vilela, Ph.D. <jcrada@fuzzylite.com>

 This file is part of fuzzylite.

 fuzzylite is free software: you can redistribute it and/or modify it under
 the terms of the FuzzyLite License included with the software.

 You should have received a copy of the FuzzyLite License along with
 fuzzylite. If not, see <http://www.fuzzylite.com/license/>.

 fuzzylite is a registered trademark of FuzzyLite Limited.
 */

#include "fl/activation/Lowest.h"

#include "fl/rule/RuleBlock.h"
#include "fl/rule/Rule.h"
#include "fl/Operation.h"

#include <queue>

namespace fl {

    Lowest::Lowest(int numberOfRules) : Activation(), _numberOfRules(numberOfRules) { }

    Lowest::~Lowest() { }

    std::string Lowest::className() const {
        return "Lowest";
    }

    std::string Lowest::parameters() const {
        return Op::str(getNumberOfRules());
    }

    void Lowest::configure(const std::string& parameters) {
        setNumberOfRules((int) Op::toScalar(parameters));
    }

    int Lowest::getNumberOfRules() const {
        return this->_numberOfRules;
    }

    void Lowest::setNumberOfRules(int activatedRules) {
        this->_numberOfRules = activatedRules;
    }

    Complexity Lowest::complexity(const RuleBlock* ruleBlock) const {
        //Cost of priority_queue:
        //http://stackoverflow.com/questions/2974470/efficiency-of-the-stl-priority-queue
        Complexity result;

        const TNorm* conjunction = ruleBlock->getConjunction();
        const SNorm* disjunction = ruleBlock->getDisjunction();
        const TNorm* implication = ruleBlock->getImplication();

        Complexity meanFiring;
        for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
            const Rule* rule = ruleBlock->getRule(i);
            result.comparison(2);
            result += rule->complexityOfActivation(conjunction, disjunction);
            meanFiring += rule->complexityOfFiring(implication);
        }
        meanFiring.divide(scalar(ruleBlock->numberOfRules()));

        //Complexity of push is O(log n)
        result += Complexity().function(1).multiply(ruleBlock->numberOfRules()
                * std::log(scalar(ruleBlock->numberOfRules())));

        result += Complexity().comparison(2).arithmetic(1).multiply(getNumberOfRules());
        result += meanFiring.multiply(getNumberOfRules());
        //Complexity of pop is 2 * O(log n)
        result += Complexity().function(1).multiply(getNumberOfRules() *
                2 * std::log(scalar(ruleBlock->numberOfRules())));
        return result;
    }

    struct Ascending {

        bool operator()(const Rule* a, const Rule* b) {
            return a->getActivationDegree() > b->getActivationDegree();
        }
    };

    void Lowest::activate(RuleBlock* ruleBlock) {
        FL_DBG("Activation: " << className() << " " << parameters());
        const TNorm* conjunction = ruleBlock->getConjunction();
        const SNorm* disjunction = ruleBlock->getDisjunction();
        const TNorm* implication = ruleBlock->getImplication();

        std::priority_queue<Rule*, std::vector<Rule*>, Ascending> rulesToActivate;

        for (std::size_t i = 0; i < ruleBlock->numberOfRules(); ++i) {
            Rule* rule = ruleBlock->getRule(i);
            rule->deactivate();
            if (rule->isLoaded()) {
                scalar activationDegree = rule->activateWith(conjunction, disjunction);
                if (Op::isGt(activationDegree, 0.0))
                    rulesToActivate.push(rule);
            }
        }

        int activated = 0;
        while (rulesToActivate.size() > 0 and activated++ < _numberOfRules) {
            Rule* rule = rulesToActivate.top();
            rule->trigger(implication);
            rulesToActivate.pop();
        }
    }

    Lowest* Lowest::clone() const {
        return new Lowest(*this);
    }

    Activation* Lowest::constructor() {
        return new Lowest;
    }

}