Java 关键路径法

Java 关键路径法,java,algorithm,Java,Algorithm,在哪里可以找到关键路径方法算法的Java实现?我确信在云中有一些实现。显然,我已经在谷歌上搜索过了,但还没有找到任何运行良好的实现。这就是我问的原因 提前谢谢。网站上有一个Java小程序。还有一个 工具书类 以下是基于上提供的解释的算法实现 有一个包装器类来保存任务、成本和关键路径成本。它首先将关键成本计算为所有依赖项的最大关键成本加上自身成本。然后,一旦关键成本可用,它将使用一个比较器根据关键成本对任务进行排序,并将依赖性作为一个平衡破坏者(如果没有依赖性,则随机选择)。请注意,如果存在一

在哪里可以找到关键路径方法算法的Java实现?我确信在云中有一些实现。显然,我已经在谷歌上搜索过了,但还没有找到任何运行良好的实现。这就是我问的原因

提前谢谢。

网站上有一个Java小程序。还有一个

工具书类

以下是基于上提供的解释的算法实现 有一个包装器类来保存任务、成本和关键路径成本。它首先将关键成本计算为所有依赖项的最大关键成本加上自身成本。然后,一旦关键成本可用,它将使用一个比较器根据关键成本对任务进行排序,并将依赖性作为一个平衡破坏者(如果没有依赖性,则随机选择)。请注意,如果存在一个周期,将抛出一个异常,如果任何成本为负,则该异常将失败

以下是实施方案:

public class CriticalPath {

  public static void main(String[] args) {
    //The example dependency graph from
    //http://www.ctl.ua.edu/math103/scheduling/scheduling_algorithms.htm
    HashSet<Task> allTasks = new HashSet<Task>();
    Task end = new Task("End", 0);
    Task F = new Task("F", 2, end);
    Task A = new Task("A", 3, end);
    Task X = new Task("X", 4, F, A);
    Task Q = new Task("Q", 2, A, X);
    Task start = new Task("Start", 0, Q);
    allTasks.add(end);
    allTasks.add(F);
    allTasks.add(A);
    allTasks.add(X);
    allTasks.add(Q);
    allTasks.add(start);
    System.out.println("Critical Path: "+Arrays.toString(criticalPath(allTasks)));
  }

  //A wrapper class to hold the tasks during the calculation
  public static class Task{
    //the actual cost of the task
    public int cost;
    //the cost of the task along the critical path
    public int criticalCost;
    //a name for the task for printing
    public String name;
    //the tasks on which this task is dependant
    public HashSet<Task> dependencies = new HashSet<Task>();
    public Task(String name, int cost, Task... dependencies) {
      this.name = name;
      this.cost = cost;
      for(Task t : dependencies){
        this.dependencies.add(t);
      }
    }
    @Override
    public String toString() {
      return name+": "+criticalCost;
    }
    public boolean isDependent(Task t){
      //is t a direct dependency?
      if(dependencies.contains(t)){
        return true;
      }
      //is t an indirect dependency
      for(Task dep : dependencies){
        if(dep.isDependent(t)){
          return true;
        }
      }
      return false;
    }
  }

