#include "MindEvaluation.h" #include "CMind.h" #include "dbService/NodeMatrixService.h" #include "dbService/UserConfigService.h" #include "algorithm/HierarchicalAnalysis.h" #include "algorithm/EntropyWeights.h" #include "algorithm/PCA.h" #include #include MindEvaluation::MindEvaluation(CMind *mind, int expertId, const QString &tableType, int mindMatrix, QObject *parent) : QObject(parent), m_mind(mind), m_expertId(expertId), m_tableType(tableType), m_mindMatrix(mindMatrix), m_isAggregationOp(false) { init(); } MindEvaluation::MindEvaluation(CMind *mind, MindEvaluation::AggregationType atype, const QString &tableType, int mindMatrix, QObject *parent) : QObject(parent), m_mind(mind), m_tableType(tableType), m_mindMatrix(mindMatrix), m_aggregationType(atype), m_isAggregationOp(true) { } MindEvaluation::~MindEvaluation() { } void MindEvaluation::updateSeqNodes() { m_mind->getSeqNodes(m_seqNodes); } static QList> getMatrixString(const QStringList &in) { QList> res; const int n = in.size(); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { res << QPair(in.at(i), in.at(j)); } } return res; } void MindEvaluation::computeWeights() { if (!m_isAggregationOp) { computeSingleWeights(); } else { if (m_aggregationType == NoMerge) { computeNoMergeWeights(); } else { computeMergeWeights(); } } } void MindEvaluation::init() { updateSeqNodes(); } void MindEvaluation::computeSingleWeights() { QList nmInfos; if (!NodeMatrixService().QueryNodeMatrixListByExpertIdAndEngineerId(&nmInfos, m_expertId, m_mind->root().projectId, m_tableType)) { QMessageBox::warning(nullptr, "警告", "数据库访问失败"); return; } for (int sn = 0; sn < m_seqNodes.count(); sn++) { qDebug() << "第" << sn << "层"; for (auto s : m_seqNodes.at(sn)) { qDebug() << s.name << s.childs; if (m_mindMatrix == 0) { // 层次分析法 auto matrixStr = getMatrixString(s.childs); QVector nxnValus(matrixStr.size(), 0.0001); // n x n矩阵 for (const auto &nmInfo : nmInfos) { if (nmInfo->mindId == m_mindMatrix) { int loc = matrixStr.indexOf(QPair(nmInfo->abscissa, nmInfo->ordinate)); if (loc >= 0) { QStringList nodeValue = nmInfo->nodeValue.split("/"); if (nodeValue.size() == 1) { nxnValus[loc] = nodeValue[0].toDouble(); } else { nxnValus[loc] = nodeValue[0].toDouble() / nodeValue[1].toDouble(); } } } } QScopedPointer ha(new HierarchicalAnalysis(s.childs.size(), nxnValus)); QVector weights = ha->getWeights(); for (int c = 0; c < s.childs.size(); ++c) { mindNodeWeights << MindNodeItem { s.name, s.childs.at(c), weights.at(c), 0 }; } } else { // 熵权法 if (1) { QMap> seqMap; for (const auto &nmInfo : nmInfos) { if (nmInfo->mindId == m_mindMatrix) { int loc = s.childs.indexOf(nmInfo->abscissa); // 指标索引 if (loc >= 0) { QStringList nodeValue = nmInfo->nodeValue.split("/"); double v; if (nodeValue.size() == 1) { v = nodeValue[0].toDouble(); } else { v = nodeValue[0].toDouble() / nodeValue[1].toDouble(); } if (!seqMap.contains(nmInfo->abscissa)) { seqMap.insert(nmInfo->abscissa, QMap()); } seqMap[nmInfo->abscissa].insert(nmInfo->strUuid, v); } } } EntropyMat eMat; // 一个指标一行数据 for (const auto &c : s.childs) { if (seqMap.contains(c)) { QVector indexVecs; QMapIterator iter(seqMap[c]); while (iter.hasNext()) { iter.next(); indexVecs << iter.value(); } eMat << indexVecs; } else { QMessageBox::warning(nullptr, "警告", QString("指标%1数据缺失").arg(c)); } } QScopedPointer ew(new EntropyWeights(eMat)); QVector weights, score; ew->compute(weights, score); for (int c = 0; c < s.childs.size(); ++c) { mindNodeWeights << MindNodeItem { s.name, s.childs.at(c), weights.at(c), score.at(c) }; } } else { // pca QMap> seqMap; for (const auto &nmInfo : nmInfos) { if (nmInfo->mindId == m_mindMatrix) { int loc = s.childs.indexOf(nmInfo->abscissa); // 指标索引 if (loc >= 0) { QStringList nodeValue = nmInfo->nodeValue.split("/"); double v; if (nodeValue.size() == 1) { v = nodeValue[0].toDouble(); } else { v = nodeValue[0].toDouble() / nodeValue[1].toDouble(); } if (!seqMap.contains(nmInfo->strUuid)) { seqMap.insert(nmInfo->strUuid, QMap()); } seqMap[nmInfo->strUuid].insert(nmInfo->abscissa, v); } } } QVector> pMat; // 一个指标一列数据 QMapIterator> iter(seqMap); while (iter.hasNext()) { iter.next(); QMap indexMap = iter.value(); QVector tmp; QMapIterator iterIndex(indexMap); while (iterIndex.hasNext()) { iterIndex.next(); tmp << iterIndex.value(); } pMat << tmp; } QScopedPointer pca(new PCA(pMat)); pca->compute(); QVector weights = pca->weights(); QVector score = pca->scores(); for (int c = 0; c < s.childs.size(); ++c) { mindNodeWeights << MindNodeItem { s.name, s.childs.at(c), weights.at(c), score.at(c) }; } } } } } qDeleteAll(nmInfos); } /// 数据集结,先计算每个专家的权重,在求均值 void MindEvaluation::computeNoMergeWeights() { int enjId = m_mind->root().projectId; QList users; if (!UserConfigService().QueryUserConfigListInfoByEngineerId(&users, enjId)) { QMessageBox::warning(nullptr, "警告", "数据库访问失败"); return; } bool QueryUserConfigListInfoByEngineerId(QList * userCfgList, int engineerId); QScopedPointer>> allItems(new QList>()); for (const auto &user : users) { QList nmInfos; if (!NodeMatrixService().QueryNodeMatrixListByExpertIdAndEngineerId(&nmInfos, user->id, enjId, m_tableType)) { qDeleteAll(users); QMessageBox::warning(nullptr, "警告", "数据库访问失败"); return; } QList mnItem; computeOneEntry(nmInfos, mnItem); allItems->append(mnItem); qDeleteAll(nmInfos); } qDeleteAll(users); for (int i = 0; i < allItems->size(); ++i) { if (i == 0) { mindNodeWeights = allItems->at(0); } else { for (const auto &item : allItems->at(i)) { int id = mindNodeWeights.indexOf(item); mindNodeWeights[id].value += item.value; mindNodeWeights[id].score += item.score; } } } for (int id = 0; id < mindNodeWeights.size(); id++) { mindNodeWeights[id].value /= allItems->size(); mindNodeWeights[id].score /= allItems->size(); } } /// 数矩阵集结,先计算出一个综合专家,在计算权重 void MindEvaluation::computeMergeWeights() { int enjId = m_mind->root().projectId; QList users; if (!UserConfigService().QueryUserConfigListInfoByEngineerId(&users, enjId)) { QMessageBox::warning(nullptr, "警告", "数据库访问失败"); return; } bool QueryUserConfigListInfoByEngineerId(QList * userCfgList, int engineerId); QList megerNMInfo; QVector nodeValues; for (const auto &user : users) { QList nmInfos; if (!NodeMatrixService().QueryNodeMatrixListByExpertIdAndEngineerId(&nmInfos, user->id, enjId, m_tableType)) { qDeleteAll(users); QMessageBox::warning(nullptr, "警告", "数据库访问失败"); return; } if (megerNMInfo.size() == 0) { for (int nm = 0; nm < nmInfos.size(); ++nm) { NodeMatrixInfo *info = nmInfos.at(nm); megerNMInfo.append(new NodeMatrixInfo()); *megerNMInfo[0] = *info; double v; QStringList nds = nmInfos.at(nm)->nodeValue.split("/"); if (nds.size() == 1) { v = nds.at(0).toDouble(); } else { v = nds.at(0).toDouble() / nds.at(1).toDouble(); } nodeValues << v; } } else { for (int nm = 0; nm < nmInfos.size(); ++nm) { double v; QStringList nds = nmInfos.at(nm)->nodeValue.split("/"); if (nds.size() == 1) { v = nds.at(0).toDouble(); } else { v = nds.at(0).toDouble() / nds.at(1).toDouble(); } nodeValues[nm] += v; } } qDeleteAll(nmInfos); } for (int nm = 0; nm < megerNMInfo.size(); ++nm) { megerNMInfo[nm]->nodeValue = QString::number(nodeValues[nm] / users.size()); } computeOneEntry(megerNMInfo, mindNodeWeights); qDeleteAll(megerNMInfo); qDeleteAll(users); } void MindEvaluation::computeOneEntry(const QList &nmInfos, QList &mindNodeItem) { for (int sn = 0; sn < m_seqNodes.count(); sn++) { qDebug() << "第" << sn << "层"; for (auto s : m_seqNodes.at(sn)) { qDebug() << s.name << s.childs; if (m_mindMatrix == 0) { // 层次分析法 auto matrixStr = getMatrixString(s.childs); QVector nxnValus(matrixStr.size(), 0.0001); // n x n矩阵 for (const auto &nmInfo : nmInfos) { if (nmInfo->mindId == m_mindMatrix) { int loc = matrixStr.indexOf(QPair(nmInfo->abscissa, nmInfo->ordinate)); if (loc >= 0) { QStringList nodeValue = nmInfo->nodeValue.split("/"); if (nodeValue.size() == 1) { nxnValus[loc] = nodeValue[0].toDouble(); } else { nxnValus[loc] = nodeValue[0].toDouble() / nodeValue[1].toDouble(); } } } } QScopedPointer ha(new HierarchicalAnalysis(s.childs.size(), nxnValus)); QVector weights = ha->getWeights(); for (int c = 0; c < s.childs.size(); ++c) { mindNodeItem << MindNodeItem { s.name, s.childs.at(c), weights.at(c), 0 }; } } else { // 熵权法 if (1) { QMap> seqMap; for (const auto &nmInfo : nmInfos) { if (nmInfo->mindId == m_mindMatrix) { int loc = s.childs.indexOf(nmInfo->abscissa); // 指标索引 if (loc >= 0) { QStringList nodeValue = nmInfo->nodeValue.split("/"); double v; if (nodeValue.size() == 1) { v = nodeValue[0].toDouble(); } else { v = nodeValue[0].toDouble() / nodeValue[1].toDouble(); } if (!seqMap.contains(nmInfo->abscissa)) { seqMap.insert(nmInfo->abscissa, QMap()); } seqMap[nmInfo->abscissa].insert(nmInfo->strUuid, v); } } } EntropyMat eMat; // 一个指标一行数据 for (const auto &c : s.childs) { if (seqMap.contains(c)) { QVector indexVecs; QMapIterator iter(seqMap[c]); while (iter.hasNext()) { iter.next(); indexVecs << iter.value(); } eMat << indexVecs; } else { QMessageBox::warning(nullptr, "警告", QString("指标%1数据缺失").arg(c)); } } QScopedPointer ew(new EntropyWeights(eMat)); QVector weights, score; ew->compute(weights, score); for (int c = 0; c < s.childs.size(); ++c) { mindNodeItem << MindNodeItem { s.name, s.childs.at(c), weights.at(c), score.at(c) }; } } else { // pca QMap> seqMap; for (const auto &nmInfo : nmInfos) { if (nmInfo->mindId == m_mindMatrix) { int loc = s.childs.indexOf(nmInfo->abscissa); // 指标索引 if (loc >= 0) { QStringList nodeValue = nmInfo->nodeValue.split("/"); double v; if (nodeValue.size() == 1) { v = nodeValue[0].toDouble(); } else { v = nodeValue[0].toDouble() / nodeValue[1].toDouble(); } if (!seqMap.contains(nmInfo->strUuid)) { seqMap.insert(nmInfo->strUuid, QMap()); } seqMap[nmInfo->strUuid].insert(nmInfo->abscissa, v); } } } QVector> pMat; // 一个指标一列数据 QMapIterator> iter(seqMap); while (iter.hasNext()) { iter.next(); QMap indexMap = iter.value(); QVector tmp; QMapIterator iterIndex(indexMap); while (iterIndex.hasNext()) { iterIndex.next(); tmp << iterIndex.value(); } pMat << tmp; } QScopedPointer pca(new PCA(pMat)); pca->compute(); QVector weights = pca->weights(); QVector score = pca->scores(); for (int c = 0; c < s.childs.size(); ++c) { mindNodeItem << MindNodeItem { s.name, s.childs.at(c), weights.at(c), score.at(c) }; } } } } } }