基本概念:
在关键路径法中,一般有以下一些时间参数:
最早开始时间(Early Start)活动最早开始时间由所有前置活动中最后一个最早结束时间确定。
最早结束时间(Early Finish)活动的最早结束时间由活动的最早开始时间加上其工期确定。
最迟结束时间(Late Finish)一个活动在不耽误整个项目的结束时间的情况下能够最迟开始的时间。它等于所有紧后工作中最早的一个最晚开始时间。
最迟开始时间(Late Start)一个活动在不耽误整个项目的结束时间的情况下能够最早开始的时间。它等于活动的最迟结束时间减去活动的工期。
总时差(Total Float) 指一项活动在不影响整体计划工期的情况下最大的浮动时间。
自由时差(Free Float)指活动在不影响其紧后工作的最早开始时间的情况下可以浮动的时间。
*
*
算法原理-前导图(PDM)法:
对于活动的最早开始和最早结束时间,采用正推法计算,其算法如下所示:
1.将第一个活动的最早开始时间设置为1.
2.在活动的最早开始时间上加上其工期,得到活动的最早结束时间。
3.根据该活动与后置活动的逻辑关系,计算后置活动应该的最早开始时间,并与其已有的最早开始时间对比,如果其后置活动还没有设置最早开始时间,则将此时间设为其最早开始时间,如果此时间早于其后置活动已有的最早开始时间,则保留后置活动的原有最早开始时间,如果此时间迟于其后置活动已有的最早开始时间,则将此时间设置为后置活动的最迟开始时间。
4.重复步骤2和3,直到所有活动的时间被计算完为止。
对于以上所示的最早时间的计算过程,可以以公式的形式表示如下:
当活动间的逻辑关系为SS,则计算如下
ESj=max{ ESi + STS}
当活动间的逻辑关系为FS,则计算如下
ESj= max{ESi+ Di+ FTS}
当活动间的逻辑关系为FF,计算如下
ESj= max{ESi+ Di - Dj +FTF}
当活动间的逻辑关系为SF,计算如下
ESj=max{ ESi - Dj +STF}
在计算出各个活动的最早开始和结束时间之后,就可以计算活动的自由时差,在计算前导图(PDM)的自由时差时应注意,由于引入了多种逻辑关系,并且活动间可以存在延时,所以其计算方法与箭线图(ADM)的计算方法不一样。
对于前导图(PDM)的活动间,除了延时还可以存在时间间隔(LAG),一般可以按照下面的方式计算。
当活动间的逻辑关系为SS,则计算如下
LAGi-j= ESj- ESi- STS
当活动间的逻辑关系为FS,则计算如下
LAGi-j= ESj- EFi- FTS
当活动间的逻辑关系为FF,计算如下
LAGi-j= EFj- EFi- FTF
当活动间的逻辑关系为SF,计算如下
LAGi-j= EFj- ESi- STF
则对于任意一个活动,其自由时差为
FFi=min{ LAGi-j}
最后一个活动的自由时差为0.
对于总时差,终点节点的总时差为0,对于其它任意一个节点,总时差按照下式进行计算
TFi=min{TFj+ LAGi-j}
对于任意一个活动的最晚开始时间可以由其最早开始时间加上总时差得到,同样,其最晚开始时间可以由最早结束时间加上其总时差得到,公式表示如下
LSi=ESi+TFi
LFi=EFi+TFi
package com.ryan.activity;
import java.util.LinkedList;
import java.util.List;
/**
* TASK基础类
*
* @author ryan
*/
public class Task {
private String taskNumber;//任务编号
private String logic;//任务之间的逻辑关系
private double earlyStartTime;//最早开始时间
private double earlyFinishTime;//最早结束时间
private double lateStartTime;//最晚开始时间
private double lateFinishTime;//最晚结束时间
private double dut;//执行时间
private double delayTime;//延迟时间
private double slack;//机动时间
private String[] logicArray;//任务之间的逻辑关系
private double[] earlyStartTimeArray;//最早开始时间
private double[] earlyFinishTimeArray;//最早结束时间
private double[] lateStartTimeArray;//最晚开始时间
private double[] lateFinishTimeArray;//最晚结束时间
private double[] dutArray;//执行时间
private double[] delayTimeArray;//延迟时间
private double[] slackArray;//机动时间
private boolean isCalEST = false;//是否计算了最早开始时间
private boolean isCalEFT = false;//是否计算了最早结束时间
private boolean isCalLST = false;//是否计算了最晚开始时间
private boolean isCalLFT = false;//是否计算了最晚结束时间
private boolean isCalSlack = false;//是否计算了机动时间
private boolean isCalETArray = false;//是否计算了最早开始时间
private boolean isCalLTArray = false;//是否计算了最晚开始时间
private boolean isCalSlackArray = false;//是否计算了机动时间
private boolean isCriticalPath = false;//是否是关键路径
private List<Task> previousTasks = new LinkedList<Task>();//前置任务集合
private List<Task> nextTasks = new LinkedList<Task>();//后置任务集合
/*
* 计算最早开始时间
*/
public void calculateET(){
if(!this.isCalEST()){
double est = 0.0d;//临时存放最早开始时间
boolean isTmp = false;//标记是否执行了逻辑关系中的代码
if(this.getPreviousTasks().size()==0){//第一个任务是没有前置任务的,所以其最早开始时间是0
this.earlyStartTime = est;
this.isCalEST = true;
} else {
if("FS".equals(logic)){//ES= max{ES(前)+ Dur(前)+ FTS}
for(Task previousTask : this.getPreviousTasks()){
if(previousTask.getEarlyFinishTime()>est && previousTask.isCalEFT()){
est = previousTask.getEarlyFinishTime();
isTmp = previousTask.isCalEFT();
}
}
est = est + this.getDelayTime();
}else if("FF".equals(logic)){//ES= max{ES(前)+ Dur(前) - Dur +FTF}
for(Task previousTask : this.getPreviousTasks()){
if(previousTask.getEarlyFinishTime()>est && previousTask.isCalEFT()){
est = previousTask.getEarlyFinishTime();
isTmp = previousTask.isCalEFT();
}
}
est = est + this.getDelayTime() - this.getDut();
}else if("SS".equals(logic)){//ES=max{ ES(前) + STS}
for(Task previousTask : this.getPreviousTasks()){
if(previousTask.getEarlyStartTime()>est && previousTask.isCalEST()){
est = previousTask.getEarlyStartTime();
isTmp = previousTask.isCalEST();
}
}
est = est + this.getDelayTime();
}else if("SF".equals(logic)){//ES=max{ ES(前) - Dur +STF}
for(Task previousTask : this.getPreviousTasks()){
if(previousTask.getEarlyStartTime()>est && previousTask.isCalEST()){
est = previousTask.getEarlyStartTime();
isTmp = previousTask.isCalEST();
}
}
est = est - this.getDut() + this.getDelayTime();
}
if(isTmp){
this.earlyStartTime = est;
this.isCalEST = true;
}
}
}
if(!this.isCalEFT() && this.isCalEST()){
this.earlyFinishTime = this.getEarlyStartTime() + this.getDut();
this.isCalEFT = true;
}
}
/*
*计算最晚时间
*/
public void calculateLT(){
if(!this.isCalLST()){
calculateLT(this.nextTasks,this);
}
if(!this.isCalLFT()){
calculateLT(this.nextTasks,this);
}
}
/*
* task的后置任务nextTasks
*/
public void calculateLT(List<Task> nextTasks,Task task){
double tmpSlack = 0.0d;//临时时间差
boolean isTmp = false;//标记
if(nextTasks.size()==0 ){
if(task.isCalEST() && task.isCalEFT()){
task.lateFinishTime = task.getEarlyFinishTime();
task.slack = 0.0d;
task.isCalLFT = true;
task.isCalSlack = true;
task.lateStartTime = task.getEarlyStartTime();
task.slack = 0.0d;
task.isCalLST = true;
task.isCalSlack = true;
}
} else{
for(int i = 0; i<nextTasks.size(); i++){
Task nextTask = nextTasks.get(i);
if(!nextTask.isCalLFT())
return;
if(!nextTask.isCalLST())
return;
if(nextTask.isCalSlack){
double _tmp = tmpSlack;//临时时间间隔
if("FS".equals(nextTask.logic) && nextTask.isCalEST() && task.isCalEFT()){//Slack = min{slack后+ES后-EF-FTS}
_tmp = nextTask.getSlack() + nextTask.getEarlyStartTime() - task.getEarlyFinishTime() - nextTask.getDelayTime();
isTmp = true;
}else if("FF".equals(nextTask.logic) && nextTask.isCalEFT() && task.isCalEFT()){//Slack = min{slack后+EF后-EF-FTF}
_tmp = nextTask.getSlack() + nextTask.getEarlyFinishTime() - task.getEarlyFinishTime() - nextTask.getDelayTime();
isTmp = true;
}else if("SF".equals(nextTask.logic) && nextTask.isCalEFT() && task.isCalEST()){//Slack = min{slack后+EF后-ES-STF}
_tmp = nextTask.getSlack() + nextTask.getEarlyFinishTime() - task.getEarlyStartTime() - nextTask.getDelayTime();
isTmp = true;
}else if("SS".equals(nextTask.logic) && nextTask.isCalEST() && task.isCalEST()){//Slack = min{slack后+ES后-ES-STS}
_tmp = nextTask.getSlack() + nextTask.getEarlyStartTime() - task.getEarlyStartTime() - nextTask.getDelayTime();
isTmp = true;
}
if(i==0){
tmpSlack = _tmp;
}
if(_tmp < tmpSlack ){
tmpSlack = _tmp;
}
}
}
}
if(isTmp && task.isCalEST() && task.isCalEFT()){//isTmp标记为true,说明已经经过计算。
task.lateFinishTime = task.getEarlyFinishTime() + tmpSlack;
task.setSlack(tmpSlack);
task.isCalLFT = true;
task.isCalSlack = true;
task.lateStartTime = task.getEarlyStartTime() + tmpSlack;
task.setSlack(tmpSlack);
task.isCalLST = true;
task.isCalSlack = true;
}
}
/*
* 计算最早开始和最早结束时间
* */
public void calculateETArray(){
if(!this.isCalETArray()){
double[] dutArray = this.getDutArray();
double[] delayTimeArray = this.getDelayTimeArray();
String[] logicArray = this.getLogicArray();
double[] earlyStartTimeArray = new double[dutArray.length];
double[] earlyFinishTimeArray = new double[dutArray.length];
int ETCount = 0;
for (int i=0;i<dutArray.length;i++) {
this.setDelayTime(delayTimeArray[i]);
this.setLogic(logicArray[i]);
this.setDut(dutArray[i]);
this.calculateET();
earlyStartTimeArray[i] = this.getEarlyStartTime();
earlyFinishTimeArray[i] = this.getEarlyFinishTime();
ETCount++;
}
if(ETCount==dutArray.length){
this.setEarlyStartTimeArray(earlyStartTimeArray);
this.setEarlyFinishTimeArray(earlyFinishTimeArray);
this.setCalETArray(true);
}
}
}
/*
* 计算最晚开始和最晚结束时间
* */
public void calculateLTArray(){
if(!this.isCalLTArray()){
double[] dutArray = this.getDutArray();
double[] delayTimeArray = this.getDelayTimeArray();
String[] logicArray = this.getLogicArray();
double[] lateStartTimeArray = new double[dutArray.length];
double[] lateFinishTimeArray = new double[dutArray.length];
int LTCount = 0;
for (int i=0;i<dutArray.length;i++) {
this.setDelayTime(delayTimeArray[i]);
this.setLogic(logicArray[i]);
this.setDut(dutArray[i]);
this.calculateLT();
lateStartTimeArray[i] = this.getLateStartTime();
lateFinishTimeArray[i] = this.getLateFinishTime();
LTCount++;
}
if(LTCount==dutArray.length){
this.setLateStartTimeArray(lateStartTimeArray);
this.setLateFinishTimeArray(lateFinishTimeArray);
this.setCalLTArray(true);
}
}
}
/*
* taskNumber 任务编号
* logic 与前置任务的逻辑关系
* dut 任务执行时间
*delayTime 提前滞后时间
*/
public Task(String taskNumber,String logic, double dut, double delayTime) {
super();
this.taskNumber = taskNumber;
this.logic = logic;
this.dut = dut;
this.delayTime = delayTime;
}
/*
* taskNumber 任务编号
* logic 与前置任务的逻辑关系
* dut 任务执行时间数组
* delayTime 提前滞后时间数组
*/
public Task(String taskNumber,String[] logicArray, double[] dutArray, double[] delayTimeArray) {
super();
this.taskNumber = taskNumber;
this.logicArray = logicArray;
this.dutArray = dutArray;
this.delayTimeArray = delayTimeArray;
}
public String getTaskNumber() {
return taskNumber;
}
public void setTaskNumber(String taskNumber) {
this.taskNumber = taskNumber;
}
public double getDelayTime() {
return delayTime;
}
public void setDelayTime(double delayTime) {
this.delayTime = delayTime;
}
public double getDut() {
return dut;
}
public void setDut(double dut) {
this.dut = dut;
}
public double getEarlyFinishTime() {
return earlyFinishTime;
}
public double getEarlyStartTime() {
return earlyStartTime;
}
public double getLateFinishTime() {
return lateFinishTime;
}
public double getLateStartTime() {
return lateStartTime;
}
public double getSlack(){
return slack;
}
public void setSlack(double slack){
this.slack = slack;
}
public boolean isCalEST(){;
return isCalEST;
}
public boolean isCalEFT(){;
return isCalEFT;
}
public boolean isCalLST(){
return isCalLST;
}
public boolean isCalLFT(){
return isCalLFT;
}
public boolean isCriticalPath(){
return isCriticalPath;
}
public List<Task> getPreviousTasks() {
return previousTasks;
}
public String getLogic() {
return logic;
}
public void setLogic(String logic) {
this.logic = logic;
}
public void setPreviousTasks(List<Task> previousTasks) {
this.previousTasks = previousTasks;
for (Task task : this.previousTasks) {
task.getNextTasks().add(this);
}
}
public List<Task> getNextTasks() {
return nextTasks;
}
public void setNextTasks(List<Task> nextTasks) {
this.nextTasks = nextTasks;
}
public String[] getLogicArray() {
return logicArray;
}
public void setLogicArray(String[] logicArray) {
this.logicArray = logicArray;
}
public double[] getDelayTimeArray() {
return delayTimeArray;
}
public void setDelayTimeArray(double[] delayTimeArray) {
this.delayTimeArray = delayTimeArray;
}
public double[] getDutArray() {
return dutArray;
}
public void setDutArray(double[] dutArray) {
this.dutArray = dutArray;
}
public double[] getEarlyFinishTimeArray() {
return earlyFinishTimeArray;
}
public void setEarlyFinishTimeArray(double[] earlyFinishTimeArray) {
this.earlyFinishTimeArray = earlyFinishTimeArray;
}
public double[] getEarlyStartTimeArray() {
return earlyStartTimeArray;
}
public void setEarlyStartTimeArray(double[] earlyStartTimeArray) {
this.earlyStartTimeArray = earlyStartTimeArray;
}
public double[] getLateFinishTimeArray() {
return lateFinishTimeArray;
}
public void setLateFinishTimeArray(double[] lateFinishTimeArray) {
this.lateFinishTimeArray = lateFinishTimeArray;
}
public double[] getLateStartTimeArray() {
return lateStartTimeArray;
}
public void setLateStartTimeArray(double[] lateStartTimeArray) {
this.lateStartTimeArray = lateStartTimeArray;
}
public double[] getSlackArray() {
return slackArray;
}
public void setSlackArray(double[] slackArray) {
this.slackArray = slackArray;
}
public boolean isCalSlackArray() {
return isCalSlackArray;
}
public void setCalSlackArray(boolean isCalSlackArray) {
this.isCalSlackArray = isCalSlackArray;
}
public boolean isCalETArray() {
return isCalETArray;
}
public void setCalETArray(boolean isCalETArray) {
this.isCalETArray = isCalETArray;
}
public boolean isCalLTArray() {
return isCalLTArray;
}
public void setCalLTArray(boolean isCalLTArray) {
this.isCalLTArray = isCalLTArray;
}
public void setCriticalPath() {
if(this.isCalLST() && this.isCalEST()){
if(this.getLateStartTime()-this.getEarlyStartTime()==0)
this.isCriticalPath = true;
}
}
public void setCriticalPathArray() {
if(this.isCalLTArray() && this.isCalETArray()){
//TODO 待完成
}
}
}
还有一个封装测试类,利用随机数模拟蒙特卡洛模拟法(
http://baike.baidu.com/view/2692033.htm
)
package com.ryan.activity;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
/**
* Task的计算逻辑类
*
* @author ryan
*/
public class Wbs {
private List<Task> tasks;//所有任务集合
private Set<Task> noPreviousTasks;//没有前置任务的任务集合
private Set<Task> noNextTasks;//没有后置任务的任务集合
/**
* @param tasks 所有任务集合
* @return 没有前置任务的任务集合
*/
public Set<Task> getNoPreviousTasks(List<Task> tasks){
if(tasks!=null && tasks.size()>0){
for(Task task : tasks){
if(task!=null && task.getPreviousTasks().size()==0){
this.noPreviousTasks.add(task);
}
}
}
return this.noPreviousTasks;
}
/**
* @param tasks 所有任务集合
* @return 没有后置任务的任务集合
*/
public Set<Task> getNoNextTasks(List<Task> tasks){
if(tasks!=null && tasks.size()>0){
for(Task task : tasks){
if(task!=null && task.getNextTasks().size()==0){
this.noNextTasks.add(task);
}
}
}
return this.noNextTasks;
}
/**
* @param tasks 所有任务
* @return 没有前置任务计算完成之后,待计算的任务
*/
private Set<Task> calculateNoPreviousEarlyTime(List<Task> tasks){
// System.out.println("开始调用calculateNoPreviousEarlyTime(List<Task> tasks)------");
Set<Task> calTasks = new LinkedHashSet<Task>();
if(tasks!=null && tasks.size()>0){
Set<Task> noPreviousTasks = this.getNoPreviousTasks(tasks);
for(Task task : noPreviousTasks){
// System.out.println("没有前置任务的是"+task.getTaskNumber());
if(!task.isCalEST()&&!task.isCalEFT())
task.calculateET();
calTasks.add(task);
}
}
// System.out.println("结束调用calculateNoPreviousEarlyTime(List<Task> tasks)------");
return calTasks;
}
/**
* @param nextTasks 本次待计算的任务
* @return 下一次待计算的任务
*/
public Set<Task> calculateEarlyTime(Set<Task> nextTasks){
Set<Task> calTasks = new LinkedHashSet<Task>();
if(nextTasks!=null && nextTasks.size()>0){
Iterator<Task> it = nextTasks.iterator();
while(it.hasNext()){
Task task = it.next();
// System.out.println("本次需要计算的任务是"+task.getTaskNumber());
//找到本任务的前置任务看是不是全部计算完成了,
List<Task> befTask = task.getPreviousTasks();
//判断本任务的前置任务是不是完全计算完成的计数器
int count = 0;//计数器
for(int i=0;i<befTask.size();i++){
Task bfTask = befTask.get(i);
if(bfTask.isCalEST() && bfTask.isCalEFT())
count++;
}
//如果全部计算完成,将本任务的后置任务加入到返回列表里
if(count==befTask.size()){
task.calculateET();
// System.out.println("已经计算了"+task.getTaskNumber());
calTasks.addAll(task.getNextTasks());
//如果没有全部计算完成,把本任务加入到计算列表里
}else{
calTasks.add(task);
}
}
}
return calTasks;
}
/**
* @param tasks 所有任务
* @return 没有前置任务的下一层需要计算的任务
*/
public Set<Task> calNoNextTasksLateTime(List<Task> tasks){
Set<Task> calTasks = new LinkedHashSet<Task>();
if(tasks!=null && tasks.size()>0){
for (Task task : this.getNoNextTasks(tasks)) {
if(!task.isCalLST()&&!task.isCalLFT())
task.calculateLT();
calTasks.add(task);
}
}
return calTasks;
}
/**
* @param nextTasks 本次待计算的任务
* @return 下一次需要计算的任务
*/
public Set<Task> calculateLateTime(Set<Task> nextTasks){
Set<Task> calTasks = new LinkedHashSet<Task>();
if(nextTasks!=null && nextTasks.size()>0){
Iterator<Task> it = nextTasks.iterator();
while(it.hasNext()){
Task task = it.next();
//找到本任务的后置任务看是不是全部计算完成了,
List<Task> nextTask = task.getNextTasks();
//判断本任务的后置任务是不是完全计算完成的计数器
int count = 0;//计数器
for(int i=0;i<nextTask.size();i++){
Task ntTask = nextTask.get(i);
if(ntTask.isCalLST()&&ntTask.isCalLFT())
count++;
}
//如果全部计算完成,将本任务的后置任务加入到返回列表里
if(count==nextTask.size()){
task.calculateLT();
// System.out.println("计算的是"+task.getTaskNumber());
calTasks.addAll(task.getPreviousTasks());
//如果没有全部计算完成,把本任务加入到计算列表里
}else{
calTasks.add(task);
}
}
}
return calTasks;
}
/*
* 计算最早最晚时间
*/
public void calculateTime() {
//计算没有前置任务的任务
Set<Task> firstTimes = calculateNoPreviousEarlyTime(this.tasks);
//依次分层计算后一层的任务EST,EFT
Set<Task> nextTimes = calculateEarlyTime(firstTimes);
Set<Task> tmpTasks;
do{
tmpTasks = nextTimes;
nextTimes = calculateEarlyTime(tmpTasks);
}while(nextTimes.size()>0);
firstTimes.clear();
nextTimes.clear();
tmpTasks.clear();
//计算没有后置任务的任务
firstTimes = calNoNextTasksLateTime(this.tasks);
//依次分层计算后一层的任务的LST
nextTimes = calculateLateTime(firstTimes);
do{
tmpTasks = nextTimes;
nextTimes = calculateLateTime(tmpTasks);
}while(nextTimes.size()>0);
//打印计算结果
for (Task task : this.tasks) {
System.out.println(task.getTaskNumber()+"tnumber=="+task.getEarlyStartTime()+"est==="+task.getEarlyFinishTime()+"eft==="+task.getLateStartTime()+"lst==="+task.getLateFinishTime()+"lft===="+task.isCriticalPath());
}
}
/**
* @param tasks 所有任务
* @return 没有前置任务计算完成之后,待计算的任务
*/
private Set<Task> calculateNoPreviousEarlyTimeArray(List<Task> tasks){
// System.out.println("开始调用calculateNoPreviousEarlyTime(List<Task> tasks)------");
Set<Task> calTasks = new LinkedHashSet<Task>();
if(tasks!=null && tasks.size()>0){
Set<Task> noPreviousTasks = this.getNoPreviousTasks(tasks);
for(Task task : noPreviousTasks){
// System.out.println("没有前置任务的是"+task.getTaskNumber());
if(!task.isCalETArray()){
task.calculateETArray();
System.out.println("计算了第一个"+task.getTaskNumber()+"tnumber=="+task.getEarlyStartTime()+"est==="+task.getEarlyFinishTime()+"eft===");
calTasks.add(task);
}
}
}
// System.out.println("结束调用calculateNoPreviousEarlyTime(List<Task> tasks)------");
return calTasks;
}
/**
* @param nextTasks 本次待计算的任务
* @return 下一次待计算的任务
*/
public Set<Task> calculateEarlyTimeArray(Set<Task> nextTasks){
Set<Task> calTasks = new LinkedHashSet<Task>();
if(nextTasks!=null && nextTasks.size()>0){
Iterator<Task> it = nextTasks.iterator();
while(it.hasNext()){
Task task = it.next();
// System.out.println("本次需要计算的任务是"+task.getTaskNumber());
//找到本任务的前置任务看是不是全部计算完成了,
List<Task> befTask = task.getPreviousTasks();
//判断本任务的前置任务是不是完全计算完成的计数器
int count = 0;//计数器
for(int i=0;i<befTask.size();i++){
Task bfTask = befTask.get(i);
if(bfTask.isCalETArray())
count++;
}
//如果全部计算完成,将本任务的后置任务加入到返回列表里
if(count==befTask.size()){
task.calculateETArray();
// System.out.println("已经计算了"+task.getTaskNumber());
calTasks.addAll(task.getNextTasks());
//如果没有全部计算完成,把本任务加入到计算列表里
}else{
calTasks.add(task);
}
}
}
return calTasks;
}
/**
* @param tasks 所有任务
* @return 没有前置任务的下一层需要计算的任务
*/
public Set<Task> calNoNextTasksLateTimeArray(List<Task> tasks){
Set<Task> calTasks = new LinkedHashSet<Task>();
if(tasks!=null && tasks.size()>0){
for (Task task : this.getNoNextTasks(tasks)) {
if(!task.isCalLTArray())
task.calculateLTArray();
calTasks.add(task);
}
}
return calTasks;
}
/**
* @param nextTasks 本次待计算的任务
* @return 下一次需要计算的任务
*/
public Set<Task> calculateLateTimeArray(Set<Task> nextTasks){
Set<Task> calTasks = new LinkedHashSet<Task>();
if(nextTasks!=null && nextTasks.size()>0){
Iterator<Task> it = nextTasks.iterator();
while(it.hasNext()){
Task task = it.next();
//找到本任务的后置任务看是不是全部计算完成了,
List<Task> nextTask = task.getNextTasks();
//判断本任务的后置任务是不是完全计算完成的计数器
int count = 0;//计数器
for(int i=0;i<nextTask.size();i++){
Task ntTask = nextTask.get(i);
if(ntTask.isCalLTArray())
count++;
}
//如果全部计算完成,将本任务的后置任务加入到返回列表里
if(count==nextTask.size()){
task.calculateLTArray();
// System.out.println("计算的是"+task.getTaskNumber());
calTasks.addAll(task.getPreviousTasks());
//如果没有全部计算完成,把本任务加入到计算列表里
}else{
calTasks.add(task);
}
}
}
return calTasks;
}
/*
* 计算最早最晚时间
*/
public void calculateTimeArray() {
//计算没有前置任务的任务
Set<Task> firstTimes = calculateNoPreviousEarlyTimeArray(this.tasks);
//依次分层计算后一层的任务EST,EFT
Set<Task> nextTimes = calculateEarlyTimeArray(firstTimes);
Set<Task> tmpTasks;
do{
tmpTasks = nextTimes;
nextTimes = calculateEarlyTimeArray(tmpTasks);
}while(nextTimes.size()>0);
firstTimes.clear();
nextTimes.clear();
tmpTasks.clear();
//计算没有后置任务的任务
firstTimes = calNoNextTasksLateTimeArray(this.tasks);
//依次分层计算后一层的任务的LST
nextTimes = calculateLateTimeArray(firstTimes);
do{
tmpTasks = nextTimes;
nextTimes = calculateLateTimeArray(tmpTasks);
}while(nextTimes.size()>0);
//打印计算结果
for (int i =0; i<this.tasks.size();i++) {
Task task = this.tasks.get(i);
System.out.println(task.getTaskNumber()+"tnumber=="+task.getEarlyStartTimeArray()[0]+"est==="+task.getEarlyFinishTimeArray()[0]+"eft==="+task.getLateStartTimeArray()[0]+"lst==="+task.getLateFinishTimeArray()[0]+"lft");
}
}
public List<Task> getTasks() {
return tasks;
}
public void setTasks(List<Task> tasks) {
this.tasks = tasks;
}
public Set<Task> getNoNextTasks() {
return getNoNextTasks(tasks);
}
public Set<Task> getNoPreviousTasks() {
return getNoPreviousTasks(tasks);
}
/*
* tasks 所有任务集合
*/
public Wbs(List<Task> tasks) {
super();
this.tasks = tasks;
this.noNextTasks = new LinkedHashSet<Task>();
this.noPreviousTasks = new LinkedHashSet<Task>();
}
public static void main(String args[]){
// String[] l1 = {"FS"};
// double[] d1 = {15};
// double[] dl1 = {0};
// Task t1 = new Task("1",l1,d1,dl1);
// String[] l2 = {"FS"};
// double[] d2 = {20};
// double[] dl2 = {-5};
// Task t2 = new Task("2",l2,d2,dl2);
// String[] l3 = {"FS"};
// double[] d3 = {26};
// double[] dl3 = {0};
// Task t3 = new Task("3",l3,d3,dl3);
// String[] l4 = {"SS"};
// double[] d4 = {18};
// double[] dl4 = {10};
// Task t4 = new Task("4",l4,d4,dl4);
// String[] l5 = {"FS"};
// double[] d5 = {15};
// double[] dl5 = {0};
// Task t5 = new Task("5",l5,d5,dl5);
// String[] l6 = {"FS"};
// double[] d6 = {38};
// double[] dl6 = {0};
// Task t6 = new Task("6",l6,d6,dl6);
// String[] l7 = {"FS"};
// double[] d7 = {25};
// double[] dl7 = {-5};
// Task t7 = new Task("7",l7,d7,dl7);
// String[] l8 = {"FS"};
// double[] d8 = {15};
// double[] dl8 = {5};
// Task t8 = new Task("8",l8,d8,dl8);
// String[] l9 = {"SS"};
// double[] d9 = {18};
// double[] dl9 = {20};
// Task t9 = new Task("9",l9,d9,dl9);
// String[] l10 = {"FS"};
// double[] d10 = {30};
// double[] dl10 = {0};
// Task t10 = new Task("10",l10,d10,dl10);
// String[] l11 = {"FS"};
// double[] d11 = {28};
// double[] dl11 = {5};
// Task t11 = new Task("11",l11,d11,dl11);
// String[] l12 = {"FS"};
// double[] d12 = {140};
// double[] dl12 = {0};
// Task t12 = new Task("12",l12,d12,dl12);
// String[] l13 = {"FS"};
// double[] d13 = {18};
// double[] dl13 = {-5};
// Task t13 = new Task("13",l13,d13,dl13);
// String[] l14 = {"SS"};
// double[] d14 = {20};
// double[] dl14 = {10};
// Task t14 = new Task("14",l14,d14,dl14);
// String[] l15 = {"FS"};
// double[] d15 = {15};
// double[] dl15 = {0};
// Task t15 = new Task("15",l15,d15,dl15);
// String[] l16 = {"FS"};
// double[] d16 = {33};
// double[] dl16 = {0};
// Task t16 = new Task("16",l16,d16,dl16);
// String[] l17 = {"FS"};
// double[] d17 = {8};
// double[] dl17 = {0};
// Task t17 = new Task("17",l17,d17,dl17);
// String[] l18 = {"FS"};
// double[] d18 = {15};
// double[] dl18 = {0};
// Task t18 = new Task("18",l18,d18,dl18);
// String[] l19 = {"FS"};
// double[] d19 = {17};
// double[] dl19 = {0};
// Task t19 = new Task("19",l19,d19,dl19);
// String[] l20 = {"FS"};
// double[] d20 = {25};
// double[] dl20 = {0};
// Task t20 = new Task("20",l20,d20,dl20);
// Task t1 = new Task("1","FS",15,0);
// Task t2 = new Task("2","FS",20,-5);
// Task t3 = new Task("3","FS",26,0);
// Task t4 = new Task("4","SS",18,10);
// Task t5 = new Task("5","FS",15,0);
// Task t6 = new Task("6","FS",38,0);
// Task t7 = new Task("7","FS",25,-5);
// Task t8 = new Task("8","FS",15,5);
// Task t9 = new Task("9","SS",18,20);
// Task t10 = new Task("10","FS",30,0);
// Task t11 = new Task("11","FS",28,5);
// Task t12 = new Task("12","FS",140,0);
// Task t13 = new Task("13","FS",18,-5);
// Task t14 = new Task("14","SS",20,10);
// Task t15 = new Task("15","FS",15,0);
// Task t16 = new Task("16","FS",33,0);
// Task t17 = new Task("17","FS",8,0);
// Task t18 = new Task("18","FS",15,0);
// Task t19 = new Task("19","FS",17,0);
// Task t20 = new Task("20","FS",25,0);
//
// List<Task> tl1 = new LinkedList<Task>();
// List<Task> tl2 = new LinkedList<Task>();
// List<Task> tl3 = new LinkedList<Task>();
// List<Task> tl4 = new LinkedList<Task>();
// List<Task> tl5 = new LinkedList<Task>();
// List<Task> tl6 = new LinkedList<Task>();
// List<Task> tl7 = new LinkedList<Task>();
// List<Task> tl8 = new LinkedList<Task>();
// List<Task> tl9 = new LinkedList<Task>();
// List<Task> tl10 = new LinkedList<Task>();
// List<Task> tl11 = new LinkedList<Task>();
// List<Task> tl12 = new LinkedList<Task>();
// List<Task> tl13 = new LinkedList<Task>();
// List<Task> tl14 = new LinkedList<Task>();
//
// List<Task> tl = new LinkedList<Task>();
//
// tl1.add(t1);
// tl2.add(t2);
// tl3.add(t4);
// tl4.add(t6);
// tl5.add(t3);
// tl5.add(t5);
// tl6.add(t7);
// tl6.add(t8);
// tl6.add(t9);
// tl7.add(t10);
// tl8.add(t12);
// tl9.add(t13);
// tl10.add(t14);
// tl11.add(t11);
// tl11.add(t15);
// tl12.add(t16);
// tl13.add(t17);
// tl14.add(t18);
// tl14.add(t19);
//
// tl.add(t1);
// tl.add(t2);
// tl.add(t3);
// tl.add(t4);
// tl.add(t5);
// tl.add(t6);
// tl.add(t7);
// tl.add(t8);
// tl.add(t9);
// tl.add(t10);
// tl.add(t11);
// tl.add(t12);
// tl.add(t13);
// tl.add(t14);
// tl.add(t15);
// tl.add(t16);
// tl.add(t17);
// tl.add(t18);
// tl.add(t19);
// tl.add(t20);
//
//
// t2.setPreviousTasks(tl1);
// t3.setPreviousTasks(tl2);
// t4.setPreviousTasks(tl2);
// t5.setPreviousTasks(tl3);
// t6.setPreviousTasks(tl5);
// t7.setPreviousTasks(tl4);
// t8.setPreviousTasks(tl4);
// t9.setPreviousTasks(tl4);
// t10.setPreviousTasks(tl6);
// t11.setPreviousTasks(tl7);
//
// t13.setPreviousTasks(tl8);
// t14.setPreviousTasks(tl9);
// t15.setPreviousTasks(tl10);
// t16.setPreviousTasks(tl11);
// t17.setPreviousTasks(tl12);
// t18.setPreviousTasks(tl13);
// t19.setPreviousTasks(tl13);
// t20.setPreviousTasks(tl14);
// Wbs wbs = new Wbs(tl);
// Set<Task> task = wbs.getNoPreviousTasks();
// for (Task task2 : task) {
// System.out.println("taskNumber=nb="+task2.getTaskNumber());
// }
// Set<Task> taskt = wbs.getNoNextTasks();
// for (Task task2 : taskt) {
// System.out.println("taskNumber=na="+task2.getTaskNumber());
// }
// wbs.calculateTime();
// wbs.calculateTimeArray();
// long time1 = System.currentTimeMillis();
// Task previous = new Task("1","FS",15,0);
// List<Task> tls = new LinkedList<Task>();
// tls.add(previous);
// List<Task> tl = new LinkedList<Task>();
// tl.add(previous);
// for(int i = 2;i<=2000;i++){
// Task tmp = new Task(String.valueOf(i),"FS",15,0);
// tmp.setPreviousTasks(tls);
// tls = new LinkedList<Task>();
// tls.add(tmp);
// tl.add(tmp);
// }
// long time2 = System.currentTimeMillis();
// System.out.println("构建用时:"+(time2-time1));
// Wbs wbs = new Wbs(tl);
// wbs.calculateTime();
// long time3 = System.currentTimeMillis();
// System.out.println("计算用时:"+(time3-time2));
//数组的计算
long time1 = System.currentTimeMillis();
int arrayLength = 200;
String[] logicarray = new String[arrayLength];
double[] delaytimearray = new double[arrayLength];
double[] durtimearray = new double[arrayLength];
Random random = new Random();
for(int i = 0; i < arrayLength;i++) {
//获得200以内的正整数为执行时间数组赋值
durtimearray[i] =Math.abs(random.nextInt())%200;
//获得20以内的整数为浮动时间赋值
delaytimearray[i] =Math.abs(random.nextInt()%20);
//获得4以内的整数为4种逻辑关系赋值
int index = Math.abs(random.nextInt())%4;
switch (index) {
case 1:
logicarray[i]="SS";
break;
case 2:
logicarray[i]="FF";
break;
case 3:
logicarray[i]="SF";
break;
default:
logicarray[i]="FS";
break;
}
}
Task previous = new Task("task1",logicarray,delaytimearray,durtimearray);
List<Task> tls = new LinkedList<Task>();
tls.add(previous);
List<Task> tl = new LinkedList<Task>();
tl.add(previous);
for(int i = 2;i<=5000;i++){
String[] logicarrayi = new String[arrayLength];
double[] delaytimearrayi = new double[arrayLength];
double[] durtimearrayi = new double[arrayLength];
Random randomi = new Random();
for(int ii = 0; ii < arrayLength;ii++) {
//获得200以内的正整数为执行时间数组赋值
durtimearrayi[ii] =Math.abs(randomi.nextInt())%200;
//获得20以内的整数为浮动时间赋值
delaytimearrayi[ii] =Math.abs(randomi.nextInt()%20);
//获得4以内的整数为4种逻辑关系赋值
int index = Math.abs(randomi.nextInt())%4;
switch (index) {
case 1:
logicarrayi[ii]="SS";
break;
case 2:
logicarrayi[ii]="FF";
break;
case 3:
logicarrayi[ii]="SF";
break;
default:
logicarrayi[ii]="FS";
break;
}
}
Task tmp = new Task("task"+i,logicarrayi,delaytimearrayi,durtimearrayi);
tmp.setPreviousTasks(tls);
tls = new LinkedList<Task>();
int previousCount = Math.abs(randomi.nextInt())%8;
for(int ii = 0; ii < previousCount;ii++) {
if(ii<tl.size()){
tls.add(tl.get(ii));
}
}
tl.add(tmp);
}
long time2 = System.currentTimeMillis();
System.out.println("构建用时:"+(time2-time1));
Wbs wbs = new Wbs(tl);
wbs.calculateTimeArray();
long time3 = System.currentTimeMillis();
System.out.println("计算用时:"+(time3-time2));
}
}