  public static Task[] criticalPath(Set<Task> tasks){
    //tasks whose critical cost has been calculated
    HashSet<Task> completed = new HashSet<Task>();
    //tasks whose ciritcal cost needs to be calculated
    HashSet<Task> remaining = new HashSet<Task>(tasks);

    //Backflow algorithm
    //while there are tasks whose critical cost isn't calculated.
    while(!remaining.isEmpty()){
      boolean progress = false;

      //find a new task to calculate
      for(Iterator<Task> it = remaining.iterator();it.hasNext();){
        Task task = it.next();
        if(completed.containsAll(task.dependencies)){
          //all dependencies calculated, critical cost is max dependency
          //critical cost, plus our cost
          int critical = 0;
          for(Task t : task.dependencies){
            if(t.criticalCost > critical){
              critical = t.criticalCost;
            }
          }
          task.criticalCost = critical+task.cost;
          //set task as calculated an remove
          completed.add(task);
          it.remove();
          //note we are making progress
          progress = true;
        }
      }
      //If we haven't made any progress then a cycle must exist in
      //the graph and we wont be able to calculate the critical path
      if(!progress) throw new RuntimeException("Cyclic dependency, algorithm stopped!");
    }

    //get the tasks
    Task[] ret = completed.toArray(new Task[0]);
    //create a priority list
    Arrays.sort(ret, new Comparator<Task>() {

      @Override
      public int compare(Task o1, Task o2) {
        //sort by cost
        int i= o2.criticalCost-o1.criticalCost;
        if(i != 0)return i;

        //using dependency as a tie breaker
        //note if a is dependent on b then
        //critical cost a must be >= critical cost of b
        if(o1.isDependent(o2))return -1;
        if(o2.isDependent(o1))return 1;
        return 0;
      }
    });

    return ret;
  }
}
公共类关键路径{
公共静态void main(字符串[]args){
//中的依赖关系图示例
//http://www.ctl.ua.edu/math103/scheduling/scheduling_algorithms.htm
HashSet allTasks=新HashSet();
任务结束=新任务(“结束”,0);
任务F=新任务(“F”,2,结束);
任务A=新任务(“A”,3,结束);
任务X=新任务(“X”,4,F,A);
任务Q=新任务(“Q”,2,A,X);
任务开始=新任务(“开始”,0,Q);
所有任务。添加(结束);
所有任务。添加(F);
所有任务。添加(A);
所有任务。添加(X);
所有任务。添加(Q);
所有任务。添加(开始);
System.out.println(“关键路径:+Arrays.toString(关键路径(所有任务)));
}
//用于在计算期间保存任务的包装器类
公共静态类任务{
//任务的实际成本
公共成本;
//沿关键路径的任务成本
公共关键成本;
//用于打印的任务的名称
公共字符串名称;
//此任务所依赖的任务
public HashSet dependencies=新HashSet();
公共任务(字符串名称、整数成本、任务…依赖项){
this.name=名称;
成本=成本;
for(任务t:依赖项){
这个.dependencies.add(t);
}
}
@凌驾
公共字符串toString(){
返回名称+“:”+关键成本;
}
公共布尔值是独立的(任务t){
//这不是直接依赖关系吗?
if(dependencies.contains(t)){
返回true;
}
//这不是一种间接依赖
对于(任务部门:依赖项){
if(副独立性(t)){
返回true;
}
}
返回false;
}
}
公共静态任务[]关键路径(设置任务){
//已计算关键成本的任务
HashSet completed=新的HashSet();
//需要计算其电路成本的任务
HashSet剩余=新的HashSet(任务);
//回流算法
//而有些任务的关键成本没有计算出来。
而(!remaining.isEmpty()){
布尔进程=false;
//查找要计算的新任务
for(Iterator it=remaining.Iterator();it.hasNext();){
Task=it.next();
if(completed.containsAll(task.dependencies)){
//计算所有依赖项,关键成本为最大依赖项
//关键成本加上我们的成本
int临界=0;
for(任务t:Task.dependencies){
如果(t.临界成本>临界成本){
临界=t.临界成本;
}
}
task.criticalCost=关键+task.cost;
//将任务设置为已计算的删除
完成。添加(任务);
it.remove();
//请注意,我们正在取得进展
进步=正确;
}
}
//如果我们没有取得任何进展,那么必然存在一个循环
//我们无法计算出关键路径
如果(!progress)抛出新的RuntimeException(“循环依赖项,算法已停止!”);
}
//获得任务
任务[]ret=已完成。toArray(新任务[0]);
//创建优先级列表
sort(ret,newcomparator(){
@凌驾
公共整数比较(任务o1、任务o2){
//按成本排序
int i=o2.临界成本-o1.临界成本;
如果(i!=0)返回i;
//使用依赖关系作为联系断路器
//注:如果a依赖于b,则
//关键成本a必须大于等于b的关键成本
if(o1.isDependent(o2))返回-1;
如果(o2.isDependent(o1))返回1;
返回0;
}
});
返回ret;
}
}

以下是Jessup代码的另一个版本。我只是添加了一些其他函数,现在代码计算最早/最晚的开始和完成时间、松弛时间以及节点是否在关键路径上。(我只是简单地添加了函数并得到了结果,我没有在算法和编码上花费太多精力)

