-
Notifications
You must be signed in to change notification settings - Fork 15
/
mixins.py
142 lines (114 loc) · 4.77 KB
/
mixins.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from __future__ import annotations
from collections import defaultdict
from typing import TYPE_CHECKING, Collection, Any
if TYPE_CHECKING:
from negmas.common import MechanismState, NegotiatorMechanismInterface
from negmas.negotiators import Negotiator
from .breaches import Breach
from .common import RenegotiationRequest
from .contract import Contract
from .world import World
__all__ = ["TimeInAgreementMixin", "NoContractExecutionMixin", "NoResponsesMixin"]
class TimeInAgreementMixin:
def init(self, time_field="time"):
self._time_field_name = time_field
self.contracts_per_step: dict[int, list[Contract]] = defaultdict(list)
def on_contract_signed(self: World, contract: Contract):
result = super().on_contract_signed(contract=contract)
if result:
self.contracts_per_step[contract.agreement[self._time_field_name]].append(
contract
)
return result
def executable_contracts(self: World) -> Collection[Contract]:
"""Called at every time-step to get the contracts that are `executable` at this point of the simulation"""
if {
_["id"]
for _ in self._saved_contracts.values()
if _["delivery_time"] == self.current_step and _["signed_at"] >= 0
} != {_.id for _ in self.contracts_per_step.get(self.current_step, [])}:
saved = {
_["id"]
for _ in self._saved_contracts.values()
if _["delivery_time"] == self.current_step and _["signed_at"] >= 0
}
used = {_.id for _ in self.contracts_per_step.get(self.current_step, [])}
err = (
f"Some signed contracts due at {self.current_step} are not being executed: {saved - used} "
f"({used - saved}):\n"
)
for c in saved - used:
err += f"Saved Only:{str(self._saved_contracts[c])}\n"
for c in used - saved:
con = None
for _ in self.contracts_per_step.get(self.current_step, []):
if _.id == c:
con = _
break
err += f"Executable Only:{con}\n"
raise ValueError(err)
return self.contracts_per_step.get(self.current_step, [])
def delete_executed_contracts(self: World) -> None:
self.contracts_per_step.pop(self.current_step, None)
def get_dropped_contracts(self) -> Collection[Contract]:
return [
_
for _ in self.contracts_per_step.get(self.current_step, [])
if self._saved_contracts[_.id]["signed_at"] >= 0
and self._saved_contracts[_.id].get("breaches", "") == ""
and self._saved_contracts[_.id].get("nullified_at", -1) < 0
and self._saved_contracts[_.id].get("erred_at", -1) < 0
and self._saved_contracts[_.id].get("executed_at", -1) < 0
]
class NoContractExecutionMixin:
"""
A mixin to add when there is no contract execution
"""
def delete_executed_contracts(self: World) -> None:
pass
def executable_contracts(self) -> Collection[Contract]:
return []
def start_contract_execution(self, contract: Contract) -> set[Breach]:
return set()
def complete_contract_execution(
self, contract: Contract, breaches: list[Breach], resolution: Contract
) -> None:
pass
class NoResponsesMixin:
"""A mixin that can be added to Agent to minimize the number of abstract methods"""
def on_neg_request_rejected(self, req_id: str, by: list[str] | None):
pass
def on_neg_request_accepted(
self, req_id: str, mechanism: NegotiatorMechanismInterface
):
pass
def on_negotiation_failure(
self,
partners: list[str],
annotation: dict[str, Any],
mechanism: NegotiatorMechanismInterface,
state: MechanismState,
) -> None:
pass
def on_negotiation_success(
self, contract: Contract, mechanism: NegotiatorMechanismInterface
) -> None:
pass
def on_contract_signed(self, contract: Contract) -> bool:
return True
def on_contract_cancelled(self, contract: Contract, rejectors: list[str]) -> None:
pass
def set_renegotiation_agenda(
self, contract: Contract, breaches: list[Breach]
) -> RenegotiationRequest | None:
pass
def respond_to_renegotiation_request(
self, contract: Contract, breaches: list[Breach], agenda: RenegotiationRequest
) -> Negotiator | None:
pass
def on_contract_executed(self, contract: Contract) -> None:
pass
def on_contract_breached(
self, contract: Contract, breaches: list[Breach], resolution: Contract | None
) -> None:
pass