CompareEngine.cpp 8.5 KB
Newer Older
Elouan Wauquier's avatar
Elouan Wauquier committed
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include "CompareEngine.hpp"

CompareEngine::CompareEngine() : fl::Engine() {
    setName("Comparator");

    const int ringCount = STEP_PER_RIDGE * RIDGE_COUNT / 2;
    const int maxSectionCount = qCeil(2 * M_PI * (ringCount + CENTER_RADIUS_IGNORE * STEP_PER_RIDGE));

    // Variables des `COMPARE_COUNT` minuties
    for (int i(0); i < COMPARE_COUNT; ++i) {
        fl::InputVariable *membership = new fl::InputVariable;
        membership->setName("<membership_" + QString::number(i).toStdString() + ">");
        membership->setEnabled(true);
        membership->setRange(0, 1);
        membership->setLockValueInRange(true);
        membership->addTerm(new fl::Trapezoid("'uncertain'", 0, 0.05, 0.1, 0.2));
        membership->addTerm(new fl::Ramp("'certain'", 0.1, 0.2));
        addInputVariable(membership);

        fl::InputVariable *ringDiff = new fl::InputVariable;
        ringDiff->setName("<ringDiff_" + QString::number(i).toStdString() + ">");
        ringDiff->setEnabled(true);
        ringDiff->addTerm(new fl::Triangle("'same'", - COMPARE_RADIUS * STEP_PER_RIDGE, 0, COMPARE_RADIUS * STEP_PER_RIDGE));
        addInputVariable(ringDiff);

        fl::InputVariable *sectionDiff = new fl::InputVariable;
        sectionDiff->setName("<sectionDiff_" + QString::number(i).toStdString() + ">");
        sectionDiff->setEnabled(true);
        sectionDiff->addTerm(new fl::Triangle("'same'", - COMPARE_RADIUS * STEP_PER_RIDGE, 0, COMPARE_RADIUS * STEP_PER_RIDGE));
        addInputVariable(sectionDiff);

        fl::InputVariable *type = new fl::InputVariable;
        type->setName("<type_" + QString::number(i).toStdString() + ">");
        type->setEnabled(true);
        for (int j(0); j < static_cast<int>(MinutiaEngine::Engine::NUMBER_OF_ENGINE); ++j) {
            std::vector<fl::Discrete::Pair> partition;
            for (int k(0); k < static_cast<int>(MinutiaEngine::Engine::NUMBER_OF_ENGINE); ++k) {
                if (k == j) {
                    partition.push_back(fl::Discrete::Pair(k, 1));
                } else {
                    partition.push_back(fl::Discrete::Pair(k, 0));
                }
            }
            type->addTerm(new fl::Discrete("'" + QString::number(j).toStdString() + "'", partition));
        }
        addInputVariable(type);
    }

    // Variables de la minutie de comparaison
    fl::InputVariable *membership = new fl::InputVariable;
    membership->setName("<membership>");
    membership->setEnabled(true);
    membership->setRange(0, 1);
    membership->setLockValueInRange(true);
    membership->addTerm(new fl::Trapezoid("'uncertain'", 0, 0.05, 0.1, 0.2));
    membership->addTerm(new fl::Ramp("'certain'", 0.1, 0.2));
    addInputVariable(membership);

    fl::InputVariable *ring = new fl::InputVariable;
    ring->setName("<ring>");
    ring->setEnabled(true);
    for (int j(0); j < ringCount; ++j) {
        ring->addTerm(new fl::Discrete("'" + QString::number(j).toStdString() + "'"));
    }
    ring->setValue(0);
    addInputVariable(ring);

    fl::InputVariable *section = new fl::InputVariable;
    section->setName("<section>");
    section->setEnabled(true);
    for (int j(0); j < maxSectionCount; ++j) {
        section->addTerm(new fl::Discrete("'" + QString::number(j).toStdString() + "'"));
    }
    section->setValue(0);
    addInputVariable(section);

    fl::InputVariable *type = new fl::InputVariable;
    type->setName("<type>");
    type->setEnabled(true);
    for (int j(0); j < static_cast<int>(MinutiaEngine::Engine::NUMBER_OF_ENGINE); ++j) {
        std::vector<fl::Discrete::Pair> partition;
        for (int k(0); k < static_cast<int>(MinutiaEngine::Engine::NUMBER_OF_ENGINE); ++k) {
            if (k == j) {
                partition.push_back(fl::Discrete::Pair(k, 1));
            } else {
                partition.push_back(fl::Discrete::Pair(k, 0));
            }
        }
        type->addTerm(new fl::Discrete("'" + QString::number(j).toStdString() + "'", partition));
    }
    addInputVariable(type);


    // Variable de sortie
    fl::OutputVariable *output = new fl::OutputVariable;
    output->setName("<proximity>");
    output->setEnabled(true);
    output->setAggregation(new fl::Maximum);
    std::vector<fl::Discrete::Pair> partition;
    partition.push_back(fl::Discrete::Pair(0, 1));
    output->addTerm(new fl::Discrete("'close'", partition));
    output->setDefuzzifier(new fl::WeightedAverage); // Non utilisé
    addOutputVariable(output);


    // Règles
    fl::RuleBlock *ruleBlock = new fl::RuleBlock;
    ruleBlock->setName("CompareRules");
    ruleBlock->setEnabled(true);
    ruleBlock->setConjunction(new fl::CircularProduct);
    ruleBlock->setImplication(new fl::Minimum);
    for (int i(0); i < COMPARE_COUNT; ++i) {
        for (int type(0); type < static_cast<int>(MinutiaEngine::Engine::NUMBER_OF_ENGINE); ++type) {
            std::string antecedent1 = "if <membership> is 'certain' "
                                      "and <type> is '" + QString::number(type).toStdString() + "' "
                                      "and <membership_" + QString::number(i).toStdString() + "> is 'certain' "
                                      "and <type_" + QString::number(i).toStdString() + "> is '" + QString::number(type).toStdString() + "' "
                                      "and <ringDiff_" + QString::number(i).toStdString() + "> is 'same' "
                                      "and <sectionDiff_" + QString::number(i).toStdString() + "> is 'same' ";
            std::string antecedent2 = "if <membership> is 'certain' "
                                      "and <type> is '" + QString::number(type).toStdString() + "' "
                                      "and <membership_" + QString::number(i).toStdString() + "> is 'uncertain' "
                                      "and <type_" + QString::number(i).toStdString() + "> is '" + QString::number(type).toStdString() + "' "
                                      "and <ringDiff_" + QString::number(i).toStdString() + "> is 'same' "
                                      "and <sectionDiff_" + QString::number(i).toStdString() + "> is 'same' ";
            std::string antecedent3 = "if <membership> is 'uncertain' "
                                      "and <type> is '" + QString::number(type).toStdString() + "' "
                                      "and <membership_" + QString::number(i).toStdString() + "> is 'uncertain' "
                                      "and <type_" + QString::number(i).toStdString() + "> is '" + QString::number(type).toStdString() + "' "
                                      "and <ringDiff_" + QString::number(i).toStdString() + "> is 'same' "
                                      "and <sectionDiff_" + QString::number(i).toStdString() + "> is 'same' ";
            ruleBlock->addRule(fl::Rule::parse(antecedent1 + "then <proximity> is 'close'", this));
            ruleBlock->addRule(fl::Rule::parse(antecedent2 + "then <proximity> is 'close' with 0.5", this));
            ruleBlock->addRule(fl::Rule::parse(antecedent3 + "then <proximity> is 'close' with 0.25", this));
        }
    }
    addRuleBlock(ruleBlock);
}