公共类关键路径{
公共静态成本;
公共静态字符串格式=“%1$-10s%2$-5s%3$-5s%4$-5s%5$-5s%6$-5s%7$-10s\n”;
公共静态void main(字符串[]args){
//依赖关系图示例
HashSet allTasks=新HashSet();
任务结束=新任务(“结束”,0);
任务F=新任务(“F”,2,结束);
任务A=新任务(“A”,3,结束);
任务X=新任务(“X”,4,F,A);
任务Q=新任务(“Q”,2,A,X);
任务开始=新任务(“开始”,0,Q);
所有任务。添加(结束);
所有任务。添加(F);
所有任务。添加(A);
所有任务。添加(X);
所有任务。添加(Q);
所有任务。添加(开始);
任务[]结果=关键路径(所有任务);
打印(结果);
//System.out.println(“关键路径:+Arrays.toString(结果));
}
//用于在计算期间保存任务的包装器类
公共静态类任务{
//任务的实际成本
公共成本;
//沿关键路径的任务成本
公共关键成本;
//th的名字
public class CriticalPath {
    public static int maxCost;
    public static String format = "%1$-10s %2$-5s %3$-5s %4$-5s %5$-5s %6$-5s %7$-10s\n";

    public static void main(String[] args) {
        // The example dependency graph
        HashSet<Task> allTasks = new HashSet<Task>();
        Task end = new Task("End", 0);
        Task F = new Task("F", 2, end);
        Task A = new Task("A", 3, end);
        Task X = new Task("X", 4, F, A);
        Task Q = new Task("Q", 2, A, X);
        Task start = new Task("Start", 0, Q);
        allTasks.add(end);
        allTasks.add(F);
        allTasks.add(A);
        allTasks.add(X);
        allTasks.add(Q);
        allTasks.add(start);
        Task[] result = criticalPath(allTasks);
        print(result);
        // System.out.println("Critical Path: " + Arrays.toString(result));
    }

    // A wrapper class to hold the tasks during the calculation
    public static class Task {
        // the actual cost of the task
        public int cost;
        // the cost of the task along the critical path
        public int criticalCost;
        // a name for the task for printing
        public String name;
        // the earliest start
        public int earlyStart;
        // the earliest finish
        public int earlyFinish;
        // the latest start
        public int latestStart;
        // the latest finish
        public int latestFinish;
        // the tasks on which this task is dependant
        public HashSet<Task> dependencies = new HashSet<Task>();

        public Task(String name, int cost, Task... dependencies) {
            this.name = name;
            this.cost = cost;
            for (Task t : dependencies) {
                this.dependencies.add(t);
            }
            this.earlyFinish = -1;
        }

        public void setLatest() {
            latestStart = maxCost - criticalCost;
            latestFinish = latestStart + cost;
        }

        public String[] toStringArray() {
            String criticalCond = earlyStart == latestStart ? "Yes" : "No";
            String[] toString = { name, earlyStart + "", earlyFinish + "", latestStart + "", latestFinish + "",
                    latestStart - earlyStart + "", criticalCond };
            return toString;
        }

        public boolean isDependent(Task t) {
            // is t a direct dependency?
            if (dependencies.contains(t)) {
                return true;
            }
            // is t an indirect dependency
            for (Task dep : dependencies) {
                if (dep.isDependent(t)) {
                    return true;
                }
            }
            return false;
        }
    }

    public static Task[] criticalPath(Set<Task> tasks) {
        // tasks whose critical cost has been calculated
        HashSet<Task> completed = new HashSet<Task>();
        // tasks whose critical cost needs to be calculated
        HashSet<Task> remaining = new HashSet<Task>(tasks);

        // Backflow algorithm
        // while there are tasks whose critical cost isn't calculated.
        while (!remaining.isEmpty()) {
            boolean progress = false;

            // find a new task to calculate
            for (Iterator<Task> it = remaining.iterator(); it.hasNext();) {
                Task task = it.next();
                if (completed.containsAll(task.dependencies)) {
                    // all dependencies calculated, critical cost is max
                    // dependency
                    // critical cost, plus our cost
                    int critical = 0;
                    for (Task t : task.dependencies) {
                        if (t.criticalCost > critical) {
                            critical = t.criticalCost;
                        }
                    }
                    task.criticalCost = critical + task.cost;
                    // set task as calculated an remove
                    completed.add(task);
                    it.remove();
                    // note we are making progress
                    progress = true;
                }
            }
            // If we haven't made any progress then a cycle must exist in
            // the graph and we wont be able to calculate the critical path
            if (!progress)
                throw new RuntimeException("Cyclic dependency, algorithm stopped!");
        }

        // get the cost
        maxCost(tasks);
        HashSet<Task> initialNodes = initials(tasks);
        calculateEarly(initialNodes);

        // get the tasks
        Task[] ret = completed.toArray(new Task[0]);
        // create a priority list
        Arrays.sort(ret, new Comparator<Task>() {

            @Override
            public int compare(Task o1, Task o2) {
                return o1.name.compareTo(o2.name);
            }
        });

        return ret;
    }

    public static void calculateEarly(HashSet<Task> initials) {
        for (Task initial : initials) {
            initial.earlyStart = 0;
            initial.earlyFinish = initial.cost;
            setEarly(initial);
        }
    }

    public static void setEarly(Task initial) {
        int completionTime = initial.earlyFinish;
        for (Task t : initial.dependencies) {
            if (completionTime >= t.earlyStart) {
                t.earlyStart = completionTime;
                t.earlyFinish = completionTime + t.cost;
            }
            setEarly(t);
        }
    }

    public static HashSet<Task> initials(Set<Task> tasks) {
        HashSet<Task> remaining = new HashSet<Task>(tasks);
        for (Task t : tasks) {
            for (Task td : t.dependencies) {
                remaining.remove(td);
            }
        }

        System.out.print("Initial nodes: ");
        for (Task t : remaining)
            System.out.print(t.name + " ");
        System.out.print("\n\n");
        return remaining;
    }

    public static void maxCost(Set<Task> tasks) {
        int max = -1;
        for (Task t : tasks) {
            if (t.criticalCost > max)
                max = t.criticalCost;
        }
        maxCost = max;
        System.out.println("Critical path length (cost): " + maxCost);
        for (Task t : tasks) {
            t.setLatest();
        }
    }

    public static void print(Task[] tasks) {
        System.out.format(format, "Task", "ES", "EF", "LS", "LF", "Slack", "Critical?");
        for (Task t : tasks)
            System.out.format(format, (Object[]) t.toStringArray());
    }
}