(Đăng ngày 29/08/2006) Trong phần này, chúng tôi xác định một vấn đề di động đơn giản và chỉ ra cách chúng tôi viết mã Java sử dụng OptimalGrid để nghiên cứu vấn đề.
Phần 5. Viết trình giải quyết vấn đề OptimalGrid
Giới thiệu
Trong phần này, chúng tôi xác định một vấn đề di động đơn giản và chỉ ra cách chúng tôi viết mã Java sử dụng OptimalGrid để nghiên cứu vấn đề.
Khi chúng tôi tiếp tục, chúng tôi sẽ cung cấp các liên kết đến mã nguồn Java đầy đủ cho các lớp Java mà chúng tôi mô tả. Nếu bạn đã tải xuống và cài đặt OptimalGrid, thì bạn cũng có thể truy cập JavaDoc cho hệ thống OptimalGrid. Nếu bạn đã cài đặt OptimalGrid
vào C: \ java , thì bạn có thể sử dụng địa chỉ URL sau:
tệp: // localhost / C: /java/grid/html/javadoc/index.html
Mô hình Eden
Đối với ví dụ của chúng tôi, chúng tôi sẽ sử dụng mô hình Eden cho sự phát triển của vi khuẩn. Trong bài toán của chúng ta, chúng ta có ba thực thể đại diện cho ba loại vi khuẩn (A, B và C) đang phát triển trong không gian hai chiều (petri Dish). Chúng tôi sử dụng hệ tọa độ Descartes nên các phần tử hoặc ô nhỏ nhất trong không gian này là hình vuông với các cạnh có độ dài đơn vị. Trong mô hình Eden, mỗi OPC đại diện cho một ô có thể chứa một thực thể đại diện cho một trong 3 loại vi khuẩn. Mỗi ô cũng chứa các phương pháp hoặc quy tắc mô tả cách các thực thể tương tác trên trang web và cách chúng lây lan hoặc truyền sang các trang web khác. Các thực thể chứa thông tin sắp tương tác với các thực thể khác. Trong ví dụ này, phương pháp tương tác khiến A ăn B, B ăn C và C ăn A. Phương pháp nhân giống mô tả cách thức lây lan của vi khuẩn. Việc lan truyền đến các vị trí hoặc ô lân cận yêu cầu mỗi ô cũng phải lưu trữ các con trỏ tới (gần nhất) hàng xóm. Các con trỏ này xác định một đồ thị và cùng với phương pháp truyền dẫn, thêm yêu cầu giao tiếp vào bài toán. Trong ví dụ, phương thức truyền gây ra, tại mỗi lần lặp lại, một thực thể tại trang web (i, j) lây lan sang các hàng xóm gần nhất của nó tại các trang web (i + 1, j), (i-1, j), (i, j +1), (i, j-1) mỗi cái với xác suất 0,5.
Chúng tôi sẽ nghiên cứu kết quả lây lan của vi khuẩn một cách trực quan. Hình 5 cho thấy tình trạng của ba loại vi khuẩn tại bốn thời điểm khác nhau.
Xác định lớp Java cho ô mô hình Eden
Bước đầu tiên là xác định một lớp Java xác định nội dung và các phương thức được sử dụng bởi OPC.
Xem danh sách Mã cho lớp OPCEden.
Đối với vấn đề này, chúng tôi sẽ triển khai một lớp OPCEden Java mở rộng lớp OPCAbstract. OPCAbstract chứa dữ liệu và hành vi cần thiết cho bất kỳ đối tượng OPC nào.
lớp công khai OPCEden mở rộng OPCAbstract
triển khai Serializable, Cloneable {
|
Một lớp OPCEden chứa hai phương thức được chạy ở mỗi lần lặp lại vấn đề.
- Lan truyền()
- localInteraction ()
Phương thức lan truyền () mô tả cách vi khuẩn lây lan. Việc lan truyền đến các vị trí hoặc ô lân cận yêu cầu mỗi ô cũng phải lưu trữ các con trỏ tới (gần nhất) hàng xóm. Những con trỏ này xác định một đồ thị và cùng với phương pháp lan truyền thêm yêu cầu giao tiếp vào bài toán. Trong ví dụ, phương pháp lan truyền khiến vi khuẩn tại vị trí (i, j) lây lan sang các vùng lân cận gần nhất của nó tại các vị trí (i + 1, j), (i-1, j), (i, j) +1), (i, j-1) mỗi với xác suất 0,4 (mô hình Eden cổ điển cho sự phát triển của vi khuẩn).
Phương thức localInteraction () khiến vi khuẩn A ăn B, B ăn C và C ăn A.
Khi sự cố được chạy với một lưới các máy được nối mạng, một hoặc nhiều hàng xóm của OPC có thể nằm trên một máy riêng biệt, nhưng điều đó là minh bạch đối với lớp OPCEden.
Xác định lớp Java cho thực thể Eden
Eden OPC có thể chứa những vi khuẩn cư trú đại diện cho một loại vi khuẩn thuộc một loại hoặc loài cụ thể (tức là A, B hoặc C) đang sống trong tế bào. Nó có thuộc tính foodID đại diện cho loại thức ăn (một loại vi khuẩn khác trong ví dụ về loài săn mồi này) mà nó sẽ ăn. Đối với mã ví dụ này, vi khuẩn A ăn B; B ăn C; và C ăn A. Trong các mô hình khác, các thực thể có thể đại diện cho chất lỏng, mật độ electron hoặc electron, ứng suất cục bộ, vi khuẩn, nhiệt, nhiệt độ, v.v. Đối với mô hình Eden của chúng tôi, chúng tôi sẽ định nghĩa một lớp Java, EntityEden , mô tả vi khuẩn .
Xem Danh sách mã cho lớp EntityEden.
public class EntityEden mở rộng EntityAbstract
triển khai Serializable, Cloneable {
|
Một lớp EntityEden sử dụng các biến phiên bản sau.
- _entityID ID của vi khuẩn này. Được kế thừa từ EntityAbstract
- _foodID ID của vi khuẩn mà vi khuẩn này sẽ ăn.
- _thực tế nếu vi khuẩn còn sống
- _propagationprob Xác suất vi khuẩn này sẽ truyền sang hàng xóm của nó
- _rgbColor Màu được gán cho vi khuẩn này. Điều này được kế thừa từ EntityAbstract và được sử dụng để biểu diễn vấn đề bằng đồ họa.
Định nghĩa lớp Java cho thuộc tính Eden
Một OPC Eden có thể chứa các thuộc tính đại diện cho các thuộc tính được gán cho OPC này. Các thuộc tính có thể là hằng số đàn hồi cục bộ, độ cứng cục bộ, độ dẫn điện cục bộ, độ dẫn nhiệt, nhiệt dung, v.v. Đối với mô hình Eden của chúng tôi, chúng tôi sẽ xác định PropertyEden mô tả sự điều chỉnh đối với xác suất vi khuẩn liên kết với OPC sẽ truyền sang các nước láng giềng của nó.
Xem danh sách Mã cho lớp PropertyEden.
Phương thức Eden model inherit ()
Các phần quan trọng của phương thức OPCEden.propagate () được hiển thị bên dưới.
Xem danh sách Mã cho OPCEden Tuyên truyền ().
Phương thức truyền () được truyền các tham số sau.
- int collectionIndex_ – Chỉ mục tới OPCCollection
- VppAbstract vpp_ – Tham chiếu đến VPP cho phần tử OPC này
- int iteration_ – Số lần lặp lại
- Random rnd_ – Trình tạo số ngẫu nhiên
công khai ArrayList được đồng bộ hóa truyền bá (int collectionIndex_,
VppAbstract vpp_, int iteration_, Ngẫu nhiên rnd_) {
|
Bây giờ nó sẽ nhận được danh sách tất cả các OPC lân cận.
ArrayList tempArray = this.getAllOPCNeighbors (collectionIndex_, vpp_);
|
Bây giờ nó sẽ lặp qua các OPC lân cận và đối với mỗi OPC thì gọi phương thức processNeighbor () sẽ xử lý việc truyền giữa OPC đó trở lại OPC hiện tại.
Iterator iter = tempArray.iterator ();
while (iter.hasNext ()) {
// lấy phần tử tập hợp
OPCEden OPCNeighbor = (OPCEden) iter.next ();
// truyền các thực thể hàng xóm sang newOccupants
processNeighbor (OPCNeighbor, newOccupants, vpp_, iteration_, rnd_);
} // trong khi hasNext
|
Bây giờ nó có trong newOccupants một danh sách các thực thể cạnh tranh. Chúng tôi sẽ trả về ArrayList mới này . Lưu ý rằng chúng tôi chưa lưu trữ nó trong OPC hiện tại vì khi chúng tôi xử lý OPC tiếp theo, nó sẽ xem OPC này như một người hàng xóm và chúng tôi muốn nó không thay đổi. Các ArrayList mà chúng ta trở về đây sẽ là một đầu vào cho localInteraction phương pháp.
trả về newOccupants;
|
Phương thức Eden model localInteration ()
Sau đây là đoạn mã quan trọng cho phương thức OPCEden localInteraction () .
Xem danh sách Mã cho OPCEden localInteraction ().
Phương thức localInteraction () được chuyển một tham chiếu đến VPP, số lần lặp và ArrayList của các đối tượng thực thể cạnh tranh thuộc OPC này do kết quả của phương thức truyền () .
công khai đồng bộ hóa void localInteraction (VppAbstract vpp_, \
int iteration_, ArrayList chiếm_) {
|
Bây giờ, nó sẽ xem xét danh sách các thực thể cạnh tranh và dựa trên quy tắc vi khuẩn (thực thể) ăn loại vi khuẩn nào, nó sẽ đưa ra chỉ một loại vi khuẩn còn lại. Nhớ lại! A ăn B, B ăn C, C ăn A.
// có người cư ngụ không?
if ((Occupants_! = null) && (Occupants_.size ()> 1)) {
// có, sau đó lặp qua chúng
for (int i = 0; i <Occupants_.size (); i ++) {
for (int j = 0; j <Occupants_.size (); j ++) {
if (i == j) tiếp tục;
EntityEden obj1 = (EntityEden) Occupants_.get (i);
EntityEden obj2 = (EntityEden) Occupants_.get (j);
// obj2._foodID chứa loại thực phẩm mà obj2 ăn.
// vì vậy nếu nó khớp với EntityID cho obj1, thì obj2 ăn obj1.
if (obj2.isAlive () && (obj2.getFoodID () == obj1.getEntityID ())) {
// vâng, thì obj1 đã chết
obj1.setAlive (sai);
}
} // cho j
} // cho tôi. Kiểm tra vòng lặp đầu tiên cho động vật ăn thịt
|
Bây giờ nó sẽ duyệt qua danh sách những người cư ngụ và loại bỏ những người đã chết.
for (Iterator iter = Occupants_.iterator (); iter.hasNext ();) {
EntityEden obj1 = (EntityEden) iter.next ();
if (! obj1.isAlive ()) {
// không, sau đó ghi lại sự thay đổi dân số và xóa nó
vpp _._ valueMonitor.accumulateValueData (iteration_, obj1.getEntityID (), -1);
iter.remove ();
}
} // lặp lại. Vòng lặp thứ hai loại bỏ những người cư ngụ đã chết
} // kết thúc nếu không rỗng hoặc trống
|
Bây giờ nó sẽ lưu danh sách các đối tượng EntityEden vào thể hiện OPCEden.
super.setOccupants (người chiếm_);
|
Lớp EntityEden
Sau đây là phần quan trọng của mã cho lớp EntityEden .
Xem thêm Danh sách mã cho lớp EntityEden.
public class EntityEden mở rộng EntityAbstract {
boolean riêng _dead = false;
private double _propagationProb;
private int _foodID = 0;
/ **
* Các loại vi khuẩn là TYPE_A, TYPE_B và TYPE_C
*
* TYPE_A ăn TYPE_B; TYPE_B ăn TYPE_C và TYPE_C ăn TYPE_A
* /
public static final int TYPE_A = 5;
public static final int TYPE_B = 3;
public static final int TYPE_C = 2;
/ **
* Các thực thể được xác định trước được VppEdenInitializer sử dụng để thiết lập
* điều kiện ban đầu
* /
public static final EntityEden ENTITY_A = new EntityEden (
TYPE_A, TYPE_B, 0,4);
public static final EntityEden ENTITY_B = new EntityEden (
TYPE_B, TYPE_C, 0,4);
public static final EntityEden ENTITY_C = new EntityEden (
TYPE_C, TYPE_A, 0,4);
/ **
*
* Construct và EntityEden với các giá trị mặc định.
* Hàm tạo công khai này là bắt buộc để hỗ trợ XML
* có thể tạo động từ tệp XML.
* /
public EntityEden () {
}
/ **
* Xây dựng một cá thể thực thể Eden mô tả một vi khuẩn.
* @param entityID_ Loại vi khuẩn TYPE_A, TYPE_B hoặc TYPE_C
* @param foodID_ Food: Loại vi khuẩn mà con này ăn
* @param kép lan truyềnProb_ Xác suất lan truyền
* /
public EntityEden (int entityID_, int foodID_, double tuyên truyềnProb_) {
_propProb = tuyên truyềnProb_;
_entityID = entityID_;
_alive = true;
_foodID = foodID_;
// xác định màu dựa trên loại
if (_entityID == TYPE_A) {
_rgbColor = Color.RED.getRGB ();
} else if (_entityID == TYPE_B) {
_rgbColor = Color.GREEN.getRGB ();
} else if (_entityID == TYPE_C) {
_rgbColor = Color.BLUE.getRGB ();
} khác {
Debug.error ("EntityEden:", "Thực thể không hợp lệ. EntityID =" + _ entityID);
}
}
|
Lớp EntityEden, tiếp tục
Hai phần tiếp theo hiển thị getXML và initFromXML phương pháp mà là một phần của mã cho EntityEden lớp.
Vì lớp entityEden đã thêm một số biến phiên bản mới ( _foodID và _propagationProb ), nó cần phải thêm những biến này vào XML đã tạo và có thể khởi tạo giá trị khi XML được đọc lại. Điều này được xử lý bởi getXML () và phương thức initFromXML () được hiển thị bên dưới. Hai phương thức này được yêu cầu trong EntityEden và PropertyEden vì chúng đã thêm các biến phiên bản duy nhất. Nếu OPCEdenđã thêm các biến cá thể, nó cũng sẽ yêu cầu các phương thức này. Nếu chúng không được bao gồm, XML được tạo và đọc bởi sự cố sẽ không hoàn chỉnh. Lưu ý rằng biến instance _dead không được chỉ định. Nó chỉ được sử dụng để chuyển trạng thái từ phương thức truyền () sang phương thức localInteraction () và không cần thiết để hiển thị trạng thái ở cuối khoảng thời gian.
/ ************************************************* *************************
** getXML () **
******************* /
/ **
*
* Tạo biểu diễn XML của một đối tượng thực thể
* được thêm vào EntityElement bởi XMLOPCCollectionWriter.
* Các phần tử này chứa mọi dữ liệu duy nhất cho một lớp
* mở rộng EntityAbstract (lớp này).
*
* Hỗ trợ XML sẽ tạo ra một cái gì đó giống như sau cho
* đối tượng EntityAbstract. Lưu ý rằng mã trong phương pháp này có
* đã thêm "food =" 3 "vào các thuộc tính.
*
*
*
*
*
*
*
*
* Phần tử này phải chứa tất cả dữ liệu duy nhất cho một lớp mở rộng
* entityAbstract. Điều đầu tiên khi triển khai phương thức getXML ()
* nên làm trong bất kỳ thực thể mở rộng lớp nào
* phương thức getXmlElement () từ lớp cha của nó để lấy cơ bản
* XML cho một thực thể trừu tượng.
*
* Sử dụng các thư viện xác định phần tử được xác định trong org.jdom
*
* @see com.ibm.almaden.smartgrid.EntityAbstract
*
*
* @returns entityEhiểu biểu diễn XML cho một lớp EntityEden
*
*
************************************************** *************************
* /
Phần tử công cộng getXML () {
// Đầu tiên nó phải gọi getXMLElement cho entityAbstract
Phần tử entityElement = super.getXmlElement ();
// bây giờ hãy thêm thuộc tính _foodID và _probProb vào XML.
entityElement.setAttribute (PROBABILITY, "" + this._propProb);
entityElement.setAttribute (FOOD_ID, "" + this._foodID);
return entityElement;
} // getXML ()
|
Thông tin thêm về lớp EntityEden
Đây là phương thức initFromXML ()
/ ************************************************* *************************
** initFromXML () **
******************* /
/ **
** Phương thức bắt buộc. Tạo một phiên bản EntityEden mới từ
* một biểu diễn XML của thực thể.
*
* Phương thức này khởi tạo một đối tượng EntityEden dựa trên
* XML được tạo bởi phương thức getXML ().
* Sử dụng dòng sau của XML, thể hiện EntityEden
* sẽ được tạo lại bao gồm giá trị "foodID" mà lớp này
* định nghĩa.
*
*
*
*
*
** Tạo một phiên bản EntityEden mới từ một phần tử XML
* Điều đầu tiên mà bất kỳ phương thức entity.initFromXML () nào phải làm
* là siêu gọi. initCommonSubsetFromXML () để khởi tạo
* những thực thể đó đặc trưng của bất kỳ lớp nào mở rộng
* entityAbstract.
*
* Sử dụng các thư viện
* org.jdom.Element;
*
* @see com.ibm.almaden.smartgrid.EntityAbstract
*
* @param entityElement_ đại diện xml của một đối tượng thuộc tính
*
*
*
************************************************** *************************
* /
public void initFromXML (Element entityElement_) {
super.initCommonSubsetFromXML (entityElement_);
this._propProb = getDoubleAttribute (entityElement_, PROBABILITY);
this._foodID = getIntAttribute (entityElement_, FOOD_ID);
} // initFromXMLL ()
|
Lớp PropertyEden
Lớp Thuộc tính xác định bất kỳ thuộc tính nào có thể áp dụng cho OPC hoặc các thực thể của nó. Trong ví dụ về mô hình Eden này, lớp PropertyEden được sử dụng để sửa đổi sự lan truyền của các đối tượng EntityEden (vi khuẩn). Trong các mô hình khác, các thuộc tính có thể là hằng số đàn hồi cục bộ, độ cứng cục bộ, độ dẫn điện cục bộ, độ dẫn nhiệt, nhiệt dung, v.v.
Việc điều chỉnh giá trị xác suất là một biến thể hiện mới trong lớp PropertyEden . Nếu PropertyId khớp với thực thể , thì xác suất lan truyền được tăng lên bằng giá trị xác suất PropertyEden . Nếu không, nó sẽ bị giảm giá trị đó. Hãy coi lớp này như một thuộc tính hoặc yếu tố trừu tượng làm cho một OPC cụ thể trở nên thân thiện hơn với một loại vi khuẩn cụ thể. Vì giá trị xác suất là một phần bổ sung cho các biến cá thể PropertyAbstract , nó yêu cầu các phương thức getXML () và initFromXML () tương tự như các phương thức EntityEden .
Xem danh sách Mã cho lớp PropertyEden.
VppEdenInitializer Class
Lớp VppEdenInitializer mở rộng VppDataInitializerAbstract .
Hầu hết các ứng dụng sẽ cần cung cấp một lớp để khởi tạo trạng thái của các OPC cụ thể của ứng dụng trong các tập hợp ban đầu mô tả một vấn đề tại thời điểm 0 (khi bắt đầu chạy). Nếu các lớp OPC có dữ liệu dành riêng cho ứng dụng, chúng sẽ yêu cầu bộ khởi tạo dành riêng cho ứng dụng. Các lớp này được sử dụng khi bắt đầu chạy bằng ProblemAutoBuilder để xây dựng trạng thái sự cố từ đầu. Các lớp này không được yêu cầu khi khởi chạy sự cố với ProblemBuilderXML vì trạng thái sự cố được xác định trong các tài liệu XML, có lẽ, được khởi tạo đúng cách.
Lớp VppEdenInitializer xác định loại vi khuẩn (thực thể nào) được đặt trong các phiên bản OPCEden mới được sử dụng để đưa vào các bộ sưu tập ban đầu. Hiện tại, các thuộc tính không được thiết lập bởi VppEdenInitializer . Các VppEdenInitializer chọn một bộ sưu tập trong mỗi VPP và puts một thể hiện của mỗi người trong số ba EntityEden loại vi khuẩn trong khác nhau OPCEden đối tượng.
Xem Danh sách mã cho lớp VppEdenInitializer.
Lớp AppUtils
Mô hình Eden không sử dụng một lớp tiện ích ứng dụng cụ thể. Tất cả dữ liệu và phương thức cần thiết cho mô hình Eden được chứa trong lớp OPC (vì vậy, mô hình Eden, theo mặc định, sử dụng lớp rỗng AppUtilsGeneric ). Người lập trình ứng dụng có thể định nghĩa một lớp triển khai lớp AppUtilsAbstract . Nó có thể chứa các chức năng tiện ích dành riêng cho ứng dụng và dữ liệu có thể được khởi tạo từ tệp cấu hình ứng dụng khi khởi động. Mỗi OPC có thể chia sẻ một phiên bản triển khai AppUtilsAbstract. Điều này cung cấp một nơi hiệu quả để lưu trữ dữ liệu và / hoặc các phương pháp chung cho mọi OPC trong một ứng dụng. Người dùng không bắt buộc phải triển khai tiện ích này. Theo mặc định, lớp AppUtilsGeneric được sử dụng.
Xem danh sách Mã cho lớp AppUtilsGeneric.
tệp eden.cfg
Mọi ứng dụng đều có thể chỉ định một tệp cấu hình dành riêng cho ứng dụng. Nếu không được yêu cầu, tệp grid.cfg đặt các giá trị mặc định cần thiết. Chúng tôi đề nghị các nhà phát triển luôn sử dụng cấu hình dành riêng cho ứng dụng nếu không vì lý do gì khác ngoài việc chỉ định một cách ngắn gọn các tệp lớp cần thiết được sử dụng cho ứng dụng của họ. Xem tệp tệp eden.cfg được cung cấp trong ví dụ phân phối. Các VppEdenInitializer đang hiển thị một ví dụ về mã đơn giản cần thiết để truy cập dữ liệu cấu hình.
Đoạn trích từ cả tệp cấu hình hệ thống, grid.cfg và tệp cấu hình sự cố, eden.cfg , được hiển thị bên dưới:
# grid.cfg
[a]
...
appConfigFile = ./eden.cfg
...
# eden.cfg
# Đây là tệp cấu hình cho ứng dụng mô hình Eden
# chạy trên OptimalGrid
# ------------------------------------------------- ----------
# Phần [sự cố] chứa các thông số kỹ thuật chung cho
# vấn đề mô hình Eden
# ------------------------------------------------- ----------
#
[vấn đề]
OPCClass = com.ibm.almaden.smartgrid.apps.eden.OPCEden
useClass = com.ibm.almaden.smartgrid.AppUtilsGeneric
vppInitializerClass = com.ibm.almaden.smartgrid. \
apps.eden.VppEdenInitializer
|
Tên của tệp cấu hình để sử dụng có thể được đặt trong tệp grid.cfg như được hiển thị ở trên hoặc nó có thể được chỉ định trên dòng lệnh.
./grid.bat -problemConfig ./eden.cfg
Khi trình quản lý sự cố được khởi động, một cửa sổ hộp thoại sẽ được hiển thị để bạn có thể thực hiện các thay đổi tạm thời đối với cấu hình OptimalGrid.
Thêm vấn đề chấm dứt
Khi sự cố kết thúc, trạng thái cuối cùng của mỗi OPC được viết dưới dạng XML. Bạn có thể sử dụng tệp đầu ra XML này để bắt đầu một phiên OptimalGrid khác hoặc viết chương trình giảm dữ liệu của riêng bạn để đọc và xử lý XML.
Sau đây là phần trích dẫn của XML được viết cho bài toán mô hình Eden.
(Bản quyền Tập đoàn IBM)
FPT Aptech – Hệ Thống Đào Tạo Lập Trình Viên Quốc Tế
FPT Aptech trực thuộc Tổ chức Giáo dục FPT có hơn 25 năm kinh nghiệm đào tạo lập trình viên quốc tế tại Việt Nam, và luôn là sự lựa chọn ưu tiên của các sinh viên và nhà tuyển dụng. |