Настройка negotiation между агентами на аукционе ресурсов с counter-offers
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Настройка negotiation между агентами на аукционе ресурсов с counter-offers
1. Цель задачи
Разработать симуляцию многоагентных переговоров (negotiation) на основе аукциона ограниченных ресурсов с поддержкой встречных предложений (counter-offers). Агенты должны конкурировать за ресурсы, оценивая их полезность, и обмениваться предложениями до достижения глобально согласованного распределения. Ключевой результат Агенты достигают соглашения (все ресурсы распределены) не более чем за заданное число раундов, и ни один агент не может улучшить свою полезность путём одностороннего изменения.
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Среда для запуска многоагентного взаимодействия | Создать самостоятельно на Python с использованием asyncio |
| Правила аукциона с counter-offers | Описание в разделе 4 (этапы) |
| Базовые стратегии агентов (ценовая функция, порог согласия) | Реализовать как классы с наследованием |
| Инструмент логирования и визуализации | logging, matplotlib (опционально) |
| Набор ресурсов (5–10 единиц с разной ценностью) | Задать вручную в конфигурации |
Если нет реального инструмента — симулируем:
- Устанавливаем Python 3.10+ и библиотеки:
asyncio(встроена),numpy,logging. - Создаём файл
auction_sim.py— вся логика в одном модуле. - Для каждого агента определяем его внутреннюю оценку каждого ресурса (рандомизированно, но с согласованным диапазоном).
- Аукционист реализует последовательные раунды: сбор ставок, анализ, выдача counter-offers.
- Визуализация: скрипт выводит таблицу с раундами и итоговое распределение.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык программирования | Python 3.10+ | Основная реализация |
| Асинхронность | asyncio | Параллельная работа агентов и аукциониста |
| Генерация случайных величин | numpy.random | Оценки ресурсов, шум в стратегиях |
| Логирование | logging | Отслеживание хода переговоров |
| Визуализация (опционально) | matplotlib | График изменения полезности по раундам |
| Контроль версий | Git | Управление кодом |
4. Этапы выполнения
Этап 1: Проектирование протокола аукциона (оценка времени: 1 ч)
Действия
- Определить множество ресурсов
R = {r1, r2, ..., rM}(M = 10) с уникальными идентификаторами. - Определить множество агентов
A = {a1, a2, ..., aN}(N = 4). - Установить правила:
- Каждый раунд агенты отправляют ставку (предлагаемую цену) за каждый ресурс, который они хотят получить.
- Аукционист собирает все ставки, определяет предварительное распределение (жадное назначение каждому ресурсу агенту с максимальной ставкой).
- После предварительного распределения аукционист генерирует counter-offer: для каждого неудовлетворённого агента предлагает альтернативный набор ресурсов по сниженной цене (например, +10% к его ставке).
- Агенты принимают counter-offer или корректируют ставки в следующем раунде.
- Критерий останова: все ресурсы распределены, и ни один агент не хочет менять своё решение (по правилу индивидуальной рациональности).
- Согласовать формат сообщений: ставка — словарь
{agent_id: {resource_id: price}}, counter-offer — список{agent_id: {resource_id: new_price}}.
Ожидаемый результат этапа Документ с протоколом (можно в виде комментариев в коде) и файл конфигурации config.py с параметрами симуляции.
Этап 2: Реализация базовых классов агентов (оценка времени: 1.5 ч)
Действия
- Создать абстрактный класс
Agent:- Атрибуты:
id,budget,valuation(словарь{resource_id: value}),strategy_type. - Метод
make_offer(all_resources, current_assignments)— возвращает ставки. - Метод
accept_counter_offer(counter_offer)— возвращаетTrue/False.
- Атрибуты:
- Реализовать две конкретные стратегии:
GreedyAgent: ставит за ресурс его полную оценку минус 10% (если хватает бюджета).PatientAgent: начинает с 50% оценки и увеличивает на 5% каждый раунд.
- В
make_offerучесть, что агенты могут ставить только на те ресурсы, которые ещё не заняты или на которые они ещё не получили counter-offer. - Добавить случайный шум в оценки (нормальный шум с σ = 10% от значения).
Пример кода
class GreedyAgent:
def __init__(self, id, budget, valuations):
self.id = id
self.budget = budget
self.valuations = valuations
self.offered = {} # ресурсы, на которые уже делались ставки
def make_offer(self, available_resources):
offer = {}
for r in available_resources:
if r not in self.offered:
price = int(self.valuations[r] * 0.9)
if price <= self.budget:
offer[r] = price
return offer
Ожидаемый результат этапа Модуль agents.py с двумя классами-агентами и протестированной логикой генерации ставок.
Этап 3: Реализация аукциониста (оценка времени: 1.5 ч)
Действия
- Создать класс
Auctioneer:- Метод
run_round(agents, resources):- Запросить у каждого агента ставки.
- Объединить ставки в
all_bids. - Жадное назначение: для каждого ресурса выбрать агента с максимальной ставкой; если ничья — случайный выбор.
- Определить список неудовлетворённых агентов (те, кто не получил желаемого ресурса, но делал ставки).
- Для каждого неудовлетворённого агента сформировать counter-offer: предложить любой свободный ресурс по цене
original_bid + 10%. - Отправить counter-offer; агенты отвечают, принимают или нет.
- Метод
- Реализовать цикл раундов, пока не выполнено условие останова:
- Все ресурсы назначены (свободных нет).
- Ни один агент не отклоняет counter-offer (т.е. все согласны с текущим распределением).
- Добавить механизм остановки при превышении лимита раундов (max_rounds = 20).
Таблица формата сообщений
| Поле | Тип | Описание |
|---|---|---|
round_number | int | Номер текущего раунда |
bids | dict | {agent_id: {resource_id: price}} |
assignments | dict | {resource_id: agent_id} после greedy |
counter_offers | dict | {agent_id: {resource_id: price}} |
Ожидаемый результат этапа Класс Auctioneer в auctioneer.py, который успешно проводит один полный раунд с двумя агентами и двумя ресурсами.
Этап 4: Интеграция и запуск симуляции (оценка времени: 1 ч)
Действия
- Создать главный скрипт
run_simulation.py:- Загрузить конфигурацию (список агентов, ресурсов, бюджетов).
- Инициализировать агентов и аукциониста.
- Запустить главный цикл
asyncio.run(main_loop()).
- Использовать
loggingдля вывода хода переговоров:- INFO: начало раунда, ставки.
- DEBUG: детали counter-offers.
- WARNING: если раунд не привёл к изменениям.
- Провести симуляцию с 4 агентами и 10 ресурсами (оценки генерировать случайно с фиксированным seed для воспроизводимости).
- После окончания вывести итоговое распределение и полезность каждого агента.
Ожидаемый результат этапа Запускаемый скрипт, который выводит в консоль лог переговоров и финальную таблицу распределения.
Этап 5: Анализ результатов (оценка времени: 0.5 ч)
Действия
- Добавить в код подсчёт метрик:
- Количество раундов до соглашения.
- Суммарная полезность всех агентов.
- Доля агентов, улучшивших свою полезность после counter-offers.
- Провести серию запусков с разными стратегиями (Greedy vs Patient) и разными бюджетами.
- Построить простой график (используя
matplotlib): изменение средней полезности по раундам.
Ожидаемый результат этапа Файл analysis.py или раздел в основном скрипте, выводящий метрики и при необходимости график.
5. Критерии приемки (Definition of Done)
- Реализован протокол аукциона с counter-offers в соответствии с этапом 1.
- Агенты способны отправлять ставки и обрабатывать встречные предложения.
- Аукционист корректно собирает ставки, назначает ресурсы и генерирует counter-offers.
- Симуляция завершается за конечное число раундов (≤20) с полным распределением ресурсов.
- Результаты логируются, и можно восстановить ход переговоров.
- Код модульный:
agents.py,auctioneer.py,config.py,run_simulation.py. - Написаны минимум 3 теста на критическую логику (greedy assignment, обработка counter-offer, условие останова).
- Ведётся Git-репозиторий с осмысленными коммитами.
6. Ожидаемый результат
Основной артефакт Архив или репозиторий, содержащий:
run_simulation.py— главный исполняемый файл.agents.py— реализация агентов.auctioneer.py— реализация аукциониста.config.py— параметры симуляции (агенты, ресурсы, бюджеты).test_auction.py— набор тестов.README.md— описание запуска и протокола.
Содержание вывода при запуске
Раунд 1:
Ставки: агент_A: {r1: 90, r2: 45}, агент_B: {r1: 85, r2: 50}
Предв. назначение: r1->A(90), r2->B(50)
Counter-offers: агент_B: предложен r1 по 93.5 (отказ)
Раунд 2:
... (до достижения соглашения)
Финальная таблица
| Ресурс | Агент | Цена | Полезность |
|---|---|---|---|
| r1 | A | 90 | 100 |
| r2 | B | 50 | 60 |
| ... | ... | ... | ... |
| Итоговая суммарная полезность: 420 (из 500 возможных, эффективность 84%). |
Дополнительно (опционально): График изменения полезности каждого агента по раундам.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Бесконечный цикл переговоров (агенты многократно отклоняют counter-offers) | Ввести максимальное число раундов и случайную стратегию «согласиться с вероятностью 0.5», если раунд не меняет распределения |
| Одновременное выставление одинаковых ставок (ничья) | Аукционист выбирает случайного агента с равной вероятностью; фиксировать seed для воспроизводимости |
| Агенты не могут улучшить свою полезность из-за ограниченного бюджета | Добавить третий тип агента — «торговец» (budget бесконечен, но ценность ниже) |
| Сложность отладки асинхронных вызовов | Использовать asyncio только для эмуляции задержек; основная логика — синхронная, вызовы через await asyncio.sleep(0) для имитации параллельности |
| Некорректное обновление состояния ресурсов после counter-offers | Ввести в Auctioneer множество tentative_assignments, которое пересчитывается после каждого раунда |
8. Бюджет времени (оценка)
| Этап | Время (часы) |
|---|---|
| Этап 1: Проектирование протокола | 1 |
| Этап 2: Реализация агентов | 1.5 |
| Этап 3: Реализация аукциониста | 1.5 |
| Этап 4: Интеграция и запуск | 1 |
| Этап 5: Анализ и доработка | 0.5 |
| Итого | 5.5 |
Примечание Для первого раза рекомендуется выделить 6–7 часов с учётом отладки и изучения asyncio. Если время ограничено, этап 5 можно сократить до простого вывода метрик в консоль.
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 101 | Основы multi-agent систем |
| 145 | Протоколы аукционов (Vickrey, English, Dutch) |
| 201 | Встречные предложения (counter-offers) |
| 267 | Индивидуальная рациональность |
| 288 | Координация через аукцион |
| 310 | Распределение ограниченных ресурсов |
| 345 | Стратегии уступок (concession strategies) |
| 402 | Асинхронное программирование для агентов |
| 456 | Эффективность распределения Парето |
| 500 | Тестирование многоагентных симуляций |
10. Чек-лист самопроверки
- Я определил протокол аукциона и counter-offers до написания кода.
- Я реализовал хотя бы две различные стратегии агентов.
- Я добавил логирование всех раундов и решений.
- Я проверил, что симуляция завершается за < 20 раундов с полным распределением.
- Я написал unit-тесты для жадного назначения и обработки ничьей.
- Я запустил симуляцию с разными seed и сравнил результаты.