过程分配的遗传算法

时间:2016-04-28 18:58:10

标签: java algorithm genetic-algorithm genetic-programming genetic

我有以下单一的任务令我感到困惑。我必须实现一个将进程分配到处理器的遗传算法。更具体地说,问题如下:

“你有一个在并行处理器系统中计算的程序。该程序由需要在多个处理器上分配的N个进程组成(其中n小于N)。整个过程中的过程可能非常耗时,因此最佳做法是将需要相互通信的过程分配给同一个处理器。

为了减少进程之间的通信时间,您可以将这些进程分配给同一个处理器,但这会否定每个处理器需要为整个进程做出贡献的并行处理理念。

考虑以下事项:假设Cij是进程i和进程j之间的通信总量。假设每个进程需要相同数量的计算能力,以便可以通过向处理器分配相同数量的进程来处理处理过程的限制。使用遗传算法将N个进程分配给n个处理器。“

以上大致翻译了问题的描述。现在我有以下问题困扰我。

1)为了使遗传算法运行,最好的可行解决方案是什么。我有他们背后的理论,我推断出你需要一个最好的解决方案来检查每一代人口。

2)如何正确设计整个问题以便由程序处理。

我计划在Java中实现这一点,但欢迎使用其他编程语言的任何其他建议。

1 个答案:

答案 0 :(得分:0)

老兄住了。或者El Duderino如果你没有进入整个简洁的事情。 您所问的实际上是一个两部分问题,但遗传算法部分可以在概念中轻松说明。我发现给一个基本的开始可能会有所帮助,但这个问题作为一个“整体”在这里解决的问题太复杂了。

正如您所注意到的,

遗传算法(GA)可以用作优化器。为了将GA应用于流程执行计划,您需要能够对执行计划进行评分,然后克隆并改变最佳计划。 GA通过运行多个计划,克隆最好的计划,然后改变其中一些轻微来查看后代(克隆)计划是否得到改善或恶化。

在这个例子中,我创建了一个包含100个随机整数的数组。每个Integer都是一个要运行的“进程”,Integer的值是运行该单个进程的“成本”。

List<Integer> processes = new ArrayList<Integer>();

然后将这些流程添加到ExecutionPlan,即List<List<Integer>>。这个整数列表将用于代表4个处理器进行25轮处理:

