基本概念:
引自 《混合差分进化与调度算法》-王凌 ,图中应该漏标了两个关键路径节点(实心点),但不影响理解。LBFSP可以转化为有向无环图模型,在工件数n、机器数m、缓冲区容量Bj,j+1都确定的情况下,工件的排序不同,图中顶点的权值和倾斜边的权值也不同(水平边和垂直边权值均为0),但图的结构并不会发生变化。
LBFSP有向图c++实现如下。
#include <iostream>
#include <vector>
#include <numeric>
using namespace std;
//边
struct Edge {
vector<int> from; //边的起点
vector<int> to; //边指向的顶点
double weight; //边的权重,LBFSP中水平边和垂直边权重为0,倾斜边(缓冲区约束)权重为边的起点对应的加工时间的相反数
Edge() {}
Edge(vector<int> from, vector<int> to, double weight = 0.0): from(from), to(to), weight(weight) {}
};
//顶点
struct Node {
vector<int> op; //顶点的编号,即工序号,从(1, 1)到(n, m),共n*m个
vector<Edge> edges; //顶点的出边
double weight; //顶点的权重,LBFSP中顶点权重为对应工序的加工时间
int in_degree = 0; //顶点的入度(用于拓扑排序)
};
int main()
{
int n = 5, m = 5; //n为工件数,m为机器数
vector<vector<Node*>> DAG(n, vector<Node*>(m, nullptr)); //邻接表
vector<int> b(m - 1, 0); //机器j与j + 1间的缓冲区容量
vector<vector<double>> T(n, vector<double>(m, 0)); //加工时间
vector<int> solution(n, 0);
iota(solution.begin(), solution.end(), 1); //工件的排序(序号从1到n) {1,2,3,4,5}
T[0] = { 1, 1, 1, 1, 1 };
T[1] = { 1, 2, 2, 1, 1 };
T[2] = { 3, 1, 1, 2, 1 };
T[3] = { 1, 1, 2, 3, 1 };
T[4] = { 1, 2, 3, 1, 4 };
/* 有向图建立 */
//初始化顶点
for (auto& nodes : DAG) {
for (auto& node : nodes) node = new Node();
}
//顶点编号和顶点权重
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
DAG[i][j]->op = vector<int>{ i + 1, j + 1 };
DAG[i][j]->weight = T[solution[i] - 1][j];
}
}
//边和边的权重
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
//工件顺序约束
if (i - 1 >= 0) {
DAG[i - 1][j]->edges.push_back(Edge({ i - 1, j }, { i, j }, 0.0));
DAG[i][j]->in_degree++;
}
//机器顺序约束
if (j - 1 >= 0) {
DAG[i][j - 1]->edges.push_back(Edge({ i, j - 1 }, { i, j }, 0.0));
DAG[i][j]->in_degree++;
}
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
//缓冲区约束
if (j + 1 < m && i - b[j] - 1 >= 0) {
DAG[i - b[j] - 1][j + 1]->edges.push_back(Edge({ i - b[j] - 1, j + 1 }, { i, j }, -T[solution[i - b[j] - 1] - 1][j + 1]));
DAG[i][j]->in_degree++;
}
}
}
/* 有向图建立完毕 */
//打印输出
int i = 1;
for (auto& nodes : DAG) {
int j = 1;
for (auto& node : nodes) {
cout << "******** " << i << ", " << j << "********" << endl;
cout << "顶点编号:" << node->op[0] << " " << node->op[1] << endl;
cout << "顶点出边数:" << node->edges.size() << endl;
cout << "顶点入度:" << node->in_degree << endl;
cout << "顶点权值:" << node->weight << endl;
cout << "******** " << i << ", " << j++ << "********" << endl;
}
cout << endl;
i++;
}
cout << "****** 特定点的出边详细信息 ******" << endl;
cout << "**(1, 1):" << endl;
for (auto& edge : DAG[0][0]->edges) {
cout << "------------" << endl;
cout << "(" << edge.from[0] << ", " << edge.from[1] << ") -> ";
cout << "(" << edge.to[0] << ", " << edge.to[1] << ")" << endl;
cout << edge.weight << endl;
cout << "------------" << endl;
}
cout << endl << "**(3, 3):" << endl;
for (auto& edge : DAG[2][2]->edges) {
cout << "------------" << endl;
cout << "(" << edge.from[0] << ", " << edge.from[1] << ") -> ";
cout << "(" << edge.to[0] << ", " << edge.to[1] << ")" << endl;
cout << edge.weight << endl;
cout << "------------" << endl;
}
cout << endl << "**(5, 5):" << endl;
for (auto& edge : DAG[4][4]->edges) {
cout << "------------" << endl;
cout << "(" << edge.from[0] << ", " << edge.from[1] << ") -> ";
cout << "(" << edge.to[0] << ", " << edge.to[1] << ")" << endl;
cout << edge.weight << endl;
cout << "------------" << endl;
}
}