[英]Resource allocation in choco solver
我正在使用choco
解決虛擬機分配問題,這就是我正在嘗試做的事情:
假設我們有3個陣列用於物理機屬性( PMcpu
, PMram
, PMbw
)和3個陣列用於虛擬機( VMcpu
, VMram
, VMbw
)。 現在,我們定義一個具有以下尺寸的矩陣: PM*VM
以便choco設置值(0或1表示將特定VM分配給PM或不分配給PM)。 基於常識,我們知道PM資源應完全等於或等於所有已分配VM資源的數量,因此,為此,我們將分配矩陣中的每個元素與資源相應地相乘,例如:
PMcpu = {8000, 7000, 3000};
PMram = {7000, 4000, 5000};
PMbw = {2000, 500, 7000};
VMcpu = {2000, 3000, 1000};
VMram = {1000, 2000, 3000};
VMbw = {100, 2000, 500};
Allocation_matrix:
0 1 0
1 0 0
0 0 1
行代表PM,列代表VM,因此在這里:
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();
}
}
我試圖通過檢查要在行model.arithm(sum_of_col.get(i), "=", 1).post();
填充的矩陣的每一列來確保分配所有model.arithm(sum_of_col.get(i), "=", 1).post();
。 如果我評論約束條件和目標,矩陣將被隨機分配,但是當應用約束條件時,choco將不會解決任何問題(沒有輸出,因為while(model.getSolver().solve()
永遠都不為真,因此choco不while(model.getSolver().solve()
似乎無法解決)。我不知道我在哪里做錯了。不勝感激:)
提前致謝
編輯:我意識到問題是choco第一次只檢查那些約束,所以當一切都為0時會檢查它,這就是為什么它不會繼續的原因,但是在resolve()循環中添加約束后,我仍然得到相同的結果,也許我應該以Choco理解它們的另一種方式應用這些約束,我現在真的很沮喪:(
我的問題是對CSP解決問題的基本了解,基本上所有變量一開始都是未知的,但是當choco求解器嘗試解決問題時,它們將由值設置。 因此,不可能像這樣檢索值和設置約束(即使在while(solve()){}
。基本上,我們應該在choco解決之前將整個約束應用於那些未知變量,因此我更改了整個模型並從choco開發人員那里獲得了幫助(請查看他們的聊天室尋求幫助)。因此,在下面,您將看到代碼如下:
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.