Thuật toán cho bài toán lập và điều khiển tiến độ
Thuật toán lập và điều khiển tiến độ: Biểu diễn sơ đồ mạng sang sơ đồ ngang.
Để thực hiện được quá trình đưa sơ đồ mạng sang sơ đồ ngang ta triển khai các thuật toán chi tiết như sau:
Thuật toán sắp xếp lại các công việc theo thứ tự topo:
Input: mảng T với nT công việc, ma trận A biểu diễn quan hệ giữa các công việc ban đầu có cỡ nT x nT. Quan hệ giữa các công việc phải không có chu trình.
Output: ma trận A biểu diễn quan hệ giữa các công việc theo trật tự tôpô, mảng Order lưu thứ tự các công việc sau khi đã sắp xếp tôpô.
Void Topo;
{ //tạo mảng Order với thứ tự các công việc theo trật tự topo. k=0; //số đỉnh trọc trong một lần xét.
do{ d=0;
for (i=1;i<=nT; i++)
if (cột(A,i)&&(KT[i]==0)){ k=k+1; d=d+1; Order[k]=i; KT[i]=1; }
if (d==0) break; //lỗi sắp topo có chu trình for (i=d-k+1; i=k;i++)
Xoahang(A,i); //xoá hàng i,cột i trong A. }
while (k==nT);
if (d==0) cout<<”lỗi sắp topo có chu trình”; //xác định lại bảng công việc T theo thứ tự Order T1=T; //lưu mảng T for (i=1;i<=nT;i++) { T[i]=T1[Order[i]]; for (j=1; j<=T[i].truoc[0];j++) for (k=1;k<=i-1;k++) if(T[i].truoc[j]==Order[k]) T[i].truoc[j]=k; T[i].tt=i;
for (j=1; j<=(T[j].truoc[0]-1);j++)
for (k=1; k<=T[i].truoc[0];k++)
if(T[i].truoc[i]>T[i].truoc[k])
Đổichỗ(T[i].truoc[i],T[i].truoc[k]); }
//Tạo lại ma trận A từ bảng công việc T mới
}
Thuật toán chuyển đồ thị biểu diễn công việc sang đồ thị biểu diễn sự kiện
Input : ma trận biểu diễn quan hệ công việc A
Output: ma trận biểu diễn sự kiện B của sơ đồ mạng Trong thuật toán có sử dụng các hàm :
int ladinhket(i,A):Hàm nhận giá trị 1 nếu đỉnh i không có cung đi ra trong đồ thị công việc biểu diễn bằng ma trận A và nhận giá trị 0 nếu ngược lại.
int khongcodinhvao(A,i): Hàm nhận giá trị 1 nếu đỉnh i không có cung đi vào trong đồ thị công việc biểu diễn bằng ma trận A và nhận giá trị 0 nếu ngược lại.
void chuyen() { Khởi tạo mang B=0;
sMax=1; //số sự kiện
for (i=1; I<=nT; I++ )
{if (ladinhket(I,A)==0) tăng thêm 1 đỉnh cho nS;
if (ladinhket(I,A)==1))
{ tăng_thêm_một_đỉnh_cho_nS; }
if (khongcodinhvao(A,i)==0) B[1][nS] = i;
co1dinhvao(A,i,&cout1,&thu1); //tính toán số cung đi vào đỉnh i //trả vào cout1, thu1 lưu giá trị của hàng có 1 phần tử đầu tiên.
if (cout1==1) //chỉ có một cung vào đỉnh i
{for (hang=1; hang<=nS; hang++)
for (cot=1;cot<=nS; cot++)
{/*Tìm nút sự kiện kết thúc công việc trước.
Nối nút sự kiện vừa thêm băng công việc đang xét*/
if(B[hang][cot]==thư1) B[cot][nS] =i; } }
else //cout1 >1 có nhiều cung vào
{
Chọn cung có thứ tự bé nhất;
Xác định công việc trước của cung này trong ma trận A; Tìm_sự kiện kết thúc công việc này trong đồ thị biểu diễn bằng ma trận B;
Nối nút này với sự kiện mới thêm; Đánh số cung này là sự kiện đang xét;
//Các bước trên thực hiện tương tự như trường hợp cout=1
Duyệt tất cả các cung còn lại, tạo một công việc ảo đến sự kiện đã chọn;
} } //end of for
Nếu có nhiều đỉnh kết, ta chọn một trong các đỉnh đó làm đỉnh kết, nối các đỉnh kia với đỉnh được chọn bằng một công việc ảo.
}//end of chuyen
Thuật toán tìm đường găng
Input: Ma trận B[][], mảng sự kiện s[], mảng công việc T[]
Output: các công việc găng ghi trong mảng G[][]
Void Criticalpath;
{ // Tính thời gian sớm của mỗi sự kiện
s[1].tgs=0; s[1].before[0]=1; s1.before1=0;
for (i=2; i<=sMax; i++)
{ d=0;
for (j=1; j<=i-1; j++)
Tìm sự kiện có cung tới i với tổng
s[i].tgs+T[B[i][j]].tgian lớn nhất;
Ghi các sự kiện có tổng s[j].tgs+T[B[i][j]].tgian đạt max vào trường trường before
} //end of i
//tính thời gian muộn của mỗi sự kiện
s[nS].tgm=s[nS].tgs;
for (i=nS-1; i>=1; i++) { for(j=nS; j>=i+1;j++ )
Tìm tgmin=min{ s[j].tgm-T[B[i][j].tgian }của sự kiện j có cung đến i;
s[i].tgm=tgmin; } //end of i
//tính thời gian dự trữ của từng sự kiện
for (i=1; i<=nS; i++)
D[i]=s[i].tgm-s[i].tgs;
//Tìm đường găng
Duyệt các sự kiện có dự trữ D[i]=0 theo các chỉ số ghi trong trường before của từng sự kiện;
Khi được 1 sự kiện thì tăng i;
if ((s[i].before[0]=1) &&(s[i].before[1]=0)) Ghi tất cả các sự kiện đó vào mảng G;
Thuật toán đưa ra mức tài nguyên ban đầu
Input: Mảng công việc T[], mảng sự kiện s[], ma trận B[][] của đồ thị sự kiện.
Output: Mảng Rs[] lưu mức sử dụng tài nguyên trong từng thời điểm và mảng Tg[] lưu thời gian tương ứng với Rs[], mảng c[] lưu mốc thời gian đánh dấu thời điểm có ít nhất một công việc bắt đầu hay kết thúc
Trong thuật toán này ta sử dụng mảng T1[] làm trung gian để xét các công việc có cùng thời gian khởi sớm.
Void Tai_nguyen_ban_dau(); {
int d1=0; //số phần tử của mảng T1[] .
int d=1; //số phần tử của mảng Tg[] và Rs[].
int khs[50]; //mảng lưu thời gian khởi sớm của mỗi công việc.
Khởi tạo T1[]=0;
Tính các giá trị thời gian khởi sớm khs[] cho từng công việc; i=1;
T1[1]=T[1]; c[1]=0;
while (i<=nT) //khi nào vẫn còn những công việc chưa được xét
Chép từ T[] vào T1[] những côngviệc có cùng thời gian khởi sớm khs[i] và lưu lại chỉ số của công việc lần cuối cùng được chép từ T[] sang T1[] vào biến luu;
Đặt một mốc c[j] = khs[i], với mỗi công thời điểm kết thúc một công việc, ta tạo thêm một mốc c[k] = khs[i] + T[k].tgian
} d1=1; i=luu+1; T1[1]=T[i];
i++; //Sang công việc tiếp theo
}
Sắp xếp các mốc c[] theo chiều tăng dần. Giữ lại các mốc khác nhau trong mảng c[], ta được m mốc
Tổng thời gian thực hiện là Tgd = c[m], số khoảng phân biệt là m- 1.
J=1
While (j<m) {
Tg[j]= c[j+1] - c[j]
Tính tổng tài nguyên các công việc đang được thực hiện trong đoạn (c[j], c[j+1]), đưa vào Rs[j]