void CompareEngine::setMinutia(int index, const MinutiaEngine::Minutia& minutia) {
    std::string indexStr(QString::number(index).toStdString());
    getInputVariable("<membership_" + indexStr + ">")->setValue(minutia.membership);
    getInputVariable("<ringDiff_" + indexStr + ">")->setValue(minutia.ring);
    getInputVariable("<sectionDiff_" + indexStr + ">")->setValue(minutia.section);
    getInputVariable("<type_" + indexStr + ">")->setValue(static_cast<int>(minutia.type));
}

void CompareEngine::setDBMinutia(const MinutiaEngine::Minutia& minutia) {
    for (int i(0); i < COMPARE_COUNT; ++i) {
        std::string index(QString::number(i).toStdString());
        int ringSrc, sectionSrc, ring, section;
        ringSrc = static_cast<int>(getInputVariable("<ringDiff_" + index + ">")->getValue());
        sectionSrc = static_cast<int>(getInputVariable("<sectionDiff_" + index + ">")->getValue());
        ring = static_cast<int>(getInputVariable("<ring>")->getValue());
        section = static_cast<int>(getInputVariable("<section>")->getValue());

        getInputVariable("<ringDiff_" + index + ">")->setValue(ringSrc + ring - minutia.ring);
        getInputVariable("<sectionDiff_" + index + ">")->setValue(sectionSrc + section - minutia.section);
    }
    getInputVariable("<membership>")->setValue(minutia.membership);
    getInputVariable("<ring>")->setValue(minutia.ring);
    getInputVariable("<section>")->setValue(minutia.section);
    getInputVariable("<type>")->setValue(static_cast<int>(minutia.type));
}