@@ -624,6 +624,16 @@ def __call__(self, state, action=None) -> MechanismStepResult:
624624 # ), f"Not all negotiator actions were used in this step: {action}"
625625 return MechanismStepResult (state , times = times , exceptions = exceptions )
626626
627+ @property
628+ def full_trace_with_utils (self ) -> list [tuple ]:
629+ """Returns the full trace and the utility of the negotiators at each step."""
630+ trace = self .full_trace
631+ ufuns = [_ .ufun for _ in self .negotiators ]
632+ return [
633+ tuple (list (_ ) + [u (_ [- 3 ]) if u else float ("nan" ) for u in ufuns ])
634+ for _ in trace
635+ ]
636+
627637 @property
628638 def full_trace (self ) -> list [TraceElement ]:
629639 """Returns the negotiation history as a list of relative_time/step/negotiator/offer tuples"""
@@ -698,6 +708,65 @@ def not_equal(a, b):
698708 response (self ._history [- 1 ]),
699709 )
700710 )
711+ if (
712+ self .state .done
713+ and self .agreement is not None
714+ and offers
715+ and not not_equal (offers [- 1 ].offer , self .agreement )
716+ ):
717+ acceptances = get_acceptances (self ._history [- 1 ])
718+ offers [- 1 ] = TraceElement (
719+ self ._history [- 1 ].time ,
720+ self ._history [- 1 ].relative_time ,
721+ self ._history [- 1 ].step ,
722+ self ._history [- 1 ].current_proposer ,
723+ self .agreement ,
724+ {n : ResponseType .ACCEPT_OFFER for n in acceptances },
725+ response (self ._history [- 1 ]),
726+ )
727+ if (
728+ self .state .done
729+ and self .agreement is None
730+ and offers
731+ and self .state .has_error
732+ ):
733+ acceptances = get_acceptances (self ._history [- 1 ])
734+ offers [- 1 ] = TraceElement (
735+ self ._history [- 1 ].time ,
736+ self ._history [- 1 ].relative_time ,
737+ self ._history [- 1 ].step ,
738+ self ._history [- 1 ].current_proposer ,
739+ self .agreement ,
740+ {n : ResponseType .ACCEPT_OFFER for n in acceptances },
741+ "error" ,
742+ )
743+ elif (
744+ self .state .done
745+ and self .agreement is None
746+ and offers
747+ and self .state .timedout
748+ ):
749+ acceptances = get_acceptances (self ._history [- 1 ])
750+ offers [- 1 ] = TraceElement (
751+ self ._history [- 1 ].time ,
752+ self ._history [- 1 ].relative_time ,
753+ self ._history [- 1 ].step ,
754+ self ._history [- 1 ].current_proposer ,
755+ self .agreement ,
756+ {n : ResponseType .ACCEPT_OFFER for n in acceptances },
757+ "timedout" ,
758+ )
759+ elif self .state .done and self .agreement is None and offers :
760+ acceptances = get_acceptances (self ._history [- 1 ])
761+ offers [- 1 ] = TraceElement (
762+ self ._history [- 1 ].time ,
763+ self ._history [- 1 ].relative_time ,
764+ self ._history [- 1 ].step ,
765+ self ._history [- 1 ].current_proposer ,
766+ self .agreement ,
767+ {n : ResponseType .ACCEPT_OFFER for n in acceptances },
768+ "broken" ,
769+ )
701770
702771 return offers
703772
0 commit comments