class ExecutionPlan implements Comparable<ExecutionPlan> {
    List<List<Integer>> plan;
    int cost;

执行计划的总cost将通过获取每轮最高流程成本(最大整数)并汇总所有轮次的成本来计算。因此,优化器的目标是在4个“处理器”上将最初的100个整数(进程)分配到25轮“处理”中,以使总成本尽可能低。

// make 10 execution plans of 25 execution rounds running on 4 processors;        
List<ExecutionPlan> executionPlans = createAndIntializePlans(processes);
// Loop on generationCount
for ( int generation = 0; generation < GENERATIONCOUNT; ++generation) {
    computeCostOfPlans(executionPlans);
    // sort plans by cost
    Collections.sort(executionPlans);
    // print execution plan costs
    System.out.println(generation + " = " + executionPlans);
    // clone 5 better plans over 5 worse plans 
    // i.e., kill off the least fit and reproduce the best fit.
    cloneBetterPlansOverWorsePlans(executionPlans);
    // mutate 5 cloned plans
    mutateClones(executionPlans);
}

当程序运行时,成本最初是随机确定的,但随着每一代的改进。如果你运行1000代并绘制结果,典型的运行将如下所示:

Best Cost Each Generation

GA的目的是Optimize或尝试确定最佳解决方案。它可以应用于您的问题的原因是您的ExecutionPlan可以被评分,克隆和变异。因此,成功的道路是将思想问题分开。首先,弄清楚如何制定一个执行计划,可以对在假定的硬件集上实际运行它的成本进行评分。添加rountines以克隆和变异ExecutionPlan。一旦你将它插入这个GA示例。祝你好运,保持冷静。

public class Optimize {
    private static int GENERATIONCOUNT = 1000;
    private static int PROCESSCOUNT = 100;
    private static int MUTATIONCOUNT = PROCESSCOUNT/10;
    public static void main(String...strings) {
        new Optimize().run();
    }
    // define an execution plan as 25 runs on 4 processors
    class ExecutionPlan implements Comparable<ExecutionPlan> {
        List<List<Integer>> plan;
        int cost;
        public ExecutionPlan(List<List<Integer>> plan) {
            this.plan = plan;
        }
        @Override
        public int compareTo(ExecutionPlan o) {
            return cost-o.cost;
        }
        @Override
        public String toString() {
            return Integer.toString(cost);
        }
    }
    private void run() {
        // make 100 processes to be completed
        List<Integer> processes = new ArrayList<Integer>();
        // assign them a random cost between 1 and 100;
        for ( int index = 0; index < PROCESSCOUNT; ++index) {
            processes.add( new Integer((int)(Math.random() * 99.0)+1));
        }
        // make 10 execution plans of 25 execution rounds running on 4 processors;        
        List<ExecutionPlan> executionPlans = createAndIntializePlans(processes);
        // Loop on generationCount
        for ( int generation = 0; generation < GENERATIONCOUNT; ++generation) {
            computeCostOfPlans(executionPlans);
            // sort plans by cost
            Collections.sort(executionPlans);
            // print execution plan costs
            System.out.println(generation + " = " + executionPlans);
            // clone 5 better plans over 5 worse plans 
            cloneBetterPlansOverWorsePlans(executionPlans);
            // mutate 5 cloned plans
            mutateClones(executionPlans);
        }
    }
    private void mutateClones(List<ExecutionPlan> executionPlans) {
        for ( int index = 0; index < executionPlans.size()/2; ++index) {
            ExecutionPlan execution = executionPlans.get(index);
            // mutate 10 different location swaps, maybe the plan improves
            for ( int mutationCount = 0; mutationCount < MUTATIONCOUNT ; ++mutationCount) {
                int location1 = (int)(Math.random() * 100.0);
                int location2 = (int)(Math.random() * 100.0);
                // swap two locations
                Integer processCostTemp = execution.plan.get(location1/4).get(location1%4);
                execution.plan.get(location1/4).set(location1%4, execution.plan.get(location2/4).get(location2%4));
                execution.plan.get(location2/4).set(location2%4, processCostTemp); 
            }
        }

    }
    private void cloneBetterPlansOverWorsePlans(List<ExecutionPlan> executionPlans) {
        for ( int index = 0; index < executionPlans.size()/2; ++index) {
            ExecutionPlan execution = executionPlans.get(index);
            List<List<Integer>> clonePlan = new ArrayList<List<Integer>>();
            for ( int roundNumber = 0; roundNumber < 25; ++roundNumber) {
                clonePlan.add( new ArrayList<Integer>(execution.plan.get(roundNumber)) );
            }
            executionPlans.set( index + executionPlans.size()/2, new ExecutionPlan(clonePlan) );
        }        
    }
    private void computeCostOfPlans(List<ExecutionPlan> executionPlans) {
        for ( ExecutionPlan execution: executionPlans) {
            execution.cost = 0;
            for ( int roundNumber = 0; roundNumber < 25; ++roundNumber) {
                // cost of a round is greatest "communication time".
                List<Integer> round = execution.plan.get(roundNumber);
                int roundCost = round.get(0)>round.get(1)?round.get(0):round.get(1);
                roundCost = execution.cost>round.get(2)?roundCost:round.get(2);
                roundCost = execution.cost>round.get(3)?roundCost:round.get(3);
                // add all the round costs' to determine total plan cost
                execution.cost += roundCost;
            }
        }        
    }
    private List<ExecutionPlan> createAndIntializePlans(List<Integer> processes) {
        List<ExecutionPlan> executionPlans = new ArrayList<ExecutionPlan>();
        for ( int planNumber = 0; planNumber < 10; ++planNumber) {
            // randomize the processes for this plan
            Collections.shuffle(processes);
            // and make the plan 
            List<List<Integer>> currentPlan = new ArrayList<List<Integer>>();
            for ( int roundNumber = 0; roundNumber < 25; ++roundNumber) {
                List<Integer> round = new ArrayList<Integer>(); 
                round.add(processes.get(4*roundNumber+0));
                round.add(processes.get(4*roundNumber+1));
                round.add(processes.get(4*roundNumber+2));
                round.add(processes.get(4*roundNumber+3));
                currentPlan.add(round);
            }
            executionPlans.add(new ExecutionPlan(currentPlan));
        }
        return executionPlans;
    }
}