如何分析和发现活动网络中的所有可能路径

时间:2016-11-22 20:32:28

标签: java algorithm graph nodes

,我一直在开发这种用于研究的“项目管理工具”,它应该计算任务持续时间和成本,以确定任何给定项目的关键路径,例如:

en example of a project and tasks relations

**直到现在我计算了所有持续时间并开始和结束但我仍然坚持如何发现这样一个图中的所有可能路径以及如何从初始节点到最终节点遍历这个结构并确定路径将持续时间最长,我不知道如何继续,所以提前感谢帮助我**

我实现了一个Task Class,如下所示:

public class Task {

    private String name;
    private int duration;
    private int earlyStart;
    private int earlyFinish;
    private int lateStart;
    private int lateFinish;
    private int totalFloat;
    private HashSet<Task> predecessors;
    private HashSet<Task> successors;
    private String[] dependencies;

    public Task(String taskName, int taskDuration, String[] dependencies) {
        // Initialize Attributes
        this.name = taskName;
        this.duration = taskDuration;
        this.dependencies = dependencies;
        this.predecessors = new HashSet<Task>();
        this.successors = new HashSet<Task>();
    }
}

Ps:我没有包含getter和setter

我还有一个名为project的类,如下所示:

public class Project {

private HashSet<Task> tasks;
private HashSet<Task> initialTasks;
private HashSet<Task> finalTasks;
private int maxDuration;

public Project() {
    this.tasks = new HashSet<Task>();
}

public void initialize(){

    this.calculateTasksRelation();
    this.calculateInitialTasks();
    this.calculateInitialTasksEarlies();
    this.forwardPass();

    this.calculateFinalTasks();
    this.calculateMaxDuration();
    this.calculateFinalTasksLates();
    this.backwardPass();

}




public void addTask(Task task) {
    this.tasks.add(task);
}

public Task getTaskByName(String taskName) {
    for (Task task : tasks) {
        if(task.getName().equals(taskName)){
            return task;
        }
    }
    return null;
}

public HashSet<Task> getAllTasks() {
    return tasks;
}

/**
 * Private Methods internal Usage Only
 * */
private void calculateTasksRelation() {
    for (Task current : tasks) {
        if ( current.getDependencies() != null ) {
            for (String string : current.getDependencies() ) {
                if (this.getTaskByName(string) != null) {
                    Task dependencie = this.getTaskByName(string);
                    current.addPredecessor(dependencie);
                    dependencie.addSuccessor(current);
                }
            }
        }
    }
}

// Return only the tasks that dosn't have predecessors
private void calculateInitialTasks(){
    HashSet<Task> remaining = new HashSet<Task>(this.tasks);
    // itertare over the remaining and remove all tasks 
    // that are successors = they have predecessor
    for (Task current : tasks) {
        for (Task successor : current.getSuccessors()) {
            remaining.remove(successor);
        }
    }
    this.initialTasks = new HashSet<>(remaining);
}

private void calculateInitialTasksEarlies() {
    for (Task initialTask : this.initialTasks) {
        initialTask.setEarlyStart(0);
        initialTask.setEarlyFinish(initialTask.getEarlyStart() + initialTask.getDuration());
    }
}

private void calculateMaxDuration() {

    for (Task task : finalTasks) {
        if(task.getEarlyFinish() > this.maxDuration) {
            this.maxDuration = task.getEarlyFinish();
        }
    }
}

// Return only the tasks that dosn't have any successors
private void calculateFinalTasks() {
    HashSet<Task> remaining = new HashSet<Task>(this.tasks);
    // itertare over the remaining and remove all tasks 
    // that are predecessors = they have successor
    for (Task current : tasks) {
        for (Task predecessor : current.getPredecessors()) {
            remaining.remove(predecessor);
        }
    }
    this.finalTasks = new HashSet<>(remaining);
}

private void calculateFinalTasksLates() {
    for (Task endTask : this.finalTasks) {
        endTask.setLateFinish(this.maxDuration);
        endTask.setLateStart(endTask.getLateFinish() - this.maxDuration);
    }
}

private void forwardPass() {
    // tasks whose early starts has been calculated
    HashSet<Task> completed = new HashSet<Task>(initialTasks);
    // tasks whose early starts has not been calculated yet
    HashSet<Task> remaining = new HashSet<Task>(tasks);
    remaining.removeAll(initialTasks);

    // Backflow algorithm
    // while there are tasks whose early start isn't calculated.
    while (!remaining.isEmpty()) {
        boolean progress = false;
        for (Task currentTask : this.tasks) {
            if(completed.containsAll(currentTask.getPredecessors())){
                int temp = 0 ;
                for ( Task dependencie : currentTask.getPredecessors() ) {
                    if( dependencie.getEarlyFinish() > temp ){
                        // update the temp variable
                        temp = dependencie.getEarlyFinish();
                    }
                }
                currentTask.setEarlyStart(temp);
                currentTask.setEarlyFinish(currentTask.getEarlyStart() + currentTask.getDuration());
                // set the task as completed and remove it from the remaining
                completed.add(currentTask);
                remaining.remove(currentTask);
                // note that we are making a 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!");
    }
}

private void backwardPass() {
    // tasks whose early starts has been calculated
    HashSet<Task> completed = new HashSet<Task>(this.finalTasks);
    // tasks whose early starts has not been calculated yet
    HashSet<Task> remaining = new HashSet<Task>(tasks);
    remaining.removeAll(finalTasks);

    // Backflow algorithm
    // while there are tasks whose early start isn't calculated.
    while (!remaining.isEmpty()) {
        boolean progress = false;
        for (Task currentTask : this.tasks) {
            if(completed.containsAll(currentTask.getSuccessors())){
                int temp = this.maxDuration;
                for ( Task successor : currentTask.getSuccessors() ) {
                    if( successor.getLateStart() < temp ){
                        // update the temp variable
                        temp = successor.getLateStart();
                    }
                }
                currentTask.setLateFinish(temp);
                currentTask.setLateStart(currentTask.getLateFinish() - currentTask.getDuration());
                // set the task as completed and remove it from the remaining
                completed.add(currentTask);
                remaining.remove(currentTask);
                // note that we are making a 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!");
    }
}
}

Ps:对不起长代码:)

1 个答案:

答案 0 :(得分:0)

找到从一个源节点到另一个源节点的最长路径是一般形式的NP难问题,因此没有多项式解决方案。 与此相反,使用Dijkstra或Bellman-Ford算法可以轻松找到最短路径。 我不是专家,但我真的建议重新考虑你能做什么以及你在练习中不能做什么。