1 | import os
|
---|
2 | from collections import defaultdict
|
---|
3 | from typing import List, cast, Set
|
---|
4 |
|
---|
5 | import plotly.graph_objects as go
|
---|
6 | from geniusweb.bidspace.pareto.GenericPareto import GenericPareto
|
---|
7 | from geniusweb.bidspace.pareto.ParetoLinearAdditive import ParetoLinearAdditive
|
---|
8 | from geniusweb.issuevalue.Bid import Bid
|
---|
9 | from geniusweb.party.DefaultParty import DefaultParty
|
---|
10 | from geniusweb.profile.utilityspace.LinearAdditive import LinearAdditive
|
---|
11 | from geniusweb.profileconnection.ProfileConnectionFactory import ProfileConnectionFactory
|
---|
12 | from geniusweb.profileconnection.ProfileInterface import ProfileInterface
|
---|
13 | from uri.uri import URI
|
---|
14 |
|
---|
15 |
|
---|
16 | def compute_pareto_frontier(settings_profiles: List[str]):
|
---|
17 | profiles = dict()
|
---|
18 | for profile_url in [f"file:{x}" for x in settings_profiles]:
|
---|
19 | profileInt: ProfileInterface = ProfileConnectionFactory.create(
|
---|
20 | URI(profile_url), DefaultParty.getReporter)
|
---|
21 | profile: LinearAdditive = cast(LinearAdditive, profileInt.getProfile())
|
---|
22 | profiles[profile_url] = profile
|
---|
23 |
|
---|
24 | pareto: ParetoLinearAdditive = ParetoLinearAdditive(list(profiles.values()))
|
---|
25 | pareto_points: Set[Bid] = pareto.getPoints()
|
---|
26 |
|
---|
27 | pareto_frontier = dict()
|
---|
28 | for pareto_bid in pareto_points:
|
---|
29 | pareto_frontier[pareto_bid] = dict()
|
---|
30 | for profile_name, profile in profiles.items():
|
---|
31 | pareto_frontier[pareto_bid][profile_name] = float(profile.getUtility(pareto_bid))
|
---|
32 |
|
---|
33 | return pareto_frontier
|
---|
34 |
|
---|
35 | def plot_pareto(results_trace: dict, pareto_frontier: dict, plot_file: str):
|
---|
36 | utilities = defaultdict(lambda: {"x": [], "y": [], "bids": []})
|
---|
37 | profiles = results_trace["connections"]
|
---|
38 | x_axis = profiles[0]
|
---|
39 | x_label = "_".join(x_axis.split("_")[-2:])
|
---|
40 | y_axis = profiles[1]
|
---|
41 | y_label = "_".join(y_axis.split("_")[-2:])
|
---|
42 |
|
---|
43 | accept = {"x": [], "y": [], "bids": []}
|
---|
44 | for action in results_trace["actions"]:
|
---|
45 | if "Offer" in action:
|
---|
46 | offer = action["Offer"]
|
---|
47 | actor = offer["actor"]
|
---|
48 | for agent, util in offer["utilities"].items():
|
---|
49 | if agent == x_axis:
|
---|
50 | utilities[actor]["x"].append(util)
|
---|
51 | else:
|
---|
52 | utilities[actor]["y"].append(util)
|
---|
53 |
|
---|
54 | utilities[actor]["bids"].append(offer["bid"]["issuevalues"])
|
---|
55 |
|
---|
56 | elif "Accept" in action:
|
---|
57 | offer = action["Accept"]
|
---|
58 | actor = offer["actor"]
|
---|
59 | for agent, util in offer["utilities"].items():
|
---|
60 | if agent == x_axis:
|
---|
61 | accept["x"].append(util)
|
---|
62 | else:
|
---|
63 | accept["y"].append(util)
|
---|
64 |
|
---|
65 | accept["bids"].append(offer["bid"]["issuevalues"])
|
---|
66 |
|
---|
67 | fig = go.Figure()
|
---|
68 | fig.add_trace(
|
---|
69 | go.Scatter(
|
---|
70 | mode="markers",
|
---|
71 | x=accept["x"],
|
---|
72 | y=accept["y"],
|
---|
73 | name="agreement",
|
---|
74 | marker={"color": "green", "size": 15},
|
---|
75 | hoverinfo="skip",
|
---|
76 | )
|
---|
77 | )
|
---|
78 |
|
---|
79 | color = {0: "red", 1: "blue"}
|
---|
80 | for i, (agent, utility) in enumerate(utilities.items()):
|
---|
81 | name = "_".join(agent.split("_")[-2:])
|
---|
82 |
|
---|
83 | text = []
|
---|
84 | for bid, util_x, util_y in zip(utility["bids"], utility["x"], utility["y"]):
|
---|
85 | text.append(
|
---|
86 | "<br>".join(
|
---|
87 | [x_label + f"<b>: {util_x:.3f}</b><br>"]
|
---|
88 | + [y_label + f"<b>: {util_y:.3f}</b><br>"]
|
---|
89 | + [f"{i}: {v}" for i, v in bid.items()]
|
---|
90 | )
|
---|
91 | )
|
---|
92 |
|
---|
93 | fig.add_trace(
|
---|
94 | go.Scatter(
|
---|
95 | x=utility["x"],
|
---|
96 | y=utility["y"],
|
---|
97 | marker={"color": color[i]},
|
---|
98 | name=f"{name}",
|
---|
99 | hovertext = text,
|
---|
100 | hoverinfo = "text"
|
---|
101 | )
|
---|
102 | )
|
---|
103 |
|
---|
104 | x_axis_profile = None
|
---|
105 | y_axis_profile = None
|
---|
106 | party_profiles = results_trace["partyprofiles"]
|
---|
107 | for party_prof in party_profiles:
|
---|
108 | if x_axis in party_prof:
|
---|
109 | x_axis_profile = party_profiles[x_axis]["profile"]
|
---|
110 | elif y_axis in party_prof:
|
---|
111 | y_axis_profile = party_profiles[y_axis]["profile"]
|
---|
112 |
|
---|
113 | pareto_bids = {"x": [], "y": [], "bids": []}
|
---|
114 | for bid, utilities in pareto_frontier.items():
|
---|
115 | for profile, util in utilities.items():
|
---|
116 | if profile == x_axis_profile:
|
---|
117 | pareto_bids["x"].append(util)
|
---|
118 | elif profile == y_axis_profile:
|
---|
119 | pareto_bids["y"].append(util)
|
---|
120 |
|
---|
121 | pareto_bids["bids"].append(bid)
|
---|
122 |
|
---|
123 | fig.add_trace(
|
---|
124 | go.Scatter(
|
---|
125 | x=pareto_bids["x"],
|
---|
126 | y=pareto_bids["y"],
|
---|
127 | mode='markers',
|
---|
128 | name='pareto frontier point'
|
---|
129 | )
|
---|
130 | )
|
---|
131 |
|
---|
132 | fig.update_layout(
|
---|
133 | width=800,
|
---|
134 | height=800,
|
---|
135 | legend={
|
---|
136 | "yanchor": "bottom",
|
---|
137 | "y": 1,
|
---|
138 | "xanchor": "left",
|
---|
139 | "x": 0,
|
---|
140 | },
|
---|
141 | )
|
---|
142 |
|
---|
143 | fig.update_layout(title_text='Negotiation traces', title_x=0.5)
|
---|
144 | fig.update_xaxes(title_text="Utility of " + x_label, ticks="outside")
|
---|
145 | fig.update_yaxes(title_text="Utility of " + y_label, ticks="outside")
|
---|
146 | fig.write_html(f"{os.path.splitext(plot_file)[0]}.html")
|
---|