Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 8

- Đầu

 cho giá trị không đạt, hàm error được gọi để dừng thực thi chương trình và hiển
thị thông điệp lỗi, chỉ ra rằng tất cả các mục phải là số nguyên từ 1 đến 9.

Lb và ub là giới hạn dưới và trên cho các biến , đặt thành 0 và 1 đẻ chỉ rõ các biến
là nhị phân(có mặt hay không có mặt) 9x9x9 vì tổng thể có 729 biến khả năng

- rằng các ôs từ 1-9 chỉ xuất hiện 1 lần trong mỗi hàng
-
- Counter được sử dụng để theo dõi chỉ số của hàng hiện tại trong Aeq
Vòng lặp ngoài chạy từ 1-9 , mỗi lần lặp đại diện cho 1 cột
Vòng lặp trong chạy từ 1-9, mỗi lần lặp đại diện cho 1 số từ 1-9 . Mục tiêu là
thiết lập ràng buộc cho mỗi số ở trong cột
- Ma trận Astuff bằng giới hạn dưới , mảng 9x9x9 (3 chiều) . Mục đích của việc
này là để làm sạch hoặc thiết lập lại Astuff trước mỗi lần lặp để chuẩn bị cho
ràng buộc mới .
- Đặt tất cả các giá trị cột j và chiều sâu k = 1. Điều này có nghĩa là trong
bảng sudoku , xuất hiện 1 lần ở cột j và áp dụng cho tất cả các hàng
-
o mảng 3D Astuff thành một vector hàng.
o Aeq(counter,:) = Astuff(:)'; gán vector này vào hàng thứ counter của Aeq, từ đó
lưu trữ ràng buộc mà chúng ta vừa xây dựng.
- Tăng counter: Sau khi mỗi ràng buộc được tạo và lưu, counter tăng lên 1 để chuẩn
bị cho ràng buộc tiếp theo.
- Tương tự thế làm với ràng buộc của các cột

for U = 0:3:6 % one in each square


for V = 0:3:6
for k = 1:9
Astuff = lb;
Astuff(U+(1:3),V+(1:3),k) = 1;
Aeq(counter,:) = Astuff(:)';
counter = counter + 1;
end
end
end
Đoạn code này là một phần của quá trình xây dựng ma trận ràng buộc Aeq cho bài toán
Sudoku, cụ thể là để đảm bảo rằng mỗi số từ 1 đến 9 xuất hiện đúng một lần trong mỗi khối
3x3 của bảng Sudoku. Cấu trúc vòng lặp và các lệnh được sử dụng như sau:

Đoạn code này là một phần của quá trình xây dựng ma trận ràng buộc Aeq cho bài toán
Sudoku, cụ thể là để đảm bảo rằng mỗi số từ 1 đến 9 xuất hiện đúng một lần trong mỗi
khối 3x3 của bảng Sudoku. Cấu trúc vòng lặp và các lệnh được sử dụng như sau:

Vòng lặp ngoài cùng: for U = 0:3:6 % one in each square

 Vòng lặp này lặp qua các hàng của các ô 3x3. Giá trị U bắt đầu từ 0, tăng theo
bước là 3 và kết thúc ở 6, đại diện cho các hàng đầu tiên của mỗi khối 3x3 (có ba
khối 3x3 theo chiều dọc).

Vòng lặp thứ hai: for V = 0:3:6

 Vòng lặp này lặp qua các cột của các ô 3x3. Giá trị V bắt đầu từ 0, tăng theo bước
là 3 và kết thúc ở 6, đại diện cho các cột đầu tiên của mỗi khối 3x3 (có ba khối
3x3 theo chiều ngang).

Vòng lặp bên trong cùng: for k = 1:9

 Vòng lặp này lặp qua các số từ 1 đến 9. Mỗi số k cần được đảm bảo xuất hiện
đúng một lần trong mỗi khối 3x3.

Lệnh Astuff = lb;

 Lệnh này thiết lập Astuff bằng giá trị của lb (là ma trận khởi tạo giới hạn dưới, ban
đầu là toàn bộ các số 0). Astuff sẽ được sử dụng để xây dựng một ràng buộc cụ
thể.

Lệnh Astuff(U+(1:3),V+(1:3),k) = 1;

 Lệnh này đặt tất cả các phần tử trong một khối 3x3 cụ thể thành 1 cho số k.
U+(1:3) và V+(1:3) tính toán các chỉ số hàng và cột thực tế trong khối 3x3. Ví dụ,
nếu U = 0 và V = 0, thì khối 3x3 đầu tiên ở góc trên cùng bên trái của bảng Sudoku
sẽ được lựa chọn.

Lệnh Aeq(counter,:) = Astuff(:)';

 Lệnh này chuyển Astuff thành một vector hàng (bằng cách sử dụng (:)' để làm
phẳng mảng) và gán nó vào hàng thứ counter của ma trận Aeq. Ma trận Aeq sử
dụng các hàng này để biểu diễn ràng buộc trong bài toán ILP, đảm bảo rằng mỗi
số từ 1 đến 9 xuất hiện đúng một lần trong mỗi khối 3x3.

Lệnh counter = counter + 1;

 Lệnh này tăng biến đếm counter lên 1 sau mỗi lần lặp, để đảm bảo rằng hàng tiếp
theo của Aeq sẽ được gán cho ràng buộc tiếp theo trong quá trình xây dựng ma
trận.
for i = 1:9 % one in each depth
for j = 1:9
Astuff = lb;
Astuff(i,j,1:end) = 1;
Aeq(counter,:) = Astuff(:)';
counter = counter + 1;
end
end
1. Vòng lặp ngoài: for i = 1:9 % one in each depth
 Đây là vòng lặp qua mỗi hàng i của bảng Sudoku. Từ "depth" ở đây có thể gây nhầm lẫn,
nhưng trong ngữ cảnh này, nó chỉ đơn giản là đang lặp qua mỗi hàng của bảng.
2. Vòng lặp trong: for j = 1:9
 Vòng lặp này chạy qua mỗi cột j của bảng. Kết hợp với vòng lặp hàng, chúng ta đang xét
đến từng ô (i, j) trên bảng Sudoku.
3. Khởi tạo Astuff: Astuff = lb;
 Astuff được thiết lập lại thành lb mỗi khi bắt đầu một lần lặp mới. lb ban đầu là một
mảng ba chiều 9x9x9 với tất cả các phần tử là 0, và Astuff sử dụng cấu trúc này để xây
dựng ràng buộc mới.
4. Thiết lập ràng buộc: Astuff(i,j,1:end) = 1;
 Dòng này đặt tất cả các phần tử trong chiều thứ ba (tức là cho tất cả các số từ 1 đến 9)
của ô được chỉ định bởi hàng i và cột j thành 1. Điều này tạo ra một ràng buộc trong ILP
biểu thị rằng chỉ một số duy nhất (từ 1 đến 9) có thể được gán cho ô đó. Nói cách khác,
trong mỗi ô (i, j) của bảng Sudoku, chỉ có thể chọn một giá trị duy nhất.
5. Lưu ràng buộc vào Aeq: Aeq(counter,:) = Astuff(:)';
 Astuff(:)' làm phẳng mảng ba chiều Astuff thành một vector hàng. Sau đó, vector này
được gán vào hàng hiện tại của ma trận Aeq, được xác định bởi biến counter. Ma trận
Aeq sử dụng các hàng này để lưu trữ các ràng buộc của bài toán ILP.
6. Cập nhật counter: counter = counter + 1;
 Sau khi một ràng buộc được thêm vào Aeq, biến đếm counter được tăng lên 1 để ràng
buộc tiếp theo có thể được lưu vào hàng tiếp theo của Aeq.

for i = 1:size(B,1)
lb(B(i,1),B(i,2),B(i,3)) = 1;
end

Câu lệnh for i = 1:size(B,1) trong MATLAB, kết hợp với các lệnh bên trong nó, là một phần
của quá trình giải Sudoku bằng cách sử dụng lập trình tuyến tính nguyên (Integer Linear
Programming - ILP). Đây là cách thiết lập các giới hạn (constraints) trong mảng ba chiều
lb dựa trên các gợi ý hoặc số đã cho từ bảng Sudoku. Dưới đây là giải thích chi tiết về ý
nghĩa và chức năng của đoạn code này:

Giải thích Câu Lệnh

 for i = 1:size(B,1) : Đây là một vòng lặp for chạy từ 1 đến số hàng của ma trận B. Ma
trận B được giả định là chứa các gợi ý của bài toán Sudoku, với mỗi hàng của B
chứa ba giá trị: chỉ số hàng ( B(i,1)), chỉ số cột ( B(i,2)), và số cụ thể ( B(i,3)) cần điền
vào bảng Sudoku. size(B,1) trả về số lượng hàng trong ma trận B, tức là số gợi ý
đã cho.
 lb(B(i,1),B(i,2),B(i,3)) = 1; : Đây là câu lệnh thực hiện việc cập nhật mảng ba chiều lb,
mà thường được khởi tạo với toàn bộ giá trị là 0. Mỗi phần tử của lb tại vị trí
(B(i,1), B(i,2), B(i,3)) được thiết lập thành 1. Nghĩa là:
 B(i,1): Chỉ số hàng trong bảng Sudoku.
 B(i,2): Chỉ số cột trong bảng Sudoku.
 B(i,3): Giá trị số tương ứng cần được đặt vào ô tại hàng B(i,1) và cột B(i,2).

Mục Đích Của Câu Lệnh

Mục đích chính của đoạn code này là đảm bảo rằng các số đã được cung cấp trước như
một phần của bài toán Sudoku được bảo toàn trong quá trình giải quyết bài toán sử
dụng ILP. Việc thiết lập lb(B(i,1),B(i,2),B(i,3)) = 1 bảo đảm rằng trong giải pháp cuối cùng, ô
tại vị trí đã chỉ định sẽ chứa số đã cho, làm cho nó cố định và không thay đổi. Điều này
giúp hạn chế không gian tìm kiếm của giải thuật ILP và định hướng giải thuật tới một lời
giải đúng đắn theo các gợi ý đã biết từ đầu.

intcon = 1:N;

[x,~,eflag] = intlinprog(f,intcon,[],[],Aeq,beq,lb,ub);
%% Convert the Solution to a Usable Form
% To go from the solution x to a Sudoku grid, simply add up the numbers at
% each $(i,j)$ entry, multiplied by the depth at which the numbers appear:

if eflag > 0% good solution


x = reshape(x,9,9,9); % change back to a 9-by-9-by-9 array
x = round(x); % clean up non-integer solutions
y = ones(size(x));
for k = 2:9
y(:,:,k) = k; % multiplier for each depth k
end

S = x.*y; % multiply each entry by its depth


S = sum(S,3); % S is 9-by-9 and holds the solved puzzle
else
S = [];
end
end

 intlinprog: Là hàm giải quyết bài toán lập trình tuyến tính nguyên trong
MATLAB.
 f: Vector chi phí, mỗi phần tử đại diện cho chi phí liên quan đến một biến cụ thể.
 intcon: Vector chỉ rõ các biến nào là biến nguyên.
 Aeq, beq: Ma trận ràng buộc bằng và vector giá trị tương ứng để xác định các
điều kiện bằng.
 lb, ub: Các giới hạn dưới và trên cho các biến (trong trường hợp này là 0 và 1,
tạo thành các biến nhị phân).
 x: Vector lời giải trả về từ hàm intlinprog, nếu có lời giải.
 eflag: Một flag trạng thái để chỉ ra liệu bài toán đã được giải quyết thành công
hay không (eflag > 0 nếu có lời giải hợp lệ).
 if eflag > 0: Kiểm tra xem bài toán có lời giải hợp lệ không.
 reshape(x,9,9,9): Chuyển đổi vector lời giải x thành một mảng 3D 9x9x9, phù
hợp với bảng Sudoku.
 round(x): Làm tròn các giá trị của x để loại bỏ các phần thập phân, chỉ cần thiết
nếu thuật toán trả về giá trị không chính xác do sai số tính toán.
 ones(size(x)): Tạo một mảng cùng kích thước với x với tất cả các giá trị là 1.
 for k = 2:9: Vòng lặp qua từng "tầng" thứ 2 đến 9 của y, thiết lập mỗi tầng với
giá trị của số tương ứng. Điều này tạo ra các bội số cho mỗi số trong bảng
Sudoku.
 *x.y: Nhân từng phần tử của x với bội số tương ứng của nó trong y. Điều này
chuyển từ biểu diễn nhị phân của lời giải (trong đó chỉ có một phần tử 1 cho mỗi
số trong mỗi ô) thành giá trị số thực tương ứng.
 sum(S,3): Tính tổng theo chiều thứ ba (tức là tổng các số trong từng ô), tạo ra
một ma trận 9x9 cuối cùng chứa lời giải Sudoku.
 Nếu không có lời giải hợp lệ ( eflag <= 0), S sẽ là một mảng rỗng, biểu thị không có
lời giải có thể.

Như vậy, đoạn code này chịu trách nhiệm không chỉ giải quyết bài toán Sudoku mà còn
chuyển đổi lời giải thành định dạng có thể sử dụng, kiểm tra xem lời giải có phù hợp
hay không, và cuối cùng là cung cấp lời giải dưới dạng bảng Sudoku 9x9.

a = [
5, 3, 0, 0, 7, 0, 0, 0, 0;
6, 0, 0, 1, 9, 5, 0, 0, 0;
0, 9, 8, 0, 0, 0, 0, 6, 0;
8, 0, 0, 0, 6, 0, 0, 0, 3;
4, 0, 0, 8, 0, 3, 0, 0, 1;
7, 0, 0, 0, 2, 0, 0, 0, 6;
0, 6, 0, 0, 0, 0, 2, 8, 0;
0, 0, 0, 4, 1, 9, 0, 0, 5;
0, 0, 0, 0, 8, 0, 0, 7, 9
];

clc;flag=0;
for i=1:9
for k=1:9
if a(i,k)>0
c=[i,k,a(i,k)]
flag=1;
break
end
end
if (flag==1)
break
end
end
for i=1:9
for k=1:9
if a(i,k)>0
b=[i,k,a(i,k)]
c=[b;c]
end
end
end

drawSudoku1(c)
type sudokuEngine
S=sudokuEngine(c)
drawSudoku1(S)

Ma trận A là ma trạn đề bài ban đầu , ma trận C là một ma trận Nx3 để cùng kích cỡ
với ma trận B trong drawsudoku1 gồm các hàng chứa 3 cột và các giá trị lần lượt của
nó trong hàng là (vị trí hàng, vị trí cột , giá trị) của ô trong ma trận A khi nó lớn
hơn 0 . đặt biến flag để dừng
1. Duyệt qua ma trận a để tìm ô chưa điền đầu tiên:
o Sử dụng hai vòng lặp for để duyệt qua từng phần tử của ma trận a.
o Nếu tìm thấy ô có giá trị khác 0, lưu lại tọa độ của ô đó (dòng và cột) vào biến c.
o Đặt cờ flag thành 1 để kết thúc việc duyệt.
2. Duyệt lại ma trận a để lấy tất cả các ô đã điền:
o Sử dụng hai vòng lặp for khác để duyệt qua từng phần tử của ma trận a.
o Nếu tìm thấy ô có giá trị khác 0, lưu lại tọa độ của ô đó và giá trị của nó vào biến b.
o Thêm tọa độ và giá trị của ô vào biến c.

You might also like