Choco求解器中的资源分配

时间:2018-09-07 06:12:17

标签: java choco

我正在使用choco解决虚拟机分配问题,这就是我正在尝试做的事情:

假设我们有3个阵列用于物理机属性(PMcpuPMramPMbw)和3个阵列用于虚拟机(VMcpu,{{1} },VMram)。现在,我们定义一个具有以下尺寸的矩阵:VMbw,以便choco设置值(0或1表示将特定VM分配给PM或不分配给PM)。基于常识,我们知道PM资源应完全等于或等于所有分配的VM资源的数量,因此,为此,我们将分配矩阵中的每个元素与资源相应地相乘,例如:

PM*VM

Allocation_matrix:

PMcpu = {8000, 7000, 3000};
PMram = {7000, 4000, 5000};
PMbw = {2000, 500, 7000};
VMcpu = {2000, 3000, 1000};
VMram = {1000, 2000, 3000};
VMbw = {100, 2000, 500};

行表示PM,列表示VM,因此:

0 1 0
1 0 0
0 0 1

所以我写了这段代码:

VM2 -> PM1
VM1 -> PM2
VM3 -> PM3

我试图通过检查要填充在行 Model model = new Model("Resource Allocation Problem"); int[] VMcpu = new int[number_of_vms]; int[] VMram = new int[number_of_vms]; int[] VMbw = new int[number_of_vms]; // some initialization here int[] PMcpu = new int[number_of_pms]; int[] PMram = new int[number_of_pms]; int[] PMbw = new int[number_of_pms]; // some initialization here IntVar[][] alloc_matrix = model.intVarMatrix("alloc_matrix", number_of_pms, number_of_vms, new int[] {0,1}); // ensuring all columns have only one 1 in them ArrayList<IntVar> sum_of_col = new ArrayList<>(); for(int j=0; j<number_of_vms; j++) { int count = 0; for(int i=0; i<number_of_pms; i++) { count += alloc_matrix[i][j].getValue(); } IntVar tempInt = model.intVar(count); sum_of_col.add(tempInt); } for(int i=0; i<sum_of_col.size(); i++) { model.arithm(sum_of_col.get(i), "=", 1).post(); } // ensuring that PMs can host that much VM (based on their resources) for (int i=0; i<number_of_pms; i++) { ArrayList<IntVar> pm_total_cpu = new ArrayList<>(); ArrayList<IntVar> pm_total_ram = new ArrayList<>(); ArrayList<IntVar> pm_total_bw = new ArrayList<>(); for (int j=0; j<number_of_vms; j++) { IntVar temp_cpu = model.intVar(alloc_matrix[i][j].getValue() * VMcpu[j]); IntVar temp_ram = model.intVar(alloc_matrix[i][j].getValue() * VMram[j]); IntVar temp_bw = model.intVar(alloc_matrix[i][j].getValue() * VMbw[j]); pm_total_cpu.add(temp_cpu); pm_total_ram.add(temp_ram); pm_total_bw.add(temp_bw); } model.sum(ArrayUtils.toArray(pm_total_cpu), "<", PMcpu[i]).post(); model.sum(ArrayUtils.toArray(pm_total_ram), "<", PMram[i]).post(); model.sum(ArrayUtils.toArray(pm_total_bw), "<", PMbw[i]).post(); } // getting the number of active PMs (those that have at least one 1 in their row) ArrayList<IntVar> pm_hostings = new ArrayList<>(); for (int i=0; i<number_of_pms; i++) { ArrayList<IntVar> row = new ArrayList<>(); for (int j=0; j<number_of_vms; j++) { IntVar temp_int_var = model.intVar(alloc_matrix[i][j].getValue()); row.add(temp_int_var); } int has_one = 0; for(int iterator=0; iterator<row.size(); iterator++) { if (row.get(iterator).getValue() == 1) { has_one = 1; break; } } IntVar temp = model.intVar(has_one); pm_hostings.add(temp); } // sum will be the number of active PMs int sum = 0; for (int i=0; i<pm_hostings.size(); i++) { sum += pm_hostings.get(i).getValue(); } // setting objective to minimize that number of active PMs IntVar answer = model.intVar(sum); model.setObjective(Model.MINIMIZE, answer); while(model.getSolver().solve()) { System.out.println("answer: " + answer.getValue()); for(int i=0;i<sum_of_col.size();i++) { System.out.println("=== " + sum_of_col.get(i).getValue()); } for(int i=0;i<number_of_pms;i++) { for(int j=0;j<number_of_vms;j++) { System.out.print(alloc_matrix[i][j].getValue() + " "); } System.out.println(); } } 中的矩阵的每一列来确保分配所有VM。如果我评论约束条件和目标,矩阵将被随机分配,但是当应用约束条件时,choco将无法解决任何问题(没有输出,因为model.arithm(sum_of_col.get(i), "=", 1).post();从未为真,因此choco似乎无法解决) 。我不知道我在哪里做错了。任何帮助表示赞赏:)

预先感谢

编辑:我意识到问题是choco第一次只检查那些约束,所以当一切都为0时会检查它,这就是为什么它不会继续的原因,但是在resolve()循环中添加约束后,我仍然得到同样的结果,也许我应该以另一种方式使这些约束应用,让choco理解它们,我现在真的很沮丧:(

1 个答案:

答案 0 :(得分:2)

我的问题是对CSP问题解决的基本了解,基本上所有变量一开始都是未知的,但是当choco求解器尝试解决问题时,它们将由值设置。因此,不可能像这样检索值并设置约束(即使在while(solve()){}中也是如此。基本上,我们应该在choco解决之前将整个约束应用于那些未知变量。因此,我更改了整个模型并获得了帮助来自choco开发人员(请查看他们的gitter聊天以寻求帮助)。因此,在下面,您将看到代码如下:

    Model model = new Model("Resource Allocation Problem");
    // here we are using number_of_sth+1 because we need to use a scalar function of choco
    // that will calculate sum(arr[i] * arr2[i]) and we need to specify the lack of PM
    // assignment by the 0 in them so that we can add a constraint later to prevent such
    // a happening (not assigning a VM to a PM)

    int[] VMcpu = new int[number_of_vms+1];
    int[] VMram = new int[number_of_vms+1];
    VMcpu[0] = 0;
    VMram[0] = 0;
    for (int i=1; i<number_of_vms+1; i++) {
        VMcpu[i] = vms.get(i-1).get_cpu();
        VMram[i] = vms.get(i-1).get_ram();
    }
    System.out.println();

    int[] PMcpu = new int[number_of_pms+1];
    int[] PMram = new int[number_of_pms+1];
    PMcpu[0] = 0;
    PMram[0] = 0;
    for (int i=1; i<number_of_pms+1; i++) {
        PMcpu[i] = pms.get(i-1).get_cpu();
        PMram[i] = pms.get(i-1).get_ram();
    }

    IntVar[] VMS = model.intVarArray("VMS", number_of_vms, 0, number_of_pms);

    // capacity constraints
    BoolVar[][] VMi_hosted_by_PMj = model.boolVarMatrix(number_of_pms+1, number_of_vms+1);

    for (int i=0; i<number_of_vms; i++) {
        model.arithm(VMS[i], "!=", 0).post();
    }

    for (int pm_i=1; pm_i<number_of_pms+1; pm_i++) {
        for (int vm_i=1; vm_i<number_of_vms+1; vm_i++) {
            // below is the functionality for 2 lines below
            // reifyXeqC(X, C, A) => (X == C) ? A=1 : A=0;
            model.reifyXeqC(VMS[vm_i-1], pm_i, VMi_hosted_by_PMj[pm_i][vm_i]);
        }
    }

    // here is the constraint to make sure the total VMs assigned to a PM
    // demand less that the PM's resources
    for (int i=1; i<number_of_pms+1; i++) {
        model.scalar(VMi_hosted_by_PMj[i], VMcpu, "<=", PMcpu[i]).post();
        model.scalar(VMi_hosted_by_PMj[i], VMram, "<=", PMram[i]).post();
    }

    // a constraint to have a number of PMs
    IntVar no_of_PM = model.intVar("#PM", 0, number_of_pms+1);

    // here we link the no_of_PM to the count of unique values in VMS (basically we
    // get a number of used PMs)
    model.nValues(VMS, no_of_PM).post();

    model.setObjective(false, no_of_PM); //false => model.MINIMIZE

    // here we define the array that will hold the final allocation vector (basically
    // we get a copy of VMS' values so that we have it later)
    int[] vm_alloc = new int[number_of_vms];
    int no_of_allocated_pms = number_of_pms;

    while(model.getSolver().solve()) {
        for (int i = 0; i < number_of_vms; i++) {
            vm_alloc[i] = VMS[i].getValue();
        }

        System.out.println("Number of used PMs: " + (no_of_PM.getValue()));
        no_of_allocated_pms = no_of_PM.getValue();

    }
相关问题