MMM全連結聚類演算法實現

青灰色的风發表於2024-05-25

使用時,僅需修改TODO下描述的欄位即可,其他無需改動。

#include <bits/stdc++.h>
// TODO: 根據需求分別修改任務數、每個模組內最大任務數、模組數、步進長度
#define TASK_NUM        (8)
#define MAX_TASK_NUM    (4)
#define MODULE_NUM      (2)
#define GRANULARITY     (0.5)

using namespace std;

void MMMSAA();
void MMMCAA();
void MMMAAA();
void MMMSAArepeat();
void MMMCAArepeat();
void MMMAAArepeat();
void MMMinit();
void printDE();
void getFinalCost();

struct DEitem
{
    double c;
    int k;
    vector<set<int>> Kc;
};

double g_costThres = 0.0;
double g_costThresDefault = 0.0;
int g_k = 0;
vector<set<int>> g_Kc;
vector<DEitem> DE;

// TODO: 根據需求修改通訊代價矩陣
double g_commMatrix[TASK_NUM][TASK_NUM] =
{
    {0, 0, 0.5, 0, 0.5, 0, 0, 0,},
    {0, 0, 0.5, 0.5, 0, 0, 0, 0,},
    {0.5, 0.5, 0, 0.5, 1, 0.5, 0, 0,},
    {0, 0.5, 0.5, 0, 0, 1, 0, 0,},
    {0.5, 0, 1, 0, 0, 0.5, 1, 0,},
    {0, 0, 0.5, 1, 0.5, 0, 0.5, 0.5,},
    {0, 0, 0, 0, 1, 0.5, 0, 0.5,},
    {0, 0, 0, 0, 0, 0.5, 0.5, 0,},
};

void MMMinit()
{
    double maxElement = -1;
    for (int i = 0; i < TASK_NUM; ++i)
    {
        for (int j = 0; j < TASK_NUM; ++j)
        {
            if (g_commMatrix[i][j] > maxElement)
            {
                maxElement = g_commMatrix[i][j];
            }
        }
    }
    g_costThres = maxElement + 1;
    g_costThresDefault = g_costThres;
    g_k = TASK_NUM;
    g_Kc.clear();
    g_Kc.resize(TASK_NUM);
    for (int i = 0; i < TASK_NUM; ++i)
    {
        g_Kc[i].insert(i);
    }
}

void getFinalCost()
{
    vector<set<int>> K1 = DE[DE.size() - 1].Kc;
    double finalCost = 0;
    for (int i = 0; i < K1.size(); i++) // ki
    {
        for (int j = i + 1; j < K1.size(); j++) // kj
        {
            for (int ti : g_Kc[i]) // ti
            {
                for (int tj : g_Kc[j]) // tj
                {
                    finalCost += g_commMatrix[ti][tj];
                }
            }
        }
    }
    cout << "finalCost:" << finalCost << endl;
    cout << "--------------" << endl;
}

void MMMSAArepeat()
{
    do
    {
        for (int i = 0; i < g_Kc.size(); i++) // ki
        {
            for (int j = i + 1; j < g_Kc.size(); j++) // kj
            {
                double larc = -1;
                for (int ti : g_Kc[i]) // ti
                {
                    for (int tj : g_Kc[j]) // tj
                    {
                        if (g_commMatrix[ti][tj] >= larc)
                        {
                            larc = g_commMatrix[ti][tj];
                        }
                    }
                }
                if (larc >= g_costThres)
                {
                    set<int> mergedSet;
                    mergedSet.insert(g_Kc[i].begin(), g_Kc[i].end());
                    mergedSet.insert(g_Kc[j].begin(), g_Kc[j].end());
                    if (mergedSet.size() <= MAX_TASK_NUM)
                    {
                        g_Kc.push_back(mergedSet);
                        g_Kc.erase(g_Kc.begin() + i);
                        g_Kc.erase(g_Kc.begin() + j - 1);
                    }
                }
            }
        }
        g_k = g_Kc.size();
        DE.push_back({g_costThres, g_k, g_Kc});
        g_costThres = g_costThres - GRANULARITY;
    } while (g_costThres != 0 && g_k != MODULE_NUM);
    if (g_costThres == 0 && g_k > MODULE_NUM)
    {
        cout << "Need MMMSAA for K1" << endl;
        g_costThres = g_costThresDefault;
        g_k = DE[DE.size() - 1].k;
        MMMSAArepeat();
    }
}

void MMMCAArepeat()
{
    do
    {
        for (int i = 0; i < g_Kc.size(); i++) // ki
        {
            for (int j = i + 1; j < g_Kc.size(); j++) // kj
            {
                double smac = 9999;
                for (int ti : g_Kc[i]) // ti
                {
                    for (int tj : g_Kc[j]) // tj
                    {
                        if (g_commMatrix[ti][tj] <= smac)
                        {
                            smac = g_commMatrix[ti][tj];
                        }
                    }
                }
                if (smac >= g_costThres)
                {
                    set<int> mergedSet;
                    mergedSet.insert(g_Kc[i].begin(), g_Kc[i].end());
                    mergedSet.insert(g_Kc[j].begin(), g_Kc[j].end());
                    if (mergedSet.size() <= MAX_TASK_NUM)
                    {
                        g_Kc.push_back(mergedSet);
                        g_Kc.erase(g_Kc.begin() + i);
                        g_Kc.erase(g_Kc.begin() + j - 1);
                    }
                }
            }
        }
        g_k = g_Kc.size();
        DE.push_back({g_costThres, g_k, g_Kc});
        g_costThres = g_costThres - GRANULARITY;
    } while (g_costThres != 0 && g_k != MODULE_NUM);
    if (g_costThres == 0 && g_k > MODULE_NUM)
    {
        cout << "Need MMMSAA for K1" << endl;
        g_costThres = g_costThresDefault;
        g_k = DE[DE.size()-1].k;
        MMMSAArepeat();
    }
}

void MMMAAArepeat()
{
    do
    {
        for (int i = 0; i < g_Kc.size(); i++) // ki
        {
            for (int j = i + 1; j < g_Kc.size(); j++) // kj
            {
                double sumc = 0.0;
                int num = 0;
                for (int ti : g_Kc[i]) // ti
                {
                    for (int tj : g_Kc[j]) // tj
                    {
                        sumc += g_commMatrix[ti][tj];
                        num++;
                    }
                }
                double avgc = sumc / num;
                if (avgc >= g_costThres)
                {
                    set<int> mergedSet;
                    mergedSet.insert(g_Kc[i].begin(), g_Kc[i].end());
                    mergedSet.insert(g_Kc[j].begin(), g_Kc[j].end());
                    if (mergedSet.size() <= MAX_TASK_NUM)
                    {
                        g_Kc.push_back(mergedSet);
                        g_Kc.erase(g_Kc.begin() + i);
                        g_Kc.erase(g_Kc.begin() + j - 1);
                    }
                }
            }
        }
        g_k = g_Kc.size();
        DE.push_back({g_costThres, g_k, g_Kc});
        g_costThres = g_costThres - GRANULARITY;
    } while (g_costThres != 0 && g_k != MODULE_NUM);
    if (g_costThres == 0 && g_k > MODULE_NUM)
    {
        cout << "Need MMMSAA for K1" << endl;
        g_costThres = g_costThresDefault;
        g_k = DE[DE.size() - 1].k;
        MMMSAArepeat();
    }
}

void printDE()
{
    for (const auto &item : DE)
    {
        cout << "c: " << item.c << ", k: " << item.k << "  Kc: ";
        for (const auto &set : item.Kc)
        {
            cout << "{";
            for (int elem : set)
            {
                std::cout << elem + 1 << ",";
            }
            cout << "}, ";
        }
        cout << endl;
        cout << "--------------" << endl;
    }
}
void MMMSAA()
{
    cout << "MMMSAA Start!" << endl;
    MMMinit();
    MMMSAArepeat();
    printDE();
    getFinalCost();
    cout << "MMMSAA End!" << endl;
}

void MMMCAA()
{
    cout << "MMMCAA Start!" << endl;
    MMMinit();
    MMMCAArepeat();
    printDE();
    getFinalCost();
    cout << "MMMCAA End!" << endl;
}

void MMMAAA()
{
    cout << "MMMAAA Start!" << endl;
    MMMinit();
    MMMAAArepeat();
    printDE();
    getFinalCost();
    cout << "MMMAAA End!" << endl;
}

int main()
{
    MMMSAA();
    MMMCAA();
    MMMAAA();
    return 0;
}

相關文章