2.3.1. Biến (Variable)
2.3.1.1. IntegerVariable: là biến mang giá trị nguyên.
30
Options:
Options. V_ENUM: Solver tạo ra miền liệt kê cho biến.
Options. V_BOUND: Solver tạo ra miền bị chặn cho biến.
Options. V_LINK: Solver tạo ra miền liên kết danh sách các biến.
Options. V_OBJECTIVE: xác định các biến để tối ưu hóa. Ví dụ:
IntegerVariable ivar1 = makeIntVar(“ivar1”, -10, 10);
IntegerVariable ivar2 = makeIntVar(“ivar2”, 0, 10000, Options. V_BOUND, Options. V_NO_DECITION);
IntegerVariable bool = makeBooleanVar(“bool”);
2.3.1.2. Real Variable: là biến số thực Cấu trúc:
makeRealVar (String name, double lowB, double uppB, String… options );
Hình 3-2: Bài toán khai báo biến RealVariable
2.3.1.3. Set Variable: biến tập hợp: Cấu trúc:
Ví dụ:
31
2.3.2. Biểu thức (Operators):
Phần này đưa ra danh sách chi tiết những biểu thức được sử dụng trong Choco để kết hợp các biến trong biểu thức.
2.3.2.1. Abs (Operators): Giá trị tuyệt đối của các đối số.
API: abs (IntegerExpressionVariable n) Return type: IntegerExpressionVariable Ví dụ:
Model m = new CPModel();
IntegerVariable x = makeIntVar(“x”, 1, 5, Options.V_ENUM); IntegerVariable y = makeIntVar(“y”, -5, 5, Options. V_ENUM); m.addConstraint(eq(abs(x), y));
Solver s = new CPSolver(); s.read(m);
s.solve();
2.3.2.2. cos (operator): cos (x)
API: cos (RealExpressionVariable exp) Return type: RealExpressionVariable Ví dụ:
Model m = new CPModel();
RealVariable x = makeRealVar(“x”, -Math.PI/2, Math.PI); m.addConstraint(eq(cos(x), 2/3));
Solver s = new CPSolver(); s.read(m);
s.solve();
2.3.2.3. div (operator): phép chia
API:
div(IntegerExpressionVariable n1, IntegerExpressionVariable n2) div(IntegerExpressionVariable n1, int n2)
32
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable x = makeIntVar(“x”, 1, 10); IntegerVariable y = makeIntVar(“y”, 22, 44); IntegerVariable z = makeIntVar(“z”, 12, 21); m.addConstraint(eq(z, div(y, z))); s.read(m); s.solve(); 2.3.2.4. ifThenElse (operator)
Biểu thức ifThenElse(c, v1, v2): Khi ràng buộc c thỏa mãn, giá trị biến sẽ là tham số v1, còn trong các trường hợp khác giá trị biến sẽ là tham số v2.
API:ifThenElse(Constraintc,IntegerExpressionVariablev1, IntegerExpressionVariable v2)
Ví dụ:
Model m = new CPModel();
IntegerVariable x = makeIntVar(“x”, 1, 5); IntegerVariable y = makeIntVar(“y”, 0, 10);
m. addConstraint (eq(y, ifThenElse(gt(x, 2), mult(x, x), x))); Solver s = new CPSolver();
s.read(m); s.solve();
2.3.2.5. max (operator): Giá trị lớn nhất
API:
Max (IntegerExpressionVariable x1, IntegerExpressionVariable x2) Max (int x1, IntegerExpressionVariable x2)
Max (IntegerExpressionVariable x1, int x2) Max (IntegerExpressionVariable [] x)
33
Ví dụ:
Model m = new CPModel();
m.setDefaultExpressionDecomposition(true);
IntegerVariable[] v = makeIntVarArray(“v”, 3, -3, 3); IntegerVariable maxv = makeIntVar(“max”, -3, 3); Constraint c = eq(maxv, max(v));
m.addConstraint(c);
Solver s = new CPSolver(); s.read(m);
s.solve();
2.3.2.6. min (operator): Giá trị nhỏ nhất API:
Min (IntegerExpressionVariable x1, IntegerExpressionVariable x2) Min (int x1, IntegerExpressionVariable x2)
Min (IntegerExpressionVariable x1, int x2) Min (IntegerExpressionVariable [] x)
Ví dụ:
Model m = new CPModel();
m.setDefaultExpressionDecomposition(true);
IntegerVariable[] v = makeIntVarArray(“v”, 3, -3, 3); IntegerVariable minv = makeIntVar(“min”, -3, 3); Constraint c = eq(minv, min(v));
m.addConstraint(c);
Solver s = new CPSolver(); s.read(m);
s.solve();
2.3.2.7. minus (operator): Phép trừ
API:
34
Minus (IntegerExpressionVariable x, int y) Minus (int x, IntegerExpressionVariable y)
Minus (RealExpressionVariable x, RealExpressionVariable y) Minus (RealExpressionVariable x, double y)
Minus (double x, RealExpressionVariable y) Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable a = makeIntVar(“a”, 0, 4); m.addConstraint(eq(minus(a, 1), 2)); s.read(m);
s.solve();
2.3.2.8. mod (operator): phép chia lấy phần dư
API:
Mod (IntegerExpressionVariable x1, IntegerExpressionVariable x2) Mod (IntegerExpressionVariable x1, int x2)
Mod (int x1, IntegerExpressionVariable x2) Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable x = makeIntVar(“x”, 1, 10); IntegerVariable w = makeIntVar(“w”, 22, 44); m.addConstraint(eq(1, mod(w, x)));
s.read(m); s.solve();
2.3.2.9. mult (operator): Phép nhân
API:
Mult (IntegerExpressionVariable x, IntegerExpressionVariable y) Mult (IntegerExpressionVariable x, int y)
35
Mult (int x, IntegerExpressionVariable y)
Mult (RealExpressionVariable x, RealExpressionVariable y) Mult (RealExpressionVariable x, double y)
Mult (double x, RealExpressionVariable y) Ví dụ:
CPModel m = new CPModel();
IntegerVariable x = makeIntVar(“x”, - 10, 10); IntegerVariable z = makeIntVar(“z”, - 10, 10); IntegerVariable w = makeIntVar(“w”, - 10, 10); m.addVariables(x, z, w);
CPSolver s = new CPSolver(); // x >= z * w
Constraint exp = geq(x, mult(z, w));
m.setDefaultExpressionDecomposition(true); m.addConstraint(exp);
s.read(m); s.solveAll();
2.3.2.10. neq (operator): Số âm
API: neq(IntegerExpressionVariable x) Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable x = makeIntVar(“x”, - 10, 10); IntegerVariable w = makeIntVar(“w”, - 10, 10); // - x = w – 20 m.addConstraint(eq(neq(x), minus(w, 20))); s.read(m); s.solve(); 2.3.2.11. Plus (operator): Phép cộng API:
36
plus (IntegerExpressionVariable x, IntegerExpressionVariable y) plus (IntegerExpressionVariable x, int y)
plus (int x, IntegerExpressionVariable y)
plus (RealExpressionVariable x, RealExpressionVariable y) plus (RealExpressionVariable x, double y)
plus (double x, RealExpressionVariable y) Ví dụ:
CPModel m = new CPModel(); Solver s = new CPSolver();
IntegerVariable a = makeIntVar(“a”, 0, 4); // a + 1 = 2 m.addConstraint(eq(plus(a, 1), 2)); s.read(m); s.solve(); 2.3.2.12. power (operator): Mũ API:
power (IntegerExpressionVariable x, IntegerExpressionVariable y) power (IntegerExpressionVariable x, int y)
power (int x, IntegerExpressionVariable y) power (RealExpressionVariable x, int y) Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable x = makeIntVar(“x”, 0, 10); IntegerVariable y = makeIntVar(“y”, 2, 4); IntegerVariable z = makeIntVar(“z”, 28, 80); m.addConstraint(eq(z, power(x,y))); s.read(m); a.solve();
37
2.3.2.13. scalar (operator): trả về biểu thức là hệ số mảng và biến của m
API:
Scalar (int[] c, IntegerVariable [] x) Scalar (IntegerVariable[] x, int c) Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable[] vars = makeIntVarArray(“C”, 9, 1, 10); int[] coefficients = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; m.addConstraint(eq(165, scalar(coefficients, vars))); s.read(m);
s.solve();
System.out.print(“165=(“+coefficients[0]+“*”+s.getVar(vars[0]).getVal()+”)”)
For (int i=1, i < var.length, i++) {
System.out.print(“=(“+coefficients[i]+“*”+s.getVar(vars[i]).getVal()+”)”);
}
System.out.println();
2.3.2.14. sin (operator):
API:
sin (RealExpressionVariable exp) Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
RealVariable x = makeRealVar(“x”, 0, Math.PI); m.addConstraint(eq(sin(x), 1));
s.read(m); s.solve();
2.3.2.15. sum (operator): Tính tổng
38
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable[] vars = makeIntVarArray (“C”, 10, 1, 10); m.addConstraint(eq(99, sum(vars)));
s.read(m); s.solve();
if(s.isFeasible()){
System.out.print(“99 = “ + s.getVar(vars[0]).getVal()); For (int i=1; i < vars.length; i++) {
System.out.print(“ + “+s.getVar(vars[i].getVal()); } System.out.print(); } 2.3.3. Constraint 2.3.3.1. Abs:
Abs (x, y): x là giá trị tuyệt đối của y X = |Y|
API: abs (IntegerVariable x, IntegerVariable y) Return type: Constraint
Ví dụ:
Model m = new CPModel();
IntegerVariable x = makeIntVar (“x”, 1, 5, Options.V_ENUM); IntegerVariable y = makeIntVar (“y”, -5, 5, Options.V_ENUM); m.addConstraint (abs(x,y));
Solver s = new CPSolver(); s.read(m);
39
2.3.3.2. allDifferent:
allDifferent (x1, …, xn): các cặp số đôi một khác nhau xi # xj; j
API:
allDifferent (IntegerVariable … x)
allDifferent (String options, IntegerVariable … x) return type: constraint
Ví dụ: n – queens
CPModel m = new CPModel();
IntegerVariable[] queens = new IntegerVariable[n]; IntegerVariable[] diag1 = new IntegerVariable[n]; IntegerVariable[] diag2 = new IntegerVariable[n]; For (int i = 0, i<n, i++) {
Queens[i] = makeIntVar (“Q” + i, 1, n); Diag1[i] = makeIntVar (“D1” + i, 1, 2*n); Diag2[i] = makeIntVar (“D2” + I, -n + 1, n); }
m.addConstraint(allDifferent(queens)); for (int i = 0, i<n, i++) {
m.addConstraint (eq(diag1[i], plus(queens[i], i))); m.addConstraint (eq(diag2[i], minus(queens[i], i))); }
CPSolver s = new CPSolver(); s.read();
s.solveALL();
2.3.3.3. among:
Among (z, x1, … , xn, s): z bằng I sao cho xi thuộc vào tập s Z = |{i | xi s}|
40
Among (IntegerVariable z, IntegerVariable[] x, int[] v)
Among (IntegerVariable z, IntegerVariable[] x, SetVariable s) Return type: Constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable nvar = makeIntVar(“v1”, 1, 2);
IntegerVariable[] vars = Choco.makeIntVarArray(“var”, 10, 0, 10); int[] values = new int[] {2,3,5};
m.addConstraint(among(nvar, vars, value)); s.read(m);
s.solve();
2.3.3.4. and
And (C1, … , Cn) : tất cả những ràng buộc đều thỏa mãn C1 C2 … Cn
And (B1, … , Bn) : các phép toán đều đúng (B1 = 1) (B2 = 1) … (bn = 1) API:
And (Constraint … c) And (IntegerVariable … b) Return type: Constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable v1 = makeIntVar(“v1”, 0, 1); IntegerVariable v2 = makeIntVar(“v2”, 0,1); m.addConstraint(and(eq(v1,1),eq(v2,1))); s.read(m);
41
2.3.3.5. atMostNValue
atMostNValue(z, x1, … , xn) : số lượng các giá trị thỏa mãn của x luôn nhỏ hơn z
z | x1, …, xn |
API: atMostNValue( IntegerVariable z, IntegerVariable[] x) Return type: Constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable v1 = makeIntVar (“v1”, 1, 1); IntegerVariable v2 = makeIntVar (“v2”, 2, 2); IntegerVariable v3 = makeIntVar (“v3”, 3, 3); IntegerVariable v4 = makeIntVar (“v4”, 3, 4); IntegerVariable n = makeIntVar (“n”, 3, 3);
Constraint c = atMostNValue (n, new IntegerVariable[] {v1, v2, v3, v4}); m.addConstraint(c);
s.read(m); s.solve();
2.3.3.6. boolChanneling
boolChaneling (b, x, v): b đúng khi và chỉ khi giá trị x = v (b = 1) (x = v)
API: boolChaneling (IntegerVariable b, IntegerVariable x, int v) Return type: constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable bool = makeIntVar(“bool”, 0, 1); IntegerVariable x = makeIntVar(“x”, 0, 5); m.addConstraint(boolChanneling(bool, x, 4));
42
s.read(m); s.solve();
2.3.3.7. distanceEQ:
distanceEQ (x1, x2, x3, c): Khoảng cách giữa x1 và x2 bằng x3+c x3 + c = |x1 – x2|
API:
distanceEQ(IntegerVariable x1, IntegerVariable x2, int x3)
distanceEQ(IntegerVariable x1, IntegerVariable x2, IntegerVariable x3) distanceEQ(IntegerVariable x1, ntegerVariable x2, IntegerVariable x3, int c) return type: Constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver();
IntegerVariable v0 = makeIntVar(“v0”, 0,5); IntegerVariable v1 = makeIntVar(“v1”, 0, 5); IntegerVariable v2 = makeIntVar(“v2”, 0, 5); m.addConstraint(distanceEQ(v0, v1, v2, 0)); s.read(m); s.solveAll(); 2.3.3.8. eq
Eq(x, y): ràng buộc sao cho x = y API: Eq (IntegerExpressionVariable x, IntegerExpressionVariable y) Eq (IntegerExpressionVariable x, int y) Eq (int x, IntegerExpressionVariable y) Eq (SetVariable x, SetVariable y) Eq (RealExpressionVariable x, RealxpressionVariable y) Eq (RealExpressionVariable x, double y) Eq (double x, RealExpressionVariable y)
43
Eq (IntegerVariable x, Realvariable y ) Eq (RealVariable x, IntegerVariable y) Return type: constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver(); Int c = 1; IntegerVariable v = makeIntVar(“v”, 0, 2); m.addConstraint(eq(v, c)); s.read(m); s.solve(); 2.3.3.9. equation
Equation (z, x1, … , xn, c1, …, cn): ràng buộc về trọng số của x sao cho bằng z.
C1x1 + c2x2 + … + cnxn = z API:
Equation(int z, IntegerVariable[] x, int[] c)
Equation (String option, int z, IntegerVariable[] x, int[] c) Equation (IntegerVariable z, IntegerVariable[] x, int[] c)
Equation (String option, IntegerVariable z, IntegerVariable[] x, int[] c)
Return type: Constraint Ví dụ:
CPModel m = new CPModel(); Solver s = new CPSolver(); Int n = 10;
IntegerVariable[] bvars = makeIntVarArray(“b”, n, 0, 10, Options.V_ENUM);
Int[] coefs = new int[n]; Int charge = 10;
Random rand = new Random(); For (int i = 0, i < coefs.length; i++) {
44
Coefs[i] = rand.nextInt(10); }
Constraint knapsack = equation(charge, bvars, coefs); m.addConstraint(knapsack);
s.read(m); s.solveAll();
2.3.3.10. Geq
Geq(x,y): ràng buộc x lớn hơn bằng y X Y
API:
geq (IntegerExpressionVariable x, IntegerExpressionVariable y) geq (IntegerExpressionVariable x, int y)
geq (int x, IntegerExpressionVariable y)
geq (RealExpressionVariable x, RealxpressionVariable y) geq (RealExpressionVariable x, double y)
geq (double x, RealExpressionVariable y) Return type: Constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver(); Int c = 1; IntegerVariable v = makeIntVar(“v”, 0, 2); m.addConstraint(eq(v, c)); s.read(m); s.solve(); 2.3.3.11. gt
Gt(x, y): ràng buộc x lớn hơn y (X > Y) API:
45
Gt (IntegerExpressionVariable x, IntegerExpressionVariable y) Gt (IntegerExpressionVariable x, int y)
Gt (int x, IntegerExpressionVariable y) Return type: Constraint
Ví dụ:
Model m = new CPModel(); Solver s = new CPSolver(); Int c = 1; IntegerVariable v = makeIntVar(“v”, 0, 2); m.addConstraint(gt(v, c)); s.read(); s.solve(); 2.3.3.12. leq
Leq(x, y): ràng buộc x nhỏ hơn hoặc bằng y API:
leq (IntegerExpressionVariable x, IntegerExpressionVariable y) leq (IntegerExpressionVariable x, int y)
leq (int x, IntegerExpressionVariable y)
leq (RealExpressionVariable x, RealxpressionVariable y) leq (RealExpressionVariable x, double y)
leq (double x, RealExpressionVariable y) Return type: Constraint
Model m = new CPModel(); Solver s = new CPSolver(); Int c = 1;
IntegerVariable v = makeIntVar(“v”, 0, 2); m.addConstraint(leq(v,c));
IntegerVariable v1 = makeIntVar(“v1”, 0, 2); IntegerVariable v2 = makeIntVar(“v2”, 0,2);
46 IntegerExpressionVariable w1 = plus(v1, 1); IntegerExpressionVariable w2 = minus(v2, 1); m.addConstraint(leq(w1, w2)); s.read(m); s.solve();
2.4. Ví dụ về các bài toán đƣợc giải quyết bằng Choco: 2.4.1. Ví dụ 1: Bài toán con hậu N-Queens 2.4.1. Ví dụ 1: Bài toán con hậu N-Queens
Cho bàn cờ kích thước n*n có n con hậu. Cách sắp xếp n con hậu trên bàn cờ sao cho không có con nào có thể ăn lẫn nhau.
package example; import choco.Choco; import choco.Options; import choco.cp.model.CPModel; import choco.cp.solver.CPSolver; import choco.kernel.model.variables.integer.IntegerVariable; public class QUEENS {
public static void main (String [] args) {
// Khai báo biến
int n=8;
IntegerVariable[] queens=new IntegerVariable[n]; IntegerVariable[] diag1=new IntegerVariable[n]; IntegerVariable[] diag2=new IntegerVariable[n];
// Xây dựng mẫu
CPModel m=new CPModel();
// Đối với từng biến, xác định tên và giới hạn miền của chúng
for (int i=0;i<n;i++) {
queens[i]=Choco.makeIntVar("Q"+i,1,n); diag1[i]=Choco.makeIntVar("D1"+i, 1,2*n);
47
diag2[i]=Choco.makeIntVar("D2"+i,-n+1,n); }
// Khai báo ràng buộc
// - Mỗi con hậu phải ở trên 1 dòng
m.addConstraint(Choco.allDifferent(queens));
// - Không có bất kỳ 2 con hậu nào cùng nằm trên một đường chéo
for (int i=0;i<n;i++) { m.addConstraint(Choco.eq(diag1[i],Choco.plus(queens[i], i))); m.addConstraint(Choco.eq(diag2[i],Choco.minus(queens[i],i))); } m.addConstraint(Choco.allDifferent(diag1)); m.addConstraint(Choco.allDifferent(diag2));
// Xây dựng lời giải
CPSolver s=new CPSolver();
// Đọc mẫu s.read(m); // Giải mẫu s.solve(); // In giải pháp for(int i=0;i<n;i++) { System.out.print(" "+s.getVar(queens[i]).getVal()); } }
48
2.4.2. Ví dụ 2: Bài toán Magic square
Ma phương bậc n (ma trận kỳ ảo bậc n) là một cách sắp xếp n2
số, thường là các số nguyên phân biệt, trong một mảng dữ liệu cùng kiểu vuông, sao cho tổng n số trên mỗi hàng, cột, và đường chéo đều bằng nhau. Ma trận kỳ ảo chuẩn chứa các số nguyên từ 1 đến n2
.
Hằng số là tổng của mỗi hàng, cột và đường chéo được gọi là hằng số kỳ ảo hay tổng số kỳ ảo M. Hằng số kỳ ảo của một ma phương cổ điển chỉ phụ thuộc vào bậc n và có giá trị n(n2
+ 1)/2. package example; import choco.Choco; import choco.cp.model.CPModel; import choco.cp.solver.CPSolver; import choco.kernel.model.variables.integer.IntegerVariable; public class Magic {
public static void main(String [] args) {
// Khai báo hằng số
int n=3; // Lệnh của ma phương
int tong=n*(n*n+1)/2; // Tổng số kỳ ảo // Tạo mảng biến cùng kiểu
IntegerVariable [][] x=new IntegerVariable[n][n];
// Đối với từng biến, xác định tên và giới hạn miền D của biến
for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { x[i][j]=Choco.makeIntVar(" x ", 1,n*n); } } // Xây dựng mẫu
49
// Ràng buộc hàng: Tổng hàng phải bằng tổng số kỳ ảo
for (int i=0;i<n;i++) { IntegerVariable[] temp=Choco.makeIntVarArray("temp", n,1,1000000); for(int j=0;j<n;j++) { temp[j]=x[i][j]; } m.addConstraint(Choco.eq(tong,Choco.sum(temp))); }
// Ràng buộc cột: Tổng cột phải bằng tổng số kỳ ảo
for(int i=0;i<n;i++) { IntegerVariable[][]tt=Choco.makeIntVarArray("tt", n, n,1,n*n); for (int j=0;j<n;j++) { tt[i][j]=x[j][i]; } }
for (int i=0;i<n;i++) { IntegerVariable[] temp=Choco.makeIntVarArray("temp", n,1,1000000); for(int j=0;j<n;j++) { temp[j]=x[i][j]; } m.addConstraint(Choco.eq(tong,Choco.sum(temp) ));
50
}
// Ràng buộc chéo: Tổng đường chéo bằng tổng số kỳ ảo
for (int i=0;i<n;i++) { IntegerVariable[] cheo1=Choco.makeIntVarArray("cheo1",n,1,n*n); IntegerVariable[] cheo2=Choco.makeIntVarArray("cheo2",n,1,n*n); for (int j=0;j<n;j++) { cheo1[i]=x[i][i]; cheo2[i]=x[n-1-i][i]; } m.addConstraint(Choco.eq(tong, Choco.sum(cheo1))); m.addConstraint(Choco.eq(tong, Choco.sum(cheo2))); }
// Các ô của ma trận phải khác nhau
IntegerVariable[] t2=Choco.makeIntVarArray("t2", n*n,1,n*n); for (int i=0;i<n;i++)
{ for(int j=0;j<n;j++) { t2[i*n+j]=x[i][j]; } m.addConstraint(Choco.allDifferent(t2)); } // Xây dựng Solver
CPSolver s=new CPSolver();
// Đọc mẫu
51
// Giải mẫu
s.solve();
// In giải pháp
for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { System.out.print(" "+s.getVar(x[i][j]).getVal()+"---"); } System.out.println(); } } }
52
CHƢƠNG 3: ÁP DỤNG THƢ VIỆN CHOCO VÀO BÀI TOÁN ỨNG DỤNG: “XẾP LỊCH HỌC CHO CÁC LỚP CAO HỌC BÁCH KHOA”
3.1. Phát biểu bài toán:
Bài toán xếp lịch học luôn là một bài toán khó, mang tính khoa học đồng thời mang tính thực tiễn rất cao. Trên thế giới, bài toán Xếp lịch học (TimeTabling) đã được rất nhiều các nhà khoa học quan tâm, nghiên cứu. Đã có hơn 1000 bài báo khoa học được viết về đề tài này, trong đó có khoảng 300 luận án Tiến sĩ và Thạc sỹ được bảo vệ xung quanh về bài toán Thời khóa biểu. Riêng đối với Việt Nam, đặc biệt trong các trường Đại học, các trường phổ thông hay Cao học, từ lâu việc xếp lịch học đã trở thành một vấn đề có tính thời sự, một bài toán gây được sự chú ý, quan tâm của nhiều người.
Một thực tế hiện nay tại Việt Nam, việc xếp thời khóa biểu phần lớn là đều được thực hiện thủ công bằng tay. Phương pháp này vừa tốn nhiều chi phí, thời gian, công sức mà hiệu quả lại không cao. Nhu cầu thực tiễn hiện nay là tin học hóa bài toán xếp lịch học với tính năng sắp thời khóa biểu chính xác, hiệu quả, giảm bớt thời gian, chi phí công sức của con người. Tính phức tạp của bài toán xếp lịch học là các quy định, ràng buộc môn học chặt chẽ, các ràng buộc về lịch dạy của giáo viên, lớp học … hết sức phức tạp, đa dạng. Chính vì vậy, bài toán lập thời khóa biểu là một bào toán khó, có rất ít phần mềm lập thời khóa biểu được viết và sử dụng tại Việt Nam.
Dựa trên mô hình đào tạo sau đại học của trường Đại học Bách Khoa, đối với mỗi kỳ học, phòng đào tạo quy định danh sách các lớp học, danh sách các môn học tương ứng cho từng lớp học và danh sách giảng viên tương ứng với mỗi môn cho từng lớp. Trong luận văn, bài toán xếp lịch học cho các lớp cao học Bách Khoa phải đáp ứng được tất cả các điều kiện ràng buộc sau:
- Mỗi môn học ứng với một danh sách các ngày mà môn đó có thể được phân bổ vào (mỗi môn học đó đã được phân trước cho giảng viên và mỗi giảng viên chỉ có thời gian rảnh rỗi vào một số ngày nhất định)
53
- Số ngày của môn học ứng với số tín chỉ
- Mỗi lớp ứng với một danh sách các môn học mà lớp đó đăng ký.
- Xếp mỗi môn học vào một ngày nào đó sao cho không có xung đột xảy ra (hai môn học có chung lớp đăng ký thì phải xếp vào hai ngày khác nhau.)
3.2. Mô hình hóa với CHOCO
Bài toán xếp lịch học hoạt động hiệu quả nhất thì phải đáp ứng được các yêu cầu nghiệp vụ của bào toán. Do đó, chúng ta sẽ lần lượt giải quyết từng ràng buộc của bài toán. Với bài toán này tôi đưa ra hai mô hình.
Dữ liệu đầu vào:
• n: số môn học, các buổi học đánh số 0, 1, …, n-1
• b[i]: số buổi học của môn i (tùy thuộc số tín chỉ), với mọi i = 0,1,…,n-1 • f[i]: danh sách những buổi học bị cấm xếp của môn i do giảng viên của môn
này bận, với mọi i = 0,1,…,n-1
• D: số buổi của học kỳ, các môn sẽ được xếp vào các buổi 0, 1, 2,…, D-1 • Conflict[i,j] =1, nếu 2 môn i và j có xung đột với nhau(chung giảng viên dạy
hoặc chung lớp đăng ký học) và Conflict[i,j] = 0 nếu ngược lại, với mọi i,j = 0,1…,n-1,
3.2.1. Mô hình 1 (stateModel 1)
• Biến: X[i,d], với i = 0,1,…,n-1, d = 0,1,…, D-1
• Miền giá trị: D(X[i,d]) = {0,1}. Nếu X[i,d] = 1 nghĩa là môn i được xếp vào ngày d, bằng 0 ngược lại môn i không được xếp vào ngày d.
• Ràng buộc:
Ràng buộc về ngày học đưa ra danh sách các ngày mà môn đó được phân bổ vào: X[i,0] + X[i,1] + … + X[i,D-1] = b[i], i = 0,1,…,n-1
Ràng buộc xung đột: X[i,d] + X[j,d] ≤ 1, 0 ≤ i < j ≤ n-1 trong đó Conflict[i,j] = 1
54
Ràng buộc về những ngày cấm học: f[i] là những ngày học môn i bị cấm,Với d f[i] thì X[i,d] = 0 tức là môn i không xếp lịch vào những ngày bị cấm đó.
3.2.2. Mô hình 2 (stateModel 2)
• Biến: X[i, j] là ngày mà buổi học thứ j của môn i được phân bổ vào. .
• Ràng buộc:
Ràng buộc về thứ tự tương đối và ngày học của mỗi môn: X[i,j] < X[i,j+1] với mọi i = 0,…,n-1, với mọi j = 0,…,b[i]-2
Ràng buộc về những ngày cấm học: X[i,j] ≠ d với mọi d f[i], với mọi i = 0,…,n-1, j=0,..,b[i]-1.
Ràng buộc xung đột: Với mọi i ≠ j trong đó Conflict[i,j] = 1 thì X[i,h] ≠ X[j,k] với mọi h = 0,…,b[i]-1, k = 0,…,b[j]-1
55
3.3. Thử nghiệm
Trong phần này, chúng tôi thử nghiệm và so sánh 2 mô hình trên 10 bộ dữ liệu sinh ngẫu nhiên. Chúng tôi xin đưa ra ví dụ 1 bộ dữ liệu đầu vào sau đây:
56
Sau đây là kết quả chạy thử nghiệm của 2 mô hình:
STT Bộ dữ liệu Số môn Số ngày Số lớp Mô hình 1 Mô hình 2
1 Test-5-50-1 5 50 1 34.094 0.356 2 Test-6-60-1 6 60 1 379.431 0.496 3 Test-7-70-1 7 70 1 - 0.38 4 Test-8-80-1 8 80 1 - 0.512