Bước 2: Chào giá và trả giá
Agent điều khiển đề xuất một giá khởi điểm thấp hơn giá của mặt hàng trên thị trường (bằng thông điệp cfp(initial_price)) và chờ tín hiệu trả giá. Mỗi lần nhận được tín hiệu trả giá, Agent điều khiển lại đề xuất một giá mới cao hơn giá cũ bằng thông điệp
cfp(new_price) và lại tiếp tục chờ cho đến khi thấy tín hiệu chấp nhận trả giá từ một
chứa các thơng tin liên quan đến q trình trả giá nên thường có cấu trúc như sau: “Tơi đề nghị tăng mức giá của mặt hàng X lên giá Z và tơi đảm bảo rằng mình có đủ khả năng để trả giá Z cho mặt hàng X”. Điều này làm cho Agent điều khiển cuộc đấu giá tin tưởng rằng Agent mua thực sự có thể trả giá vừa đặt. Nếu các Agent tham gia không hiểu cấu trúc hoặc ontology của thơng điệp cfp thì nó sẽ trả lại một thông điệp not-
understood.
Bước 3: Xác nhận lời trả giá
Agent điều khiển đấu giá sẽ gửi lại cho Agent trả giá một thông điệp chấp nhận accept-
proposal hoặc từ chối reject-proposal lời trả giá.
Bước 4: Lặp lại quá trình đề xuất giá, trả giá và xác nhận
Quá trình đưa giá và trả giá lặp đi lặp lại một số lần cho đến khi khơng có một Agent tham gia nào chấp nhận giá đưa ra hoặc hết thời gian cuộc đấu giá.
Bước 5: Lựa chọn người thắng cuộc
Khi kết thúc phiên đấu giá, nếu giá được chấp nhận cuối cùng lớn hơn giá sàn thì mặt hàng sẽ được bán, ngược lại cuộc đấu giá coi như thất bại. Agent thắng cuộc được lựa chọn ngẫu nhiên trong số các Agent trả giá cao nhất. Các Agent tham gia sẽ được thông báo kết thúc đấu giá bằng thông điệp inform và người thắng cuộc được yêu cầu thanh
toán cho mặt hàng đã chấp nhận mua bằng thơng điệp request. Sau đó, Agent mua và Agent điều khiển đấu giá sẽ bắt đầu quá trình tương tác để thực hiện việc mua và bán.
4.1.2. Chiến lược đấu giá
Trong quá trình đấu giá, việc tìm kiếm Agent điều khiển đấu giá đối với Agent bán là khá đơn giản. Seller chỉ cần lập danh sách các Auctioneer đang hoạt động và sau đó chọn ngẫu nhiên một Auctioneer để yêu cầu rao bán mặt hàng. Trong phần này, chúng ta chỉ tập trung vào thiết kế chiến lược cho Bidder và Auctioneer.
4.1.2.1. Chiến lược cho Agent điều khiển đấu giá ( Auctioneer)
Ngay khi nhận được yêu cầu rao hàng của bên bán Seller, Auctioneer căn cứ vào giá sàn mà Seller đưa ra để quyết định giá khởi điểm. Ở đây, chúng tôi chọn giá khởi điểm chính bằng giá sàn. Bởi Seller sẽ khơng bán mặt hàng với giá thấp hơn giá sàn nên việc đấu giá với các mức giá nhỏ hơn giá sàn là không cần thiết. Việc điều khiển đấu giá sẽ được thực hiện theo thuật tốn sau [42]:
Hình 4.2. Thuật tốn quyết định của Auctioneer.
Giá sẽ được tăng dần theo một số hữu hạn các mức rời rạc. Giả sử rằng có m+1 mức giá rời rạc, L0< L1<..<Lm. Tồn tại một gia số I (do hệ thống hoặc người phát triển quyết định) để tính giá tại mỗi mức. Có nhiều cách thức tính giá khác nhau, ở đây chúng tôi lựa chọn cơng thức tính giá tại mức i theo giá mức i-1 như sau:
Li = Li-1 (1+I) i=1,2,..,m; I=(0,1)
Ở mức giá đầu tiên, Auctioneer sẽ chờ trong khoảng thời gian TO2 để nhận lời trả giá đầu tiên. Hết thời gian này mà khơng có Bidder nào trả giá, cuộc đấu giá sẽ kết thúc mà không bán được hàng. Ngược lại, cuộc đấu giá tiếp tục với các mức giá tiếp theo. Với mỗi mức giá agent điều khiển đấu giá đưa ra, các Bidder sẽ có một khoảng thời gian tối đa TO3 để đưa ra lời trả giá (xác nhận nó sẵn sàng trả giá mà Agent điều khiển đưa ra). Ngay khi nhận được tín hiệu trả giá đầu tiên cho mức giá đã chào, Auctioneer sẽ ghi nhận Bidder vừa trả giá là Agent thắng cuộc tạm thời
…
L0=reverse;
while (t < tmax) and (Có người trả giá đã đề xuất) {
Tính tốn giá đề xuất cho mức mới theo công thức: Li=Li-1(1+I);
Gửi đề xuất giá tới các Bidder có yêu cầu. Nhận lời trả giá.
Chọn Bidder chiến thắng tạm thời }
và chuyển sang mức giá tiếp theo. Phiên đấu giá kết thúc khi hết thời gian timeout TO3 mà khơng có Bidder nào sẵn sàng trả giá. Bidder thắng cuộc ở mức giá trước đó sẽ là Bidder thắng cuộc cuối cùng. Mặt hàng sẽ được bán với giá mà Bidder thắng cuộc đã trả.
4.1.2.2. Chiến lược trả giá cho Bidder
Trước khi mô tả khung quyết định, chúng ta cần phải đề cập chi tiết một số giả thiết về môi trường. Thứ nhất, chúng ta chỉ xem xét giao thức đấu giá kiểu Anh. Thứ hai, mọi cuộc đấu giá đều có thời gian bắt đầu Ts và thời gian kết thúc Te cho trước. Thứ ba, mọi agent trả giá đều có một thời hạn cứng tmax, đến thời điểm đó agent phải mua được mặt hàng mà người dùng yêu cầu. Giả thiết cuối cùng, agent không được phép mua quá số lượng mặt hàng người dùng mong muốn. Sàn đấu giá mà chúng ta mơ phỏng có nhiều cuộc đấu giá kiểu Anh diễn ra đồng thời. Mỗi cuộc đấu giá có một vài bidder tham gia.
Khi Bidder nhận được yêu cầu mua mặt hàng từ người dùng, nó sẽ hoạt động theo thuật tốn ở Hình 4.3 [39] với t là thời điểm hiện tại.
Bidder sẽ tạo lập một danh sách các cuộc đấu giá đang hoạt động (những cuộc đấu giá đã qua thời điểm bắt đầu nhưng chưa đến thời điểm kết thúc), kí hiệu là L(t) và thu thập thông tin liên quan, ví dụ như thời điểm bắt đầu, kết thúc, mặt hàng đang rao bán…Sau đó, Bidder sẽ tính tốn giá tối đa hiện tại current maximum
Hình 4.3. Thuật tốn đấu giá của Bidder
Về lý thuyết, giá tối đa hiện tại current maximum bid phải nhỏ hơn hoặc
bằng số tiền mà Bidder hiện có. Tiếp đó, Bidder chọn lựa trong danh sách các cuộc đấu giá đang hoạt động L(t) để tìm ra danh sách các cuộc đấu giá tiềm năng, tức là những cuộc đấu giá có bán mặt hàng cần mua. Bidder sẽ chọn ngẫu nhiên trong danh sách tiềm năng này một cuộc đấu giá đích để tham gia trả giá. Quá trình trả giá được lặp đi lặp lại nhiều lần cho tới khi mua thành công hoặc Auctioneer đưa ra vượt quá số tiền mà Bidder đó có. Trong trường hợp chưa mua được hàng, Bidder sẽ quay lại bước tìm kiếm các cuộc đấu giá đang diễn ra. Cứ như vậy, Bidder sẽ chỉ kết thúc khi mua được hàng hoặc hết thời gian tồn tại cho phép.
4.2. JADE Platform
JADE là một middleware hỗ trợ việc phát triển các hệ thống đa Agent tuân theo chuẩn FIPA [24] dành cho các Agent thông minh. JADE [28] bao gồm các thành phần sau đây:
Môi trường hoạt động: Đây là nơi các Agent có thể sống và môi trường này phải được kích hoạt trên một host có sẵn trước khi có bất kỳ một Agent nào hoạt động trên host đó.
Một thư viện các lớp mà lập trình viên có thể sử dụng để phát triển Agent của chính họ.
while (t < tmax) and (Chưa mua được mặt hàng yêu cầu) {
Xây dựng danh sách các phiên đấu giá đang hoạt động; Tính tốn giá tối đa có thể trả hiện tại sử dụng chiến lược của Agent.;
Chọn các phiên đấu giá tiềm năng để trả giá từ danh sách đấu giá đang hoạt động;
Chọn phiên đấu giá đích ngẫu nhiên trong số các phiên đấu giá tiềm năng.
Trả giá trong cuộc đấu giá đích }
Một bộ công cụ đồ họa cho phép người dùng quản lý và điều khiển các hoạt động của Agent đang chạy.
Hình 4.4. Nền Jade và các Container
JADE được viết hoàn toàn bằng ngơn ngữ Java và gồm nhiều gói khác nhau cho phép người phát triển sau này có thể tận dụng lại các tính năng và giao diện trừu tượng có sẵn.
4.2.1. Ngôn ngữ truyền thông ACL
Các JADE Agent sử dụng một ngôn ngữ riêng để giao tiếp với nhau, đó là ngơn ngữ truyền thông ACL (do tổ chức chuẩn quốc tế về liên tác Agent - FIPA định nghĩa). Định dạng thông điệp ACL khá phức tạp nhưng tựu trung lại có một số thành phần đặc biệt quan trọng sau đây:
Danh sách địa chỉ bên nhận
Mục đích giao tiếp: Những cái mà bên gửi muốn đạt được khi gửi thơng điệp đó. Ví dụ, khi bên nhận gửi cho bên nhận thông điệp REQUEST tức là bên gửi muốn bên nhận thực hiện một hành động nào đó, thơng điệp INFORM là thông báo cho bên nhận một sự thực nào đó, REJECT là từ chối một đề nghị thương lượng nào đó…
Nội dung: Các thơng tin thực sự chứa trong thơng điệp, ví dụ nội dung của thông điệp INFORM của người điều khiển phiên đấu giá gửi cho người trả giá có thể là start auction để thông báo bắt đầu cuộc đấu giá.
Ngôn ngữ nội dung: Là cấu trúc được dùng để diễn tả nội dung. Cả Agent gửi và nhận đều phải hiểu được ngôn ngữ này.
4.2.2. Cơ chế truyền thông giữa các Agent
Kỹ thuật truyền thông được sử dụng ở đây là truyền thông điệp không đồng bộ. Mỗi một Agent sẽ có một hộp thư (hàng đợi các thơng điệp của Agent) trong đó đặt các thơng điệp do các Agent khác gửi tới. Agent sẽ được thơng báo mỗi khi có thơng điệp được thêm vào hàng đợi. Khi Agent thực sự xem xét đến thơng điệp đó (lấy thơng điệp ra khỏi hàng đợi) thì người lập trình mới thực sự xử lý nội dung thông điệp.
Hình 4.5. Cơ chế truyền thơng điệp khơng đồng bộ của Jade
Quy trình truyền thơng ACL giữa các Agent có thể được mơ tả qua Hình 4.10 ở trên. Quá trình này gồm một số bước cơ bản sau đây:
Chuẩn bị nội dung thông điệp: chỉ đơn giản là điền đầy các trường của
đối tượng ACLMessage.
Gửi thông điệp: bằng cách gọi phương thức send() của một đối tượng
thuộc lớp Agent. Đoạn code sau đây sẽ gửi một thông điệp đến Agent có tên BidderA với thơng báo „Auction is Over‟.
ACLMessage msg = new ACLMessage(ACLMessage.INFORM); msg.addReceiver(new AID(“BidderA”, AID.ISLOCALNAME)); msg.setLanguage(“English”);
msg.setOntology(“Auction-ontology”); msg.setContent(“Auction is Over”); send(msg);
Nhận thông điệp vào hàng đợi: Trong thời gian chạy, JADE tự động gửi
thông điệp vào hàng đợi thông điệp cá nhân của Agent nhận.
Nhận và xử lý thơng điệp: Một Agent có thể lấy các thơng điệp từ hàng
đợi của mình bằng cách gọi thực hiện phương thức receive(). Phương thức
A1 A2
Chuẩn bị thông điệp gửi A2
Gửi thông điệp Lưu thông điệp vào hàng đợi của A2
Lấy thông điệp từ hàng đợi và xử lý
này trả về thông điệp đầu tiên trong hàng đợi thơng điệp, sau đó xóa nó khỏi hàng đợi. Sau khi lấy được thông điệp từ hàng đợi, Agent sẽ tiến hành xử lý thông tin nhận được và đưa ra quyết định hành động tiếp theo.
4.2.3. Ví dụ minh họa truyền thông ACL
Chúng ta hãy xem xét chi tiết cách thức truyền thông điệp giữa hai Agent đã đảm nhận hai role Bidder và Auctioneer trong một hệ đấu giá.
Trong hệ thống đấu giá,thông điệp CFP được sử dụng để thực hiện việc Auctioneer gửi giá đề nghị cho mặt hàng chào bán tới các Bidder. Thơng điệp PROPOSE có thể được Bidder sử dụng để chứa lời xác nhận sẵn sàng trả giá Auctioneer đã đặt ra cho mặt hàng. Thông điệp ACCEPT_PROPOSAL để thể hiện việc Auctioneer chấp nhận lời trả giá của Bidder.
ACLMessage msgACL = new ACLMessage(ACLMessage.REQUEST); msgACL.addReceiver(addressee.getAgent());
try {
msgACL.setContentObject(msgR); } catch (java.io.IOException ioe) {
System.err.println(ioe); throw new RoleException(); }
myAgent.send(msgACL);
4.3. Cài đặt role
Role được cài đặt bằng một lớp trừu tượng trong đó các tính năng của role được biểu diễn dưới dạng các trường tĩnh và phương thức tĩnh [15]. Lớp biểu diễn role có tên trùng với tên của role và là một phần của gói (package) biểu diễn ngữ cảnh ứng dụng của role đó. Ví dụ, ở hệ thống eAuction là gói auction.
package rolesystem.roles.auction; import rolesystem.core.RoleAction; import rolesystem.roles.KnownEvent; /**
This role is the bidder of an auction. Keywords: auction, bidder.
*/
public abstract class Bidder {…}
Mỗi hành động được biểu diễn bởi một phương thức tĩnh, có nhiệm vụ tạo ra một thể hiện thích hợp của lớp RoleAction và trả nó về cho đối tượng gọi phương
thức đó. Tên của phương thức tĩnh này cũng trùng với tên của hành động tương ứng và có thể có một hoặc hai tham số: tham số thứ nhất là địa chỉ của Agent nhận sự kiện tương ứng với hành động, tham số thứ hai (có thể có hoặc khơng) là nội dung thông tin để thực thi hành động. Ví dụ, dưới đây là mã nguồn cài đặt hành động trả giá (bid) của Bidder.
public static RoleAction bid(Id addressee,Price content) { return new RoleAction("bid", addressee,content);}
Đối với sự kiện, ta có hai lớp cài đặt sự kiện khác nhau. Một là lớp RoleEvent, lớp kia là KnownEvent. Lớp RoleEvent biểu diễn các sự kiện được Server Agent dịch từ hành động mà nó nhận được từ Agent. Lớp này cài đặt các sự kiện với các thông tin như: tên của sự kiện, ID của Agent gửi, role mà Agent gửi đang đảm nhận và lớp nội dung thông tin của sự kiện.
public class RoleEvent implements Serializable {
private String name; private int sender;
private String senderRole; private Serializable content; ….
}
Lớp thứ hai cài đặt sự kiện là lớp KnownEvent, thể hiện các sự kiện nằm trong phạm vi xử lý của một role nào đó. Mỗi một sự kiện là instance của lớp RoleEvent cũng sẽ có một sự kiện tương tự là instance lớp KnownEvent. Với cùng một sự kiện, tên của các instance ở hai lớp này là giống nhau, instance của lớp KnownEvent có thêm kí tự KE ở trước để phân biệt. Ví dụ, sự kiện bid là instance
của lớp RoleEvent, ta sẽ có một instance tương ứng của lớp KnownEvent là
KE_bid.
Các sự kiện một role có thể nhận biết là instance của lớp KnownEvent, được khai báo dưới dạng các trường dữ liệu tĩnh. Ví dụ, sự kiện bid mà Auctioneer nhận được dưới đây:
public static final KnownEvent KE_bid=new KnownEvent("bid", Bidder.ROLE_ID, Price.class);
Mối quan hệ giữa các lớp được thể hiện qua lược đồ dưới đây:
Hình 4.6. Lược đồ quan hệ giữa các lớp trong hệ Auction.
Như đã trình bày ở chương 3, việc cài đặt role bằng ngơn ngữ Java có thể được thực hiện dễ dàng và nhanh chóng hơn nhờ các tài liệu XRole. Bằng cách dùng các XSL thích hợp, ta có thể chuyển các định nghĩa role Seller, Bidder và Auctioneer tương ứng thành các lớp trừu tượng như dưới đây:
public abstract class Seller {
String description="role to make resources available"; String keyword[]= {"seller", "auction"};
/*Request to put the good on sale*/
public static RoleAction ReqOnSale(AgentID addressee); /*Put the good to be sold on sale*/
public static RoleAction putGoodOnSale(String Good_ID, String Description);
/*Auctioneer accept seller's request or not*/
public static final KnownEvent KE_acceptSale(AgentID addressee); /*the good cannot be sold at the auction*/
public static final KnownEvent KE_unSold(AgentID addressee); /*payment from the auctioneer*/
public static final KnownEvent KE_pay(AgentID addressee, String content);
}
Hình 4.7. Mã nguồn Java tương ứng với Seller.xml.
Role A (Abstract) ROLE_ID:String=Auction x RoleA KE_A: KnownEvent KE_B: KnownEvent … ActionA: RoleAction ActionB: RoleAction Auction KnownEvent RoleAction
public abstract class Auctioneer {
String description="role to control the auctions"; String keyword[]= {"Auctioneer", "auction"};
/*notify requesting bidders the current goods on sale*/
public static RoleAction notifyGood(AgentID addressee, string content); /*notify bidders the current situation*/
public static RoleAction notifySituation(AgentID addressee, string content);
/*notify bidders the final winner*/
public static RoleAction youWon(AgentID addressee, Price content); /*request to put goods on sale from sellers*/
public static final KnownEvent KE_reqOnSale(AgentID sender); /*put goods on sale*/
public static final KnownEvent KE_putGoodOnSale(AgentID sender, string content);
/*bidder ask about the current goods*/
public static final KnownEvent KE_askGood(AgentID sender); /*ask about the current situation of the auction*/
public static final KnownEvent KE_askSituation(AgentID sender, string content);
/*bid from the bidders*/
public static final KnownEvent KE_bid(AgentID sender, string content); }
Hình 4.8. Mã nguồn Java tương ứng với Auctioneer.xml
public abstract class bidder {
public string description="role to make a bid for the good "; public string keyword[]= {"bidder"};
/*ASK AUCTIONEER ABOUT GOODS ON SALE*/
public static RoleAction askGood(AgentID addressee); public static RoleAction askSituation(AgentID addressee); /*make a bid for the good interested*/