[[PageOutline]] = GENIUS 2 = Genius2 is an open architecture for heterogeneous negotiating parties via the internet. It provides the basis for an implementation of a testbed for negotiating parties that includes a set of negotiation problems for benchmarking parties, a library of negotiation strategies, and analytical tools to evaluate an party's performance and their strategies allows user. == Genius2 overview == Genius2 contains a number of components ||= name =||= description =||= more information =|| ||the core ||the data structures for issues, values, bids, profiles, events and actions, agents etc.||here|| ||profilesserver||a web server that provides profiles and domain descriptions||[https://tracinsy.ewi.tudelft.nl/trac/Genius2ProfilesServer profiles server]|| ||partiesserver||A web server that provides instances of running parties to use for negotiation||[https://tracinsy.ewi.tudelft.nl/trac/Genius2PartiesServer parties server]|| ||runserver||A web server that can run sessions and tournaments||[https://tracinsy.ewi.tudelft.nl/trac/Genius2RunServer run server]|| You can either run these servers locally on either your computer or on your web server, or use a public server somewhere else. For creating your own profile or party, you only need the core. == Server choice, privacy and security = You can choose to either run services privately, on your intranet, or completely open on the internet. ||= privacy need =||= configuration =|| ||completely private, no sharing with others || all services run on local tomcat server, network access of computer disabled || ||competition : share your party with the world, but not its code ||You host your own partiesserver that is connected to the web*. || ||shared profile ||profilesserver on own server or on an existing profilesserver on the web* || ||public party with built-in private profile||Hard-code the profile in the party. Party runs as in competition. || ||run private sessions/tournaments||Run your own runserver, possibly even from behind a firewall or on your local computer. Existing parties- and profilesservers are used in your runs. Negotiation results are handled only on your computer and not visible outside. Others might be able to see agents act on your behalf, but it's not trivial to determine that they are negotiating against each other, especially if these parties are on different partiesservers.|| ||run your own protocols||as with running private sessions/tournaments|| * All firewalls above the server have to be configured appropriately, most corporations have firewalls between your computer and inside the company there is only connection between company computers. == Writing a party in Java Example parties can be found [https://tracinsy.ewi.tudelft.nl/trac/Genius2/browser/exampleparties here]. An agent 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. The basic structure of an agent looks like this {{{ public class RandomParty extends DefaultParty { @Override public void notifyChange(Inform info) { // System.out.println("Received info:" + info); if (info instanceof Settings) { fetchProfile(((Settings) info).getProfile()); this.me = ((Settings) info).getID(); } else if (info instanceof ActionDone) { lastActor = ((ActionDone) info).getAction().getActor(); Action otheract = ((ActionDone) info).getAction(); if (otheract instanceof Offer) { lastReceivedBid = ((Offer) otheract).getBid(); } } else if (info instanceof YourTurn) { myTurn(); } } private void myTurn() { Action action; if (lastReceivedBid != null && profileint.getProfile() .getUtility(lastReceivedBid).doubleValue() > 0.6) { action = new Accept(lastActor, lastReceivedBid); } else { AllBidsList bidspace = new AllBidsList(getProfile().getDomain()); long i = random.nextInt(bidspace.size().intValue()); action = new Offer(me, bidspace.get(BigInteger.valueOf(i))); } try { getConnection().send(action); } catch (IOException e) { e.printStackTrace(); } } @Override public Capabilities getCapabilities() { return new Capabilities(new HashSet<>( Arrays.asList(new ProtocolRef(new URI("SAOP"))))); } @Override public String getDescription() { return "places random bids until it can accept an offer with utility >0.6"; } } }}} === Preparing the jar file In order to put your agent on the [https://tracinsy.ewi.tudelft.nl/trac/Genius2PartiesServer partiesserver] for running, you need a jar file of your party. 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. 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. The example randomagent does this from the maven build script. We recommend to do initialization of the party only in the init() and not in the constructor or static code. This because instances of your class can be made both for extracting general info as getDescription(), or to really run your class. == Create a domain There is not yet a domain editor available so you have to create domains by manually editing a file with JSON code. A domain looks like this {{{ {"name":"jobs", "issuesValues":{ "lease car":{"values":["yes","no"]}, "permanent contract":{"values":["yes","no"]}, "career development opportunities":{"values":["low","medium","high"]}, "fte":{"values":["0.6","0.8","1.0"]}, "salary":{"values":["2000","2500","3000","3500","4000"]}, "work from home":{"values":["0","1","2"]} } } }}} * The name is just a string. It must match the filename and directory name when placed on the profiles server. So your directory must be domainsrepo/jobs and the filename must be jobs.json. * The issueValues contains a dictionary with issues. Each issue is indicated by a name (a string), followed by a column (:) and then a dictionary. The dictionary can contain either a discrete valueset or a number valueset * a discrete valueset looks like "values", a column and then a list of discrete values (all strings) * a number valueset contains a range of numbers and looks like {{{ {"range":["12.2","12.6","0.3"]} }}} so "range:" followed by a list of 3 values. The first value is the minimum value in the range, the second the maximum value in the range, and the third the step value. This example range thus contains 12.2 and 12.5 (the next one would be 12.8 but that is already outside the range). == Create a profile A profile (a.k.a utilityspace) looks like this {{{ { "LinearAdditiveUtilitySpace": { "issueUtilities": { "salary": { "discreteutils": { "valueUtilities": { "2000": 0, "2500": 0.25, "3000": 0.3, "3500": 0.75, "4000": 1.0 } } }, "fte": { "discreteutils": { "valueUtilities": { "0.6": 0.25, "0.8": 0.5, "1.0": 0.75 } } }, "work from home": { ..... } } } }, "issueWeights": { "salary": 0.24, "fte": 0.32, "work from home": 0.18, "lease car": 0.06, "permanent contract": 0.16, "career development opportunities": 0.04 }, "domain": { "name": "jobs", ..... }, "name": "jobs1" } } }}} This is an "LinearAdditiveYtilitySpace", other utilityspaces would have different contents. It contains a number of components: * issueUtilities. Here, each issue value from the domain gets a utility assigned. The two types of issue values each having their matching utility function: ||= Issue Value class =||= Utility class =||= json serialization example =|| {{{#!td DiscreteValue }}} {{{#!td DiscreteValueSetUtilities }}} {{{#!td "discreteutils": { "valueUtilities": { "2000": 0, "2500": 0.25, "3000": 0.3, "3500": 0.75, "4000": 1.0 } } }}} |---------------------------- {{{#!td NumberValue }}} {{{#!td NumberValueSetUtilities }}} {{{#!td numberutils": { "lowValue":12, "lowUtility":0.3, "highValue":18, "highUtility":0.6 } }}} |---------------------------- * issueWeights: this is a map, for each issue there is a value in [0,1] and the sum of the weights in this map must be exactly 1. * domain: identical to above. We replaced some issueValues with "..." in this example . * name: a simple string with the name of the profile. The name must match the filename of the profile. == Bids == A 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. A bid typically looks like {{{ { "salary":"2000", "fte":"0.8", "work from home","0.6" ...} }}} === Value workaround This example also illustrates a problem with the json parser. In our jobs example domain, fte is a discrete value, so "0.8" is just a string, not a number. However if fte would be a numeric issue, we naively would write the 0.8 without quotes: {{{fte:0.8}}}. However due to the way the json parser works, we would get 0.8 parsed as s double. This introduces rounding errors. And these cause all kinds of problems. To avoid these rounding errors, the solution is to store the decimal value also in a string. We can then later convert it properly. However if we store it in a string, we would be unable to distinguish it from a discrete value. To work around this, we put it in a string and prepend it with a "=". * "0.8": the DiscreteValue * "=0.8": the NumberValue. This workaround is only needed for issue values like in bids. In other places where we can *only* have double values, we can work around the issue without needing the string trick. == Genius2 sources == === downloading source code You can browse the genius2 core sources directly using the browse button at the right top of this page. You can download the source code of this component from https://tracinsy.ewi.tudelft.nl/svn/genius2/ === Import all sources in Eclipse Normal developers that write new parties do not need to install the genius2 source code. This is only needed if you want to debug/trace into the genius2 code for instance for debugging or understanding the inner workings of genius2. Install Subclipse using "help/Eclipse MarketPlace" and search for subclipse. Disable the JavaHL native DLLs and install. NOTE: due to a bug in Eclipse Photon the marketplace may not work. We suggest to upgrade... You may get some errors on JavaHL library. To get rid of those, go to preferences/Team/SVN/ * disable General SVN settings / JavaHL * SVN interface/Client: select SVNKit instead of JavaHL. Right click in Package Explorer in Eclipse, select "Import/SVN/Checkout Projects from SVN". Select the root of the project, finish (selecting sub-projects will result in a stupid loop in the checkout procedure in Eclipse and won't lead anywhere...) Richt click on the checked-out project that you want eclipse to recognise as Maven project (the project are maven but Eclipse does not recognise this after check-out). Select import/maven/existing maven projects. Finish. Note. Eclipse does not automatically recognise this as a maven project because Eclipse supports this only with GIT repositories while we use SVN.