Giải thuật DiJkstra cho Sortest path Routing
Trang 2PHẦN 2:
TRÌNH BÀY ĐỀ TÀI NGHIÊN CỨU
ỨNG DỤNG THUẬT TOÁN DIJKSTRA TRONG SHORTEST PATH ROUTING
Chương 1 Mô tả đề tài và vấn đề liên quan
1.1.Định tuyến trong mạng thông tin:
1.a.Định tuyến (routing):
Định tuyến là quá trình chọn lựa các đường đi trên một mạng máy tính để gửi
dữ liệu qua đó Việc định tuyến được thực hiện cho nhiều loại mạng, trong đó có mạng điện thoại, liên mạng, Internet, mạng giao thông
Định tuyến chỉ ra hướng, sự di chuyển của các gói (dữ liệu) được đánh địa chỉ
từ mạng nguồn của chúng, hướng đến đích cuối thông qua các node trung gian Thiết
bị phần cứng chuyên dùng được gọi là router (bộ định tuyến) Tiến trình định tuyến thường chỉ hướng đi dựa vào bảng định tuyến, đó là bảng chứa những lộ trình tốt nhấtđến các đích khác nhau trên mạng Vì vậy việc xây dựng bảng định tuyến, được tổ chức trong bộ nhớ của router, trở nên vô cùng quan trọng cho việc định tuyến hiệu quả
Routing khác với bridging (bắc cầu) ở chỗ trong nhiệm vụ của nó thì các cấu trúc địa chỉ gợi nên sự gần gũi của các địa chỉ tương tự trong mạng, qua đó cho phép nhập liệu một bảng định tuyến đơn để mô tả lộ trình đến một nhóm các địa chỉ Vì thế,routing làm việc tốt hơn bridging trong những mạng lớn, và nó trở thành dạng chiếm
ưu thế của việc tìm đường trên mạng internet
1.b Các lớp thuật toán định tuyến:
Thuật toán vector (distance-vector routing protocol):
Thuật toán này dùng thuật toán Bellman-Ford Nó chỉ định một con số, gọi là chi phí (hay trọng số), cho mỗi một liên kết giữa các node trong mạng Các node sẽ gửi thông tin từ điểm A đến điểm B qua đường đi mang lại tổng chi phí thấp nhất (là tổng các chi phí của các kết nối giữa các node được dùng)
Thuật toán hoạt động với những hành động đơn giản Khi một node khởi độnglần đầu, nó chỉ biết các node kề trực tiếp với nó, và chi phí trực tiếp để đi đến đó
Trang 3(thông tin, danh sách của các đích, tổng chi phí của từng node, và bước kế tiếp để gửi
dữ liệu đến đó tạo nên bảng định tuyến, hay bảng khoảng cách) Mỗi node, trong một tiến trình, gửi đến từng “hàng xóm” tổng chi phí của nó để đi đến các đích mà nó biết.Các node “hàng xóm” phân tích thông tin này, và so sánh với những thông tin mà chúng đang “biết”; bất kì điều gì cải thiện được những thông tin chúng đang có sẽ được đưa vào các bảng định tuyến Đến khi kết thúc, tất cả các node trên mạng sẽ tìm
ra bước truyền kế tiếp tối ưu đến tất cả mọi đích, và tổng chi phí tốt nhất
Thuật toán trạng thái kết nối (Link-state routing protocols):
Khi áp dụng các thuật toán trạng thái kết nối, mỗi node sử dụng cơ sở dữ liệu của nó như là một bản đồ của mạng với dạng đồ thị Để làm để làm điều này, mỗi node phát đi tới tổng thể mạng những thông tin về các node khác mà nó có thể kết nốiđược, và từng node góp thông tin một cách độc lập vào bản đồ Sử dụng bản đồ này, mỗi router sau đó sẽ quyết định về tuyến đường tốt nhất từ nó đến mọi node khác
Các router sẽ trao đổi gói tin LSA với những router khác Đây là những gói tinnhỏ, chứa thông tin về các router Mỗi router sẽ dựa vào LSAs này để tạo ra
topological database, sử dụng giải thuật SPF (Short Path First) để tìm ra đường đi Mỗi router đều xác định được chính xác topology của mạng Chính vì vậy router sẽ đưa ra quyết định để đưa packet đến đích tốt hơn Mỗi router trong mạng sẽ báo cáo trạng thái của nó, các link nối trực tiếp và trạng thái của mỗi link Router sẽ nhân bản thông tin này tới tất cả các router trên mạng Cuối cùng tất cả các router trên mạng đều có cái nhìn giống nhau về topology mạng
Thuật toán làm theo cách này là thuật toán Dijkstra (thuật toán mà ta sẽ tìm hiểu và ứng dụng), bằng cách xây dựng cấu trúc dữ liệu khác, dạng cây, trng đó node hiện tại là gốc, và chứa mọi node khác trong mạng Bắt đầu với một cây ban đầu chỉ chứa chính nó Sau đó lần lượt từ tập các node chưa được thêm vào cây, nó sẽ thêm node có chi phí thấp nhất để đến một node đã có trên cây Tiếp tục quá trình đến khi mọi node đều được thêm Cây này sau đó phục vụ để xây dựng bảng định tuyến, đưa
ra bước truyền kế tiếp tối ưu,… để từ một node đến bất kì node khác trên mạng
Thuật toán định tuyến bằng trạng thái kết nối phản ứng nhanh nhạy hơn, và trong một khoảng thời gian có hạn, đối với sự thay đổi kết nối Ngoài ra, những gói được gửi qua mạng trong định tuyến bằng trạng thái kết nối thì nhỏ hơn những gói dùng trong định tuyến bằng vector
Trang 41.2.Giao thức định tuyến:
Giao thức định tuyến được dùng trong khi thi hành thuật toán định tuyến để thuận tiện cho việc trao đổi thông tin giữa các mạng, cho phép các router xây dựng bảng định tuyến một cách linh hoạt Trong một số trường hợp, giao thức định tuyến
có thể tự chạy đè lên giao thức đã được định tuyến
Danh sách các giao thức định tuyến:
2.a.Giao thức định tuyến trong:
Router Information Protocol (RIP)
Open Shortest Path First (OSPF)
Intermediate System to Intermediate System (IS-IS)
Interior Gateway Routing Protocol (IGRP) (thuộc sở hữu của Cisco)
Enhanced IGRP (EIGRP) (thuộc sở hữu của Cisco)
2.b.Giao thức định tuyến ngoài:
Exterior Gateway Protocol (EGP)
Border Gateway Protocol (BGP)
Constrained Shortest Path First (CSPF)
1.3.Lý thuyết Graph:
Một Graph G, được định nghĩa bởi tập các đỉnh V và tập hợp các cạnh E Các đỉnh thường được gọi là các nút (node) và chúng biểu diễn vị trí (ví dụ một điểm chứalưu lượng hoặc một khu vực chứa thiết bị truyền thông) Các cạnh được gọi là các liênkết và chúng diễn biến phương tiện truyền thông Graph có thể được biểu diễn như sau:
G=(V,E)
Trang 5
Hình 1.Một Graph đơn giản.
Mặc dù theo lý thuyết, V có thể là tập hợp rỗng hoặc không có xác định nhưngthông thường V là tập hợp xác định khác rỗng, nghĩa là có thể biểu diễn
e=(v,v) hoặc e=(i,k)
Một liên kết gọi là đi tới một nút nếu đó là một trong hai điểm cuối của liên kết Nút i và k gọi là kề nhau nếu tồn tại một liên kết (i,k) giữa chúng Những nút như vậy được xem là các nút “hàng xóm” Bậc của nút là số lượng liên kết đi tới nút hya là
số lượng nút hàng xóm
Một liên kết có thể có hai hướng Khi đó thứ tự của các nút là không có ý nghĩa Ngược lại thứ tự các nút có ý nghĩa Trong trường hợp thứ tự các nút có ý nghĩa, một liên kết có thể được xem như là một cung và được định nghĩa :
a=[v,v] hoặc a=[i,k]
k được gọi là cận kề hướng ra đối với i nếu một cung [i,k] tồn tại và bậc hướng ra của i là số lượng các cung như vậy
Một graph goi là một mạng nếu các liên kết và các nút có mặt trong liên kết cócác thuộc tính (chẳng hạn như độ dài, dung lượng, loại,…) Các mạng được sử dụng
để mô hình các vấn đề cần quan tâm trong truyền thông, các thuộc tính riêng biệt của các nút và liên kết thì liên quan đến các vấn đề cụ thể trong truyền thông
Trang 6Một graph có các liên kết gọi là graph vô hướng, tuy nhiên một graph vô hướng, tuy nhiên một graph có các cung gọi là graph hữu hướng Một graph hữu hướng có thể có cả các liên kết vô hướng Thông thường, các graph được giả sử là vô hướng, hoặc sự phân biệt đó là không có ý nghĩa.
Có thể có khả năng xảy ra hiện tượng xuất hiện nhiều hơn một liên kết giữa cùng một cặp nút Những liên kết như vậy gọi là các liên kết song song Một graph có liên kết song song gọi là một multigraph
Cũng có khả năng xuất hiện các liên kết giữa một nút nào đó và chính nút đó Những liên kết đó được gọi là các self loop Một graph không có các liên kết song song hoặc các self loop gọi là một graph đơn giản
Chương 2 Lý thuyết nghiên cứu
2.1.Định tuyến đường dẫn ngắn nhất (Shortest Path
Routing):
Bài toán tìm đường đi ngắn nhất là một bài toán khá quan trọng trong quá trình thiết kế và phân tích mạng Hầu hết các bài toán định tuyến có thể giải quyết nhưgiải quyết bài toán tìm đường đi ngắn nhất khi một “độ dài” thích hợp được gắn vào mỗi cạnh (hoặc cung) trong mạng Trong khi các thuật toán thiết kế thì cố gắng tìm kiếm cách tạo ra các mạng thỏa mãn tiêu chẩn độ dài đường đi
Bài toán đơn giản nhất của loại toán này là tìm đường đi ngắn nhất giữa hai nút cho trước Loại bài toán này có thể là bài toán tìm đường đi ngắn nhất từ một nút tới tất cả các nút còn lại, tương đương bài toán tìm đường đi ngắn nhất từ tất cả các điểm đến một điểm Đôi khi đòi hỏi phải tìm đường đi ngắn nhất giữa tất cả các cặp nút
Ta xét các graph hữu hướng và giả sử rằng đã biết độ dài của một cung giữa mỗi cặp nút i và j là l Các độ dài này không cần phải đối xứng Khi một cung không tồn tại thì độ dài l được giả sử là rất lớn (chẳng hạn lớn gấp n lần độ dài cung lớn nhấttrong mạng) Chú ý rằng có thể áp dụng quá trình này cho các mạng vô hướng bằngcách thay mỗi cạnh bằng hai cung có cùng độ dài Ban đầu giả sử rằng l là dương hoàn toàn; sau đó giả thiết này có thể được thay đổi
Phần lớn các mạng chuyển mạch gói sử dụng các thuật toán khác nhau của phương pháp chọn tuyến đường ngắn nhất do lớp mạng thực hiện Một số mạng chọn
Trang 7tuyến theo cách thức tập trung, thiết lập đường dẫn giữa nút nguồn và nút đích ở trungtâm điều hành mạng NMC (Network Management Center) hay trung tâm điều khiển chọn tuyến RCC (Routing Control Center) rồi sau đó phân phối các thông tin chọn tuyến đến tất cả các nút chuyển mạch trong mạng Các nút mạng khác sử dụng cách thức phi tập trung hay còn gọi là cách thức phân bố, từng nút trao đổi thông tin chọn tuyến và giá thành với các nút khác trong mạng trên cơ sở tương tác cho đến khi các bảng định tuyến đáp ứng được yêu cầu định tuyến ngắn nhất.
2.2.Thuật toán Dijkstra:
Tất cả các thuật toán tìm đường đi ngắn nhất đều dựa vào việc lồng nhau giữa các đường đi ngắn nhất nghĩa là một nút k thuộc một đường đi ngắn nhất từ i tới j thì đường đi ngắn nhất từ i tới j sẽ bằng đường đi ngắn nhất từ i tới k kết hợp với đường
đi ngắn nhất từ j tới k Vì thế chúng ta có thể tìm đường đi ngắn nhất bằng công thức
đệ quy sau:
d = (d + d)
Hình 2 Các đường đi ngắn nhất lồng nhau.
Dxy là độ dài của đường đi ngắn nhất từ x tới y Khó khăn của cách tiếp cận này là phải có một cách khởi động đệ quy nào đó vì chúng ta không thể khởi động vớicác giá trị bất kỳ ở vế phải của phương trình trên
Thuật toán Dijkstra phù hợp cho việc tìm đường đi ngắn nhất từ một nút i tới tất cả các nút khác Bắt đầu bằng cách thiết lập
Trang 8tới thời điểm đó Xem d như là nhãn trên nút k Quá trình sử dụng một nút để triển khai các nhãn cho các nút khác gọi là quá trình quét nút.
Thực hiện tương tự, tiếp tục tìm các nút chưa được quét có nhãn bé nhất và quét nó Chú ý rằng, vì giả thiết tất cả các l đều dương do đó một nút không thể gán cho nút khác một nhãn bé hơn chính nhãn của nút đó Vì vậy, khi một nút được quét thì việc quét lại nó nhất thiết không bao giờ xảy ra Nếu nhãn trên một nút thay đổi, nút đó phải được quét lại
Ví dụ : xét mạng như hình sau, trên mỗi đường ghép nối có các trọng số tươngứng với giá thành của từng đường, để đơn giản ta coi các trọng số này theo cả hai chiều là như nhau, mặc dù trên thực tế chúng có thể khác nhau về giá trị Để chọn được đường dẫn ngắn nhất từ một nguồn tới tất cả các nút trong mạng, đòi hỏi phải cókiến thức về cấu hình tổng thể của mạng (danh sách các nút và các ghép nối giữa chúng) cũng như giá thành của từng đường nối Điều đó dẫn tới việc tính toán tập trung dựa trên thông tin đầy đủ lưu trong các cơ sở dữ liệu trung tâm (Central
Database)
Hình 3 Ví dụ một mạng.
Thuật toán được thực hiện theo từng bước, xây dựng mô hình cây đường ngắn nhất (Shortest Path Tree) có gốc tại nút nguồn (nút 1) Các đường dẫn ngắn nhất tới k nút khác được tính toán trong k bước, chúng được tập hợp lại trong tập N
Trang 9Coi D(v) là khoảng cách (tổng của các trọng số đường nối dọc theo đường dẫn) từ nút nguồn 1 tới nút v Coi l(i,j) là giá thành đã cho giữa 2 nút i và j Thuật toángồm 2 bước:
1.Bước khởi đầu
Đặt N={1} (tập N ban đầu chỉ gồm duy nhất 1 nút), với mỗi nút v N đặt D(v)=l(l,v), với các nút không nối trực tiếp với nút l ta coi giá thành bằng
2.Bước lặp
Tìm nút w không thuộc N sao cho D(w) là tối thiểu và bổ sung w vào tập N Sau đó thay D(v) cho toàn bộ các nút không thuộc N còn lại bằng cách tính:
D(v) min[D(v),D(w) + l(w,v)]
Bước này được lặp lại cho đến khi tất cả các nút đều có trong N
Sau khi thực hiện, ta lần lượt có được các bước mô tả bởi bảng thống kê sau:
Trang 10Hình 5.Bảng chọn tuyến cho nút 1.
Với thuật toán này ta có thể tính được các tuyến đường có đường dẫn ngắn nhất cho từng nút, cụ thể ta coi nút đó là nút nguồn rồi thực hiện các bước giải thuật
kể trên Trong trường hợp chọn tuyến theo phương thức tập trung, NMC sẽ gửi các bảng chọn tuyến cho từng nút một sau khi đã thiết lập xong, còn nếu mạng sử dụng phương thức phân bố thì từng nút phải tính lấy bảng định tuyến, cùng sử dụng các thông tin tổng thể như trên (được cung cấp bởi các nút lân cận hoặc bởi NMC) và chọn ra cây đường dẫn cho riêng nó
Chương 3.Xây dựng và thiết kế chương trình minh họa thuật toán Dijkstra
3.1.Xây dựng chương trình cơ bản tìm đường đi ngắn nhất bằng thuật toán Dijkstra:
Viết bằng ngôn nữa C:
Trang 11#include<conio.h>
#include<math.h>
#define filein “Dijkstra.inp”
#define fileout “Dijkstra.out”
Trang 123.2.Thiết kế phần mềm minh họa thuật toán Dijkstra:
Sử dụng bộ công cụ Eclipse lập trình với Java
Trang 13private static final long serialVersionUID = 1L;
// Dat cac Options ben trai man hinh ung dung
Button b1 = new Button( "Clear" );
Button b2 = new Button( "Run" );
Button b3 = new Button( "Step" );
Button b4 = new Button( "Reset" );
Button b5 = new Button( "Example" );
Button b6 = new Button( "Exit" );
Button b7 = new Button( "About" );
public boolean action(Event evt, Object arg) {
if (evt target instanceof Button) {
//Neu la JButton "Step" va Unlock thi thuc hien buoc dau tien va hien thi "Nextstep" len JButton,
//nguoc lai thi khong thuc hien
if (((String)arg).equals( "Step" )) {
if (! Locked ) {
b3 setLabel( "Next step" );
parent graphcanvas stepalg();
//Neu la JButton "Nextstep" thi thuc hien buoc tiep thep
if (((String)arg).equals( "Next step" )){
parent graphcanvas nextstep();
Trang 14//Neu la JButton "Clear" thi xoa graphics
Trang 15class Documentation extends Panel {
// Documentaion huong dan o phia tren man hinh ung dung
DocOptions docopt = new DocOptions(this);
DocText doctext = new DocText();
Documentation() {
setLayout(new BorderLayout(10, 10));
add( "West" , docopt );
add( "Center" , doctext );
}
}
class DocOptions extends Panel {
//Tao Choice huong dan ben trai man hinh ung dung
Choice doc = new Choice();
add(new Label( "DOCUMENTATION:" ));
doc addItem( "draw nodes" );
doc addItem( "remove nodes" );
doc addItem( "move nodes" );
doc addItem( "the startnode" );
doc addItem( "draw arrows" );
doc addItem( "change weights" );
doc addItem( "remove arrows" );
doc addItem( "clear / reset" );
doc addItem( "run algorithm" );
doc addItem( "step through" );
doc addItem( "example" );
doc addItem( "about" );
doc addItem( "exit" );
doc addItem( "all items" );
if (evt target instanceof Choice) {
String str=new String( doc getSelectedItem());
parent doctext showline(str);
}
return true;
}
Trang 16class DocText extends TextArea {
//TextDocumentation huong dan cho cac Choice va JButton
final String drawnodes = new String( "DRAWING NODES:\n" +
"Draw a node by clicking the mouse on the screen
application.\n\n" );
final String rmvnodes = new String( "REMOVE NODES:\n" +
"To remove a node press <ctrl> and click on the node.\n" + "You can not remove the startnode.\n" +
"Select another startnode, then you can remove the node.\n\ n" );
final String mvnodes = new String( "MOVING NODES\n" +
"To move a node press <Shift>, click on the node,\nand drag
it to" +
" its new position.\n\n" );
final String startnode = new String( "STARTNODE:\n" +
"The startnode is blue, other nodes are grey.\n" +
"The first node you draw on the screen will be the
startnode.\n" +
"To select another startnode press <ctrl>, click on the startnode,\n" +
"and drag the mouse to another node.\n" +
"To delete the startnode, first select another startnode, and then" +
"\nremove the node the usual way.\n\n" );
final String drawarrows = new String( "DRAWING ARROWS:\n" +
"To draw an arrow click mouse in a node," +
"and drag it to another node.\n\n" );
final String weight = new String( "CHANGING WEIGHTS:\n" +
"To change the weight of an arrow, click on the arrowhead and drag\n" +
"it along the arrow.\n\n" );
final String rmvarrows = new String( "REMOVE ARROWS:\n" +
"To remove an arrow, change its weight to 0.\n\n" );
final String clrreset = new String( "<CLEAR> BUTTON: " +
"Remove the current graph from the screen.\n" +
"<RESET> BUTTON: " +
"Remove the results of the algorithm from the graph,\n" + " and unlock screen.\n\n" );
final String runalg = new String( "<RUN> BUTTON: " +
"Run the algorithm on the graph, there will be a time\n" + "delay of +/- 1 second between steps.\n" +
"To run the algorithm slower, use <STEP>.\n" );
final String step = new String( "<STEP> BUTTON: " +
"An opportunity to step through the algorithm.\n" );
final String example = new String( "<EXAMPLE> BUTTON: " +
Trang 17"Displays a default graph on the screen for you.\n" +
"You can then use <STEP> or <RUN>\n" );
final String exitbutton = new String( "<EXIT> BUTTON: " +
"Only works if applet is run with appletviewer.\n" );
final String aboutbutton = new String( "<ABOUT> BUTTON: " +
"Show about Dijkstra program information.\n" );
final String toclose = new String( "ERROR: " +
"This position is to close to another node/arrow.\n" );
final String done = new String( "Algorithm has finished, " +
"follow green arrows from startnode to any node " +
"to get\nthe shortest path to " +
"the node The length of the path is written in the node.\n"
+
"press <RESET> to reset the graph, and unlock the
screen." );
final String some = new String( "Algorithm has finished, " +
"follow green arrows from startnode to any node " +
"to get\nthe shortest path to " +
"the node The length of the path is written in the node.\n"
final String none = new String( "Algorithm has finished, " +
"there are no nodes reachable from the start node.\n" +
"press <RESET> to reset the graph, and unlock the screen." );
final String maxnodes = new String( "ERROR: " +
"Maximum number of nodes reached!\n\n" );
final String info = new String( "DOCUMENTATION:\n" +
"You can scroll through the documentation or get
documentation\n" +
"on a specific " +
"item by selecting the item on the left.\nSelecting <All items> " +
"brings you back " +
" to the scrolling text.\n\n" );
final String locked = new String( "ERROR: " +
"Keyboard/mouse locked for this action.\n" +
"Either press <NEXT STEP> or <RESET>.\n" );
final String doc = info + drawnodes + rmvnodes + mvnodes +
startnode + drawarrows + weight + rmvarrows + clrreset + runalg + step + example + aboutbutton +
Trang 18}
public void showline(String str) {
if (str.equals( "draw nodes" )) setText( drawnodes );
else if (str.equals( "remove nodes" )) setText( rmvnodes );
else if (str.equals( "move nodes" )) setText( mvnodes );
else if (str.equals( "the startnode" )) setText( startnode );
else if (str.equals( "draw arrows" )) setText( drawarrows );
else if (str.equals( "change weights" )) setText( weight );
else if (str.equals( "remove arrows" )) setText( rmvarrows );
else if (str.equals( "clear / reset" )) setText( clrreset );
else if (str.equals( "run algorithm" )) setText( runalg );
else if (str.equals( "step through" )) setText( step );
else if (str.equals( "example" )) setText( example ); else if (str.equals( "exit" )) setText( exitbutton ); else if (str.equals( "about" ))
setText( aboutbutton );
else if (str.equals( "all items" )) setText( doc );
else if (str.equals( "toclose" )) setText( toclose );
else if (str.equals( "done" )) setText( done );
else if (str.equals( "locked" )) setText( locked );
else if (str.equals( "maxnodes" )) setText( maxnodes ); else if (str.equals( "none" )) setText( none ); else if (str.equals( "some" )) setText( some );
JPanel jp1 =new JPanel();
JPanel jp2 =new JPanel(new GridLayout(3,1));
Trang 19JPanel jp3 =new JPanel();
ImageIcon img =new
ImageIcon(this.getClass().getResource( "/nhanntv/nhanntv1.png" ));
//tao JLabel
JLabel jlb1 =new JLabel( img );
JLabel jlb2 =new JLabel( "************Program Java
GridBagLayout gb =new GridBagLayout();
GridBagConstraints gbc =new GridBagConstraints();
private static final long serialVersionUID = 1L;
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getSource()== jb ){
this.dispose();
} }
public void addComponent(Component c,int row,int col,int
nrow,int ncol){
gbc gridy =row; // toa do y
gbc gridx =col; // toa do x
gbc gridheight =nrow; // so dong chiem
gbc gridwidth =ncol; // so cot chiem
Trang 20Class GraphCanvas là Class đồ họa của chương trình, chứa các thuật toán giải quyết việc tìm đường đi ngắn nhất trong mạng (Shortest Path Routing), các phương thức để vẽ một mạng, xây dựng và tìm đường, đưa ra kết quả dưới dạng đồ họa cho giải thuật Dijkstra.
class GraphCanvas extends Canvas implements Runnable {
// drawing area for the graph
final int MAXNODES = 20;
final int MAX = MAXNODES +1;
final int NODESIZE = 26;
final int NODERADIX = 13;
final int DIJKSTRA = 1;
// basic graph information
Point node [] = new Point[ MAX ]; // node
int weight [][] = new int[ MAX ][ MAX ]; // weight of arrow
Point arrow [][] = new Point[ MAX ][ MAX ]; // current position of arrowhead
Point startp [][] = new Point[ MAX ][ MAX ]; // start and
Point endp [][] = new Point[ MAX ][ MAX ]; // endpoint of arrow
float dir_x [][] = new float[ MAX ][ MAX ]; // direction of arrow
float dir_y [][] = new float[ MAX ][ MAX ]; // direction of arrow
// graph information while running algorithm
boolean algedge [][] = new boolean[ MAX ][ MAX ];
int dist [] = new int[ MAX ];
int finaldist [] = new int[ MAX ];
Color colornode [] = new Color[ MAX ];
boolean changed [] = new boolean[ MAX ]; // indicates distance change during algorithm
// information used by the algorithm to find the next
// node with minimum distance
int mindist , minnode , minstart , minend ;
int numnodes =0; // number of nodes
Trang 21int emptyspots =0; // empty spots in array node[] (due to node deletion)
int startgraph =0; // start of graph
int hitnode ; // mouse clicked on or close to this node
int node1 , node2 ; // numbers of nodes involved in current action
Point thispoint =new Point(0,0); // current mouseposition
Point oldpoint =new Point(0, 0); // previous position of node being moved
// current action
boolean newarrow = false;
boolean movearrow = false;
boolean movestart = false;
boolean deletenode = false;
boolean movenode = false;
boolean performalg = false;
boolean clicked = false;
// fonts
Font roman = new Font( "TimesRoman" , Font.BOLD, 12);
Font helvetica = new Font( "Helvetica" , Font.BOLD, 15);
FontMetrics fmetrics = getFontMetrics( roman );
int = (int) fmetrics getHeight()/3;
// for double buffering
private Image offScreenImage ;
private Graphics offScreenGraphics ;
private Dimension offScreenSize ;
// for run option
Thread algrthm ;
// current algorithm, (in case more algorithms are added)
int algorithm ;
// algorithm information to be displayed in documetation panel
String showstring = new String( "" );
boolean stepthrough =false;
// locking the screen while running the algorithm
boolean Locked = false;
public void lock() {
// lock screen while running an algorithm
Locked =true;
}
Trang 22public void unlock() {
Locked =false;
}
public void start() {
if ( algrthm != null) algrthm resume () }
public void init() {
for (int i=0;i< MAXNODES ;i++) {
colornode [i]=Color.gray;
for (int j=0; j< MAXNODES ;j++)
algedge [i][j]=false;
}
colornode [ startgraph ]=Color.blue;
performalg = false;
}
public void clear() {
// removes graph from screen
startgraph =0;
numnodes =0;
emptyspots =0;
init();
for(int i=0; i< MAXNODES ; i++) {
node [i]=new Point(0, 0);
for (int j=0; j< MAXNODES ;j++)
public void reset() {
// resets a graph after running an algorithm
public void runalg() {
// gives an animation of the algorithm
public void stepalg() {
// lets you step through the algorithm
Trang 23public void initalg() {
init();
for(int i=0; i< MAXNODES ; i++) {
dist [i]=-1;
finaldist [i]=-1;
for (int j=0; j< MAXNODES ;j++)
algedge [i][j]=false;
public void nextstep() {
// calculates a step in the algorithm (finds a shortest
// path to a next node).
finaldist [ minend ]= mindist ;
algedge [ minstart ][ minend ]=true;
colornode [ minend ]=Color.green;
// build more information to display on documentation panel
step ++;
repaint();
}
public void stop() {
if ( algrthm != null) algrthm suspend ()
}
public void run() {
for(int i=0; i<( numnodes - emptyspots ); i++){
public void showexample() {
// draws a default graph on the screen
for(int i=0; i< MAXNODES ; i++) {
node [i]=new Point(0, 0);
for (int j=0; j< MAXNODES ;j++)
weight [i][j]=0;
}
w=this.size () width /8;
h=this.size () height /8;
node [0]=new Point(2*w, 4*h);
node [1]=new Point(3*w, 2*h);
node [2]=new Point(5*w, 2*h);
node [3]=new Point(6*w, 4*h);
node [4]=new Point(5*w, 6*h);
node [5]=new Point(3*w, 6*h);
Trang 24weight [0][1]=4; weight [1][0]=4; weight [0][5]=2; weight [5] [0]=2;
weight [1][2]=3; weight [2][1]=3; weight [1][4]=3; weight [4] [1]=3;
weight [2][3]=2; weight [3][2]=2;
weight [3][4]=1; weight [4][3]=1;
weight [4][5]=3; weight [5][4]=3;
for (int i=0;i< numnodes ;i++)
for (int j=0;j< numnodes ;j++)
thispoint = new Point(x,y);
colornode [ startgraph ]=Color.gray;
else if (nodehit(x, y, NODESIZE )) {
// draw a new arrow
Trang 25// take the next available spot in the array
for (i=0;i< numnodes ;i++)
if ( node [i] x ==-100) break;
node [i]=new Point(x, y);
public boolean mouseDrag(Event evt, int x, int y) {
if ( (! Locked ) && clicked ) {
if ( movenode ) {
// move node and adjust arrows coming into/outof the node
node [ node1 ]=new Point(x, y);
for (int i=0;i< numnodes ;i++) {
if ( weight [i][ node1 ]>0) {
arrowupdate(i, node1 , weight [i][ node1 ]);
}
if ( weight [ node1 ][i]>0) {
arrowupdate( node1 , i, weight [ node1 ][i]);
}
}
repaint();
}
else if ( movestart || newarrow ) {
thispoint = new Point(x, y);
public boolean mouseUp(Event evt, int x, int y) {
if ( (! Locked ) && clicked ) {
if ( movenode ) {
// move the node if the new position is not to close to
// another node or outside of the panel
node [ node1 ]=new Point(0, 0);
Trang 26if ( nodehit(x, y, 50) || (x<0) || (x>this.size () width )
else node [ node1 ]=new Point(x, y);
for (int i=0;i< numnodes ;i++) {
if ( weight [i][ node1 ]>0)
arrowupdate(i, node1 , weight [i][ node1 ]);
if ( weight [ node1 ][i]>0)
arrowupdate( node1 , i, weight [ node1 ][i]);
arrowupdate( node1 , node2 , 50);
if ( weight [ node2 ][ node1 ]>0) {
arrowupdate( node2 , node1 , weight [ node2 ][ node1 ]); }
parent documentation doctext showline( "change weights" );
public boolean nodehit(int x, int y, int dist) {
// checks if you hit a node with your mouseclick
for (int i=0; i< numnodes ; i++)
if ( (x- node [i] x )*(x- node [i] x ) +
(y- node [i] y )*(y- node [i] y ) < dist*dist ) { hitnode = i;
return true;
Trang 27}
return false;
}
public boolean arrowhit(int x, int y, int dist) {
// checks if you hit an arrow with your mouseclick
for (int i=0; i< numnodes ; i++)
for (int j=0; j< numnodes ; j++) {
if ( ( weight [i][j]>0 ) &&
(Math.pow(x-arrow [i][j] x , 2) +
Math.pow(y-arrow [i][j] y, 2) < Math.pow(dist, 2) )
public void nodedelete() {
// delete a node and the arrows coming into/outof the node
node [ node1 ]=new Point(-100, -100);
for (int j=0;j< numnodes ;j++) {
public void changeweight(int x, int y) {
// changes the weight of an arrow (edge in the graph), when a user drags
// the arrowhead over the edge connecting node node1 and node2.
// direction of the arrow
int diff_x = (int)(20* dir_x [ node1 ][ node2 ]);
int diff_y = (int)(20* dir_y [ node1 ][ node2 ]);
// depending on the arrow direction, follow the x, or the y // position of the mouse while the arrowhead is being dragged
boolean follow_x=false;
if (Math.abs(endp [ node1 ][ node2 ] x startp [ node1 ][ node2 ] x ) >
Math.abs(endp [ node1 ][ node2 ] y startp [ node1 ] [ node2 ] y ) ) {
follow_x = true;
}
// find the new position of the arrowhead, and calculate
// the corresponding weight
if (follow_x) {
int hbound = Math.max(startp [ node1 ][ node2 ] x ,
endp [ node1 ][ node2 ] x)-Math.abs(diff_x);
int lbound = Math.min(startp [ node1 ][ node2 ] x ,
endp [ node1 ][ node2 ] x)+Math.abs(diff_x);
// arrow must stay between the nodes
if (x<lbound) { arrow [ node1 ][ node2 ] x =lbound; }
else if (x>hbound) { arrow [ node1 ][ node2 ] x =hbound; }
Trang 28else arrow [ node1 ][ node2 ] x =x;
arrow [ node1 ][ node2 ] y
( arrow [ node1 ][ node2 ] x startp [ node1 ][ node2 ] x ) * ( endp [ node1 ][ node2 ] y startp [ node1 ][ node2 ] y )/
( endp [ node1 ][ node2 ] x startp [ node1 ][ node2 ] x ) +
startp [ node1 ][ node2 ] y
// new weight
weight [ node1 ][ node2 ]=
Math.abs(arrow [ node1 ][ node2 ] x startp [ node1 ][ node2 ] x
int hbound = Math.max(startp [ node1 ][ node2 ] y ,
endp [ node1 ][ node2 ] y)-Math.abs(diff_y);
int lbound = Math.min(startp [ node1 ][ node2 ] y ,
endp [ node1 ][ node2 ] y)+Math.abs(diff_y);
if (y<lbound) { arrow [ node1 ][ node2 ] y =lbound; }
else if (y>hbound) { arrow [ node1 ][ node2 ] y =hbound; }
else arrow [ node1 ][ node2 ] y =y;
arrow [ node1 ][ node2 ] x
( arrow [ node1 ][ node2 ] y startp [ node1 ][ node2 ] y ) * ( endp [ node1 ][ node2 ] x startp [ node1 ][ node2 ] x )/
( endp [ node1 ][ node2 ] y startp [ node1 ][ node2 ] y ) +
startp [ node1 ][ node2 ] x
weight [ node1 ][ node2 ]=
Math.abs(arrow [ node1 ][ node2 ] y startp [ node1 ][ node2 ] y
diff_y)*
100/(hbound-lbound);
}
}
public void arrowupdate(int p1, int p2, int w) {
// make a new arrow from node p1 to p2 with weight w, or change
// the weight of the existing arrow to w, calculate the resulting
// position of the arrowhead
// distance between p1 and p2
l = (float)( Math.sqrt((float)(dx*dx + dy*dy)));
dir_x [p1][p2]=dx/l;
dir_y [p1][p2]=dy/l;
// calculate the start and endpoints of the arrow,
// adjust startpoints if there also is an arrow from p2 to p1
if ( weight [p2][p1]>0) {
startp [p1][p2] = new Point((int)( node [p1] x -5* dir_y [p1] [p2]),
Trang 29(int)( node [p1] y +5* dir_x [p1][p2])); endp [p1][p2] = new Point((int)( node [p2] x -5* dir_y [p1][p2]),
(int)( node [p2] y +5* dir_x [p1][p2]));
}
else {
startp [p1][p2] = new Point( node [p1] x , node [p1] y );
endp [p1][p2] = new Point( node [p2] x , node [p2] y );
}
// range for arrowhead is not all the way to the
start/endpoints
int diff_x = (int)(Math.abs(20*dir_x [p1][p2]));
int diff_y = (int)(Math.abs(20*dir_y [p1][p2]));
// calculate new x-position arrowhead
if ( startp [p1][p2] x endp [p1][p2] x ) {
arrow [p1][p2] = new Point( endp [p1][p2] x + diff_x +
(Math.abs(endp [p1][p2] x startp [p1][p2] x ) - 2*diff_x )*
(100-w)/100 , 0);
}
else {
arrow [p1][p2] = new Point( startp [p1][p2] x + diff_x +
(Math.abs(endp [p1][p2] x startp [p1][p2] x ) - 2*diff_x )*
w/100, 0);
}
// calculate new y-position arrowhead
if ( startp [p1][p2] y endp [p1][p2] y ) {
arrow [p1][p2] y endp [p1][p2] y + diff_y +
(Math.abs(endp [p1][p2] y startp [p1][p2] y ) - 2*diff_y )*
(100-w)/100;
}
else {
arrow [p1][p2] y startp [p1][p2] y + diff_y +
(Math.abs(endp [p1][p2] y startp [p1][p2] y ) - 2*diff_y )*
w/100;
}
}
public String intToString(int i) {
char c=(char)((int) 'a' +i);
return "" +c;
}
public final synchronized void update(Graphics g) {
// prepare new image offscreen
offScreenGraphics setColor(Color.white);
offScreenGraphics fillRect(0, 0, d width , d height );
paint( offScreenGraphics );
g.drawImage( offScreenImage , 0, 0, null);
Trang 30}
public void drawarrow(Graphics g, int i, int j) {
// draw arrow between node i and node j
int x1, x2, x3, y1, y2, y3;
// calculate arrowhead
x1= (int)( arrow [i][j] x - 3* dir_x [i][j] + 6* dir_y [i][j]);
x2= (int)( arrow [i][j] x - 3* dir_x [i][j] - 6* dir_y [i][j]);
x3= (int)( arrow [i][j] x + 6* dir_x [i][j]);
y1= (int)( arrow [i][j] y - 3* dir_y [i][j] - 6* dir_x [i][j]);
y2= (int)( arrow [i][j] y - 3* dir_y [i][j] + 6* dir_x [i][j]);
y3= (int)( arrow [i][j] y + 6* dir_y [i][j]);
int arrowhead_x[] = { x1, x2, x3, x1 };
int arrowhead_y[] = { y1, y2, y3, y1 };
// if edge already chosen by algorithm change color
if ( algedge [i][j]) g.setColor(Color.green);
// draw arrow
g.drawLine( startp [i][j] x , startp [i][j] y , endp [i][j] x ,
endp [i][j] y );
g.fillPolygon(arrowhead_x, arrowhead_y, 4);
// write weight of arrow at an appropriate position
int dx = (int)(Math.abs(7*dir_y [i][j]));
int dy = (int)(Math.abs(7*dir_x [i][j]));
String str = new String( "" + weight [i][j]);
g.setColor(Color.black);
if (( startp [i][j] x endp [i][j] x ) && ( startp [i][j] y >= endp [i] [j] y ))
g.drawString( str, arrow [i][j] x + dx, arrow [i][j] y - dy);
if (( startp [i][j] x >= endp [i][j] x ) && ( startp [i][j] y endp [i] [j] y ))
g.drawString( str, arrow [i][j] x - fmetrics stringWidth(str)
- dx ,
arrow [i][j] y - dy);
if (( startp [i][j] x endp [i][j] x ) && ( startp [i][j] y <= endp [i] [j] y ))
g.drawString( str, arrow [i][j] x -
fmetrics stringWidth(str) ,
arrow [i][j] y + fmetrics getHeight());
if (( startp [i][j] x <= endp [i][j] x ) && ( startp [i][j] y endp [i] [j] y ))
g.drawString( str, arrow [i][j] x + dx,
arrow [i][j] y + fmetrics getHeight() ); }
public void detailsDijkstra(Graphics g, int i, int j) {
// check arrow between node i and node j is amongst the arrows to
// choose from during this step of the algorithm
// check if node j has the next minimal distance to the startnode
if ( ( finaldist [i]!=-1) && ( finaldist [j]==-1) ) {
g.setColor(Color.red);
if ( ( dist [j]==-1) || ( dist [j]>=( dist [i]+ weight [i][j])) ) {
if ( ( dist [i]+ weight [i][j])< dist [j] ) {
Trang 31changed [j]=true;
numchanged ++;
}
dist [j] = dist [i]+ weight [i][j];
colornode [j]=Color.red;
if ( ( mindist ==0) || ( dist [j]< mindist ) ) {
public void endstepDijkstra(Graphics g) {
// displays current and final distances of nodes, sets the final distance
// for the node that had minimal distance in this step
// explains algorithm on documentation panel
for (int i=0; i< numnodes ; i++)
if ( ( node [i] x >0) && ( dist [i]!=-1) ) {
String str = new String( "" + dist [i]);
g.drawString(str, node [i] x -
(int) fmetrics stringWidth(str)/2 -1,
showstring = showstring + "have changed!\n" ;
else showstring = showstring + "has changed!\n" ;
showstring = showstring + "Node " + intToString( minend ) +
" has the minimum distance.\n" ; //check if there are other paths to minend
int newpaths=0;
for (int i=0; i< numnodes ; i++)