Changes between Version 223 and Version 224 of WikiStart


Ignore:
Timestamp:
08/14/19 08:55:22 (5 years ago)
Author:
wouter
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • WikiStart

    v223 v224  
    142142
    143143 
    144 
    145 == Party
    146 A party is a program that receives inform messages from the protocol, and can send the actions it wants to take regarding the negotiation back to the protocol. These actions are sent over a websocket that is created by the partiesserver that created the party, which in turn creates this according to a http GET request that comes from a running protocol. The party can also pro-actively search for information and take other actions as it likes, as long as it adheres to the requirements of the protocol (discussed later in this document).
    147 
    148 The party module contains the inform objects. There are several, and although they have quite specific meanings, their fine details can be tweaked by the protocol.
    149 
    150 ||inform object||meaning||
    151 ||Settings||usually sent as first inform to a party, indicating start of the session and providing the party name, protocol, profile, deadline etc||
    152 ||YourTurn||Indicating that the party receiving this inform now has the turn. ||
    153 ||ActionDone||Informing that some party did an action||
    154 ||Finished||Indicating that a session has been finished||
    155 
    156 Please check the [source:party/src/main/java/geniusweb/party/inform source code of Inform objects] for all the details especially on the json serialization.
    157 
    158 The party module also contains basic interfaces for implementing your negotiation party. These interfaces are only relevant to create a party compatible with our reference implementation of the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver]. The main class is Party, which defines the basic functionality required for a negotiation party on our server. The heart of the party is that your Party implements Connectable<Inform,Action>. Connectable contains 2 main functions: connect and disconnect.  When connect is called, your party receives a Connection over which it receives Inform objects and can send Action objects. What exactly is sent and received is determined by the protocol (see the protocol section below). For example if the SAOP protocol is used, your party will receive a YourTurn message, after which it decides on its action and sends it into the Connection. See also the example party discussed below.
    159 
    160 
    161 == Timeline
    162 The timeline module describes the deadline and a progress objects.
    163 The deadline indicates how much time a negotiation session can take and is used to specify the settings for a session or tournament. Two examples:
    164 
    165 {{{
    166 {"deadlinerounds":{"rounds":100,"durationms":999}}
    167 }}}
    168 
    169 and
    170 {{{
    171 {"deadlinetime":{"durationms":2000}}
    172 }}}
    173 
    174  * durationms indicates the maximum run time in milliseconds for the party. The clock starts ticking at the moment the party receives its SessionSettings object.
    175  * rounds indicates the maximum number of rounds in the session. The session will end after this number of rounds, deal or no deal.
    176 
    177 The progress indicates where currently running session is towards the deadline. Progress is contained in the settings object. Round based progress must be updated by the party after each round.
    178  
    179 
    180 
    181 
    182 == References
    183 Parties, domains,  profiles and protocols are stored and used on remote machines.
    184 We use IRI's (internationalized resource identifier, which looks similar to the well known URLs you use in your web browser) to refer to them. These IRI's are packed inside objects like the PartyRef, ProtocolRef, ProfileRef, DomainRef so that it is clear what type of object the IRI is referring to.
    185 For example, when your party is initialized, it usually receives a Settings object that contains a ProfileRef. The intention is that the party fetches the actual profile from the web, using the IRI in the ProtocolRef. See the example party below for an example.
    186 
    187 There are a number of schemes used for references:
    188 
    189 ||scheme||used with||example||comments||
    190 ||http:||party||http://localhost:8080/partiesserver/run/randompyparty-1.0.0|| ||
    191 ||ws:||profile||ws://localhost:8080/profilesserver/websocket/get/jobs/jobs1.json|| ||
    192 ||file:||profile||file:src/test/settings.json ||gives file relative to local current working dir||
    193 ||classpath:||party||classpath:geniusweb.exampleparties.randomparty.RandomParty||must be in classpath||
    194 
    195 == BidSpace
    196 The bidspace module contains functionality to support building a negotiation party. We currently have
    197 * OpponentModel: this is a category of classes that can estimate the opponent's profile from the bids that he places.
    198 * Pareto: this is a category of classes that can compute the pareto frontier from a set of profiles. Pareto optimality is an important mechanism to place optimal bids.
    199 * AllBidsList: this can be used to craete a list containing all possible bids in a domain. This list is created in a lazy way, and competely avoids storing the whole list in memory (which might not even fit)
    200 
    201 
    202 
    203 == Protocol
    204 The protocol module contains the functionality to define and execute a negotiation protocol.
    205 There are session protocols and tournament protocols.
    206 
    207 The basic classes defining a protocol are:
    208 * The [source:/protocol/src/main/java/geniusweb/protocol/NegoSettings.java NegoSettings]: these define the settings for the protocol, such as the deadline, the participants and the profile
    209 * The [source:/protocol/src/main/java/geniusweb/protocol/NegoState.java NegoState]: this contains the current state of execution of the protocol. To give some example states: "waiting for bid from party 2", "ended with agreement", "ended because party 1 broke the protocol". A state also has various {{{with()}}} functions defining the new state from an old state and a party doing an action.
    210 * The [source:/protocol/src/main/java/geniusweb/protocol/NegoProtocol.java NegoProtocol]: this defines what happens when a negotiation starts, when a participant enters halfway the session, what are the allowed actions, what happens if a participant breaks the protocol, etc.   
    211 
    212 
    213 
    214 
    215 = Writing a party in Java
    216 
    217 Example parties can be found [source:/exampleparties here]. You can easily clone a party with SVN using {{{svn co https://tracinsy.ewi.tudelft.nl/svn/GeniusWeb/exampleparties/randomparty/}}} (this clones randomparty, use a different name to fetch another example).
    218 
    219 A party is compiled with maven. After compilation ({{{mvn package}}}) you get a {{{target/yourparty-X.Y.Z-jar-with-dependencies.jar}}} that can be copied into the parties server for deployment.
    220 
    221 The basic structure of an party looks like this
    222 {{{
    223 public class RandomParty extends DefaultParty {
    224         @Override
    225         public void notifyChange(Inform info) {
    226                 if (info instanceof Settings) {
    227                         Settings settings = (Settings) info;
    228                         this.profileint = ProfileConnectionFactory
    229                                         .create(settings.getProfile().getURI(), getReporter());
    230                         this.me = settings.getID();
    231                         this.progress = settings.getProgress();
    232                 } else if (info instanceof ActionDone) {
    233                         Action otheract = ((ActionDone) info).getAction();
    234                         if (otheract instanceof Offer) {
    235                                 lastReceivedBid = ((Offer) otheract).getBid();
    236                         }
    237                 } else if (info instanceof YourTurn) {
    238                         myTurn();
    239                         if (progress instanceof ProgressRounds) {
    240                                 progress = ((ProgressRounds) progress).advance();
    241                         }
    242                 } else if (info instanceof Finished) {
    243                         getReporter().log(Level.INFO, "Final ourcome:" + info);
    244                 }
    245         }
    246 
    247 
    248         private void myTurn() {
    249                 Action action;
    250                 if (isGood(lastReceivedBid)) {
    251                         action = new Accept(me, lastReceivedBid);
    252                 } else {
    253                         // for demo. Obviously full bids have higher util in general
    254                         AllPartialBidsList bidspace = new AllPartialBidsList(
    255                                         profileint.getProfile().getDomain());
    256                         Bid bid = null;
    257                         for (int attempt = 0; attempt < 20 && !isGood(bid); attempt++) {
    258                                 long i = random.nextInt(bidspace.size().intValue());
    259                                 bid = bidspace.get(BigInteger.valueOf(i));
    260                         }
    261                         action = new Offer(me, bid);
    262                 }
    263                 getConnection().send(action);
    264         }
    265 
    266         private boolean isGood(Bid bid) {
    267                 return bid != null
    268                                 && ((LinearAdditiveUtilitySpace) profileint.getProfile())
    269                                                 .getUtility(bid).doubleValue() > 0.6;
    270         }
    271 
    272         @Override
    273         public Capabilities getCapabilities() {
    274                         return new Capabilities(new HashSet<>(
    275                                         Arrays.asList(new ProtocolRef(new URI("SAOP")))));
    276         }
    277 
    278         @Override
    279         public String getDescription() {
    280                 return "places random bids until it can accept an offer with utility >0.6";
    281         }
    282 
    283 }
    284 }}}
    285 
    286 == Preparing the jar file
    287 In order to put your party on the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver] for running, you need a jar file of your party.
    288 
    289 Normally the party includes all dependencies. The jar files are loaded with an isolated jar class loader that should avoid collisions with possibly identically named but possibly different packages in other jar files.
    290 
    291 
    292 Party jar files must have a Main-Class set in the MANIFEST.MF file. This main-class must implement Party and have a no-arg constructor.
    293 
    294 The example randomparty does this from the maven build script.
    295 
    296 We recommend to do initialization of the party only in the init() and not in the constructor or static code.
    297 This because instances of your class can be made both for extracting general info as getDescription(), or to really run your class.
    298 
    299 
    300 = Writing a party in Python
    301 We provide a python-to-java adapter so that you can easily write your party in python instead of Java. You can check the full working example code [source:/exampleparties/randompartypy/src/main/resources/RandomParty.py here]. A python-based party looks like this:
    302 {{{
    303 class RandomParty (DefaultParty):
    304         def notifyChange(self, info):
    305                 if isinstance(info, Settings) :
    306                         self.profile = ProfileConnectionFactory.create(info.getProfile().getURI(), self.getReporter());
    307                         self.me = info.getID()
    308                         self.progress = info.getProgress()
    309                 elif isinstance(info , ActionDone):
    310                         self.lastActor = info.getAction().getActor()
    311                         otheract = info.getAction()
    312                         if isinstance(otheract, Offer):
    313                                 self.lastReceivedBid = otheract.getBid()
    314                 elif isinstance(info , YourTurn):
    315                         self._myTurn()
    316                         if isinstance(self.progress, ProgressRounds) :
    317                                 self.progress = self.progress.advance();
    318 
    319 
    320 
    321         def getCapabilities(self): # -> Capabilities
    322                 return Capabilities(HashSet([ ProtocolRef(URI("SAOP"))]))
    323 
    324         def getDescription(self):
    325                 return "places random bids until it can accept an offer with utility >0.6. Python version"
    326        
    327         def terminate(self):
    328                 self.profile.disconnect()
    329 
    330         def _myTurn(self):
    331                 if self.lastReceivedBid != None and self.profile.getProfile().getUtility(self.lastReceivedBid).doubleValue() > 0.6:
    332                         action = Accept(self.me, self.lastReceivedBid)
    333                 else:
    334                         bidspace = AllPartialBidsList(self.profile.getProfile().getDomain())
    335                         bid = None
    336                         for attempt in range(20):
    337                                 i = self.random.nextInt(bidspace.size()) # warning: jython implicitly converts BigInteger to long.
    338                                 bid = bidspace.get(BigInteger.valueOf(i))
    339                                 if self._isGood(bid):
    340                                         break
    341                         action = Offer(self.me, bid);
    342                         self.getConnection().send(action)
    343 
    344         def _isGood(self, bid):
    345                 return bid != None and self.profile.getProfile().getUtility(bid).doubleValue() > 0.6;
    346 
    347 }}}
    348 
    349 You need to wrap your python party into a jar wrapper to get it accepted by the parties server. To do this, check the javadoc with the [source:/pythonadapter/src/main/java/geniusweb/pythonadapter/PythonPartyAdapter.java PythonPartyAdapter].
    350 
    351 
    352 = Writing a party in other languages
    353 If you want to use another language than java or python2 to write your parties, you have a number of options
    354 * Make your own adapter that runs your language from Java. Check [source:pythonadapter/src/main/java/geniusweb/pythonadapter/PythonPartyAdapter.java our pythonadapter] for an example how this can be done.
    355 * Write your own partiesserver that correctly implements the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver interface]. This boils down to creating a webserver that  correctly can handle calls to a number of prescribed URLs and websockets.
    356 
    357 = JSON layout
    358 This section discusses how domains and profiles are looking in JSON. JSON is the communication format, java instances of Domain, Profile and Bid can easily be converted back and forth to JSON using the jackson objectmapper (see the test and example codes)
    359 
    360 == Create a domain
    361 
    362144== Create a profile
    363145A profile is usually created after the domain. An example linear additive profile looks like this
     
    453235* name: a simple string with the name of the profile. The name must match the filename of the profile.
    454236
     237== Party
     238A party is a program that receives inform messages from the protocol, and can send the actions it wants to take regarding the negotiation back to the protocol. These actions are sent over a websocket that is created by the partiesserver that created the party, which in turn creates this according to a http GET request that comes from a running protocol. The party can also pro-actively search for information and take other actions as it likes, as long as it adheres to the requirements of the protocol (discussed later in this document).
     239
     240The party module contains the inform objects. There are several, and although they have quite specific meanings, their fine details can be tweaked by the protocol.
     241
     242||inform object||meaning||
     243||Settings||usually sent as first inform to a party, indicating start of the session and providing the party name, protocol, profile, deadline etc||
     244||YourTurn||Indicating that the party receiving this inform now has the turn. ||
     245||ActionDone||Informing that some party did an action||
     246||Finished||Indicating that a session has been finished||
     247
     248Please check the [source:party/src/main/java/geniusweb/party/inform source code of Inform objects] for all the details especially on the json serialization.
     249
     250The party module also contains basic interfaces for implementing your negotiation party. These interfaces are only relevant to create a party compatible with our reference implementation of the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver]. The main class is Party, which defines the basic functionality required for a negotiation party on our server. The heart of the party is that your Party implements Connectable<Inform,Action>. Connectable contains 2 main functions: connect and disconnect.  When connect is called, your party receives a Connection over which it receives Inform objects and can send Action objects. What exactly is sent and received is determined by the protocol (see the protocol section below). For example if the SAOP protocol is used, your party will receive a YourTurn message, after which it decides on its action and sends it into the Connection. See also the example party discussed below.
     251
     252
     253== Timeline
     254The timeline module describes the deadline and a progress objects.
     255The deadline indicates how much time a negotiation session can take and is used to specify the settings for a session or tournament. Two examples:
     256
     257{{{
     258{"deadlinerounds":{"rounds":100,"durationms":999}}
     259}}}
     260
     261and
     262{{{
     263{"deadlinetime":{"durationms":2000}}
     264}}}
     265
     266 * durationms indicates the maximum run time in milliseconds for the party. The clock starts ticking at the moment the party receives its SessionSettings object.
     267 * rounds indicates the maximum number of rounds in the session. The session will end after this number of rounds, deal or no deal.
     268
     269The progress indicates where currently running session is towards the deadline. Progress is contained in the settings object. Round based progress must be updated by the party after each round.
     270 
     271
     272
     273
     274== References
     275Parties, domains,  profiles and protocols are stored and used on remote machines.
     276We use IRI's (internationalized resource identifier, which looks similar to the well known URLs you use in your web browser) to refer to them. These IRI's are packed inside objects like the PartyRef, ProtocolRef, ProfileRef, DomainRef so that it is clear what type of object the IRI is referring to.
     277For example, when your party is initialized, it usually receives a Settings object that contains a ProfileRef. The intention is that the party fetches the actual profile from the web, using the IRI in the ProtocolRef. See the example party below for an example.
     278
     279There are a number of schemes used for references:
     280
     281||scheme||used with||example||comments||
     282||http:||party||http://localhost:8080/partiesserver/run/randompyparty-1.0.0|| ||
     283||ws:||profile||ws://localhost:8080/profilesserver/websocket/get/jobs/jobs1.json|| ||
     284||file:||profile||file:src/test/settings.json ||gives file relative to local current working dir||
     285||classpath:||party||classpath:geniusweb.exampleparties.randomparty.RandomParty||must be in classpath||
     286
     287== BidSpace
     288The bidspace module contains functionality to support building a negotiation party. We currently have
     289* OpponentModel: this is a category of classes that can estimate the opponent's profile from the bids that he places.
     290* Pareto: this is a category of classes that can compute the pareto frontier from a set of profiles. Pareto optimality is an important mechanism to place optimal bids.
     291* AllBidsList: this can be used to craete a list containing all possible bids in a domain. This list is created in a lazy way, and competely avoids storing the whole list in memory (which might not even fit)
     292
     293
     294
     295== Protocol
     296The protocol module contains the functionality to define and execute a negotiation protocol.
     297There are session protocols and tournament protocols.
     298
     299The basic classes defining a protocol are:
     300* The [source:/protocol/src/main/java/geniusweb/protocol/NegoSettings.java NegoSettings]: these define the settings for the protocol, such as the deadline, the participants and the profile
     301* The [source:/protocol/src/main/java/geniusweb/protocol/NegoState.java NegoState]: this contains the current state of execution of the protocol. To give some example states: "waiting for bid from party 2", "ended with agreement", "ended because party 1 broke the protocol". A state also has various {{{with()}}} functions defining the new state from an old state and a party doing an action.
     302* The [source:/protocol/src/main/java/geniusweb/protocol/NegoProtocol.java NegoProtocol]: this defines what happens when a negotiation starts, when a participant enters halfway the session, what are the allowed actions, what happens if a participant breaks the protocol, etc.   
     303
     304
     305
     306
     307= Writing a party in Java
     308
     309Example parties can be found [source:/exampleparties here]. You can easily clone a party with SVN using {{{svn co https://tracinsy.ewi.tudelft.nl/svn/GeniusWeb/exampleparties/randomparty/}}} (this clones randomparty, use a different name to fetch another example).
     310
     311A party is compiled with maven. After compilation ({{{mvn package}}}) you get a {{{target/yourparty-X.Y.Z-jar-with-dependencies.jar}}} that can be copied into the parties server for deployment.
     312
     313The basic structure of an party looks like this
     314{{{
     315public class RandomParty extends DefaultParty {
     316        @Override
     317        public void notifyChange(Inform info) {
     318                if (info instanceof Settings) {
     319                        Settings settings = (Settings) info;
     320                        this.profileint = ProfileConnectionFactory
     321                                        .create(settings.getProfile().getURI(), getReporter());
     322                        this.me = settings.getID();
     323                        this.progress = settings.getProgress();
     324                } else if (info instanceof ActionDone) {
     325                        Action otheract = ((ActionDone) info).getAction();
     326                        if (otheract instanceof Offer) {
     327                                lastReceivedBid = ((Offer) otheract).getBid();
     328                        }
     329                } else if (info instanceof YourTurn) {
     330                        myTurn();
     331                        if (progress instanceof ProgressRounds) {
     332                                progress = ((ProgressRounds) progress).advance();
     333                        }
     334                } else if (info instanceof Finished) {
     335                        getReporter().log(Level.INFO, "Final ourcome:" + info);
     336                }
     337        }
     338
     339
     340        private void myTurn() {
     341                Action action;
     342                if (isGood(lastReceivedBid)) {
     343                        action = new Accept(me, lastReceivedBid);
     344                } else {
     345                        // for demo. Obviously full bids have higher util in general
     346                        AllPartialBidsList bidspace = new AllPartialBidsList(
     347                                        profileint.getProfile().getDomain());
     348                        Bid bid = null;
     349                        for (int attempt = 0; attempt < 20 && !isGood(bid); attempt++) {
     350                                long i = random.nextInt(bidspace.size().intValue());
     351                                bid = bidspace.get(BigInteger.valueOf(i));
     352                        }
     353                        action = new Offer(me, bid);
     354                }
     355                getConnection().send(action);
     356        }
     357
     358        private boolean isGood(Bid bid) {
     359                return bid != null
     360                                && ((LinearAdditiveUtilitySpace) profileint.getProfile())
     361                                                .getUtility(bid).doubleValue() > 0.6;
     362        }
     363
     364        @Override
     365        public Capabilities getCapabilities() {
     366                        return new Capabilities(new HashSet<>(
     367                                        Arrays.asList(new ProtocolRef(new URI("SAOP")))));
     368        }
     369
     370        @Override
     371        public String getDescription() {
     372                return "places random bids until it can accept an offer with utility >0.6";
     373        }
     374
     375}
     376}}}
     377
     378== Preparing the jar file
     379In order to put your party on the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver] for running, you need a jar file of your party.
     380
     381Normally the party includes all dependencies. The jar files are loaded with an isolated jar class loader that should avoid collisions with possibly identically named but possibly different packages in other jar files.
     382
     383
     384Party jar files must have a Main-Class set in the MANIFEST.MF file. This main-class must implement Party and have a no-arg constructor.
     385
     386The example randomparty does this from the maven build script.
     387
     388We recommend to do initialization of the party only in the init() and not in the constructor or static code.
     389This because instances of your class can be made both for extracting general info as getDescription(), or to really run your class.
     390
     391
     392= Writing a party in Python
     393We provide a python-to-java adapter so that you can easily write your party in python instead of Java. You can check the full working example code [source:/exampleparties/randompartypy/src/main/resources/RandomParty.py here]. A python-based party looks like this:
     394{{{
     395class RandomParty (DefaultParty):
     396        def notifyChange(self, info):
     397                if isinstance(info, Settings) :
     398                        self.profile = ProfileConnectionFactory.create(info.getProfile().getURI(), self.getReporter());
     399                        self.me = info.getID()
     400                        self.progress = info.getProgress()
     401                elif isinstance(info , ActionDone):
     402                        self.lastActor = info.getAction().getActor()
     403                        otheract = info.getAction()
     404                        if isinstance(otheract, Offer):
     405                                self.lastReceivedBid = otheract.getBid()
     406                elif isinstance(info , YourTurn):
     407                        self._myTurn()
     408                        if isinstance(self.progress, ProgressRounds) :
     409                                self.progress = self.progress.advance();
     410
     411
     412
     413        def getCapabilities(self): # -> Capabilities
     414                return Capabilities(HashSet([ ProtocolRef(URI("SAOP"))]))
     415
     416        def getDescription(self):
     417                return "places random bids until it can accept an offer with utility >0.6. Python version"
     418       
     419        def terminate(self):
     420                self.profile.disconnect()
     421
     422        def _myTurn(self):
     423                if self.lastReceivedBid != None and self.profile.getProfile().getUtility(self.lastReceivedBid).doubleValue() > 0.6:
     424                        action = Accept(self.me, self.lastReceivedBid)
     425                else:
     426                        bidspace = AllPartialBidsList(self.profile.getProfile().getDomain())
     427                        bid = None
     428                        for attempt in range(20):
     429                                i = self.random.nextInt(bidspace.size()) # warning: jython implicitly converts BigInteger to long.
     430                                bid = bidspace.get(BigInteger.valueOf(i))
     431                                if self._isGood(bid):
     432                                        break
     433                        action = Offer(self.me, bid);
     434                        self.getConnection().send(action)
     435
     436        def _isGood(self, bid):
     437                return bid != None and self.profile.getProfile().getUtility(bid).doubleValue() > 0.6;
     438
     439}}}
     440
     441You need to wrap your python party into a jar wrapper to get it accepted by the parties server. To do this, check the javadoc with the [source:/pythonadapter/src/main/java/geniusweb/pythonadapter/PythonPartyAdapter.java PythonPartyAdapter].
     442
     443
     444= Writing a party in other languages
     445If you want to use another language than java or python2 to write your parties, you have a number of options
     446* Make your own adapter that runs your language from Java. Check [source:pythonadapter/src/main/java/geniusweb/pythonadapter/PythonPartyAdapter.java our pythonadapter] for an example how this can be done.
     447* Write your own partiesserver that correctly implements the [https://tracinsy.ewi.tudelft.nl/pubtrac/GeniusWebPartiesServer partiesserver interface]. This boils down to creating a webserver that  correctly can handle calls to a number of prescribed URLs and websockets.
     448
     449= JSON layout
     450This section discusses how domains and profiles are looking in JSON. JSON is the communication format, java instances of Domain, Profile and Bid can easily be converted back and forth to JSON using the jackson objectmapper (see the test and example codes)
     451
     452== Create a domain
     453
     454
    455455== Bids ==
    456456A Bid is a map with the issue names as keys (strings) and the values being an element from the valueset as in the domain description.