Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pull request #6

Merged
Merged
Show file tree
Hide file tree
Changes from 124 commits
Commits
Show all changes
167 commits
Select commit Hold shift + click to select a range
ddc2a9f
write doctest for algorithm 1
RenanaTurgeman Jan 19, 2024
8649c32
write tests for algorithm 1
RenanaTurgeman Jan 19, 2024
dece364
add documentation
RenanaTurgeman Jan 19, 2024
6b98ef7
Update tests for algorithm 1
RenanaTurgeman Jan 25, 2024
1610dc7
add tests for algorithm 3
RenanaTurgeman Jan 25, 2024
d789ea3
fix the tests for algorithms 1,3
RenanaTurgeman Feb 2, 2024
a548fb8
upload linear program
RenanaTurgeman Feb 6, 2024
2f22c42
working on ACEEI algorithm
RenanaTurgeman Feb 6, 2024
b190173
working on student_budget_per_bundle function
RenanaTurgeman Feb 6, 2024
7dd0015
finish student_budget_per_bundle
RenanaTurgeman Feb 8, 2024
182a31d
working on linear program
RenanaTurgeman Feb 8, 2024
a9935ac
working on student_budget_per_bundle
RenanaTurgeman Feb 8, 2024
77abdf9
working on enum
RenanaTurgeman Feb 13, 2024
83cfa1f
add doctest to find_different_budgets
ofirshitrit Feb 13, 2024
f384c53
implement student_budget_per_bundle
RenanaTurgeman Feb 13, 2024
1d0b896
work on student_best_bundle_per_budget
RenanaTurgeman Feb 20, 2024
98bef28
fix student_best_bundle_per_budget nd implement with dict
RenanaTurgeman Feb 28, 2024
0df23ce
simply student_best_bundle_per_budget
RenanaTurgeman Feb 28, 2024
93e4f73
working on linear_program.py
RenanaTurgeman Feb 28, 2024
90332be
Merge branch 'ariel-research:main' into main
RenanaTurgeman Mar 3, 2024
51d6c64
Merge branch 'ariel-research:main' into main
RenanaTurgeman Mar 3, 2024
6d9d08a
try
RenanaTurgeman Mar 5, 2024
803af37
working on linear_program.py
RenanaTurgeman Mar 5, 2024
86c9796
add doctest to linear_program.py
ErgaDN Mar 5, 2024
ef10b0f
finish linear_program.py
ErgaDN Mar 5, 2024
3f63c6a
working on the main function find_ACEEI_with_EFTB
ErgaDN Mar 5, 2024
c0def08
after erel
RenanaTurgeman Mar 6, 2024
929c4fa
fix initial_budgets in the ACEEI tests
RenanaTurgeman Mar 6, 2024
cd9badd
delete the lp prints
RenanaTurgeman Mar 12, 2024
241d6a1
Using the directory function
ErgaDN Mar 12, 2024
81bf296
Correcting the return in the main function
ErgaDN Mar 12, 2024
cbe196d
print the final budget b* and final prices p*
RenanaTurgeman Mar 12, 2024
432399a
Deleting unused functions
RenanaTurgeman Mar 12, 2024
141b3bb
contested EFTB
ErgaDN Mar 12, 2024
06b31f8
Merge remote-tracking branch 'origin/main'
ErgaDN Mar 12, 2024
1c777fc
fix contested EFTB in check_envy
ErgaDN Mar 12, 2024
bb8e6da
Types of variables in the function declaration
ErgaDN Mar 13, 2024
6098732
start fix test_ACEEI.py
ErgaDN Mar 17, 2024
9b764c6
Adapting the tests to the code structure
ErgaDN Mar 17, 2024
333f5dd
run doctest
ErgaDN Mar 17, 2024
b7b3711
delete EFTBStatus from linear_program.py
ErgaDN Mar 17, 2024
3a744c1
update
ErgaDN Apr 15, 2024
1f6035c
change the initial_budgets to dict in algo 3
RenanaTurgeman Apr 16, 2024
a5e47fc
Declaration of functions
RenanaTurgeman Apr 16, 2024
2877ecb
implement student_best_bundle
ofirshitrit Apr 16, 2024
7ed7c87
implement find_gradient_neighbors
ofirshitrit Apr 16, 2024
a814920
implement clipped_excess_demand and excess_demand
ofirshitrit Apr 16, 2024
8606c78
working on find_individual_price_adjustment_neighbors
ofirshitrit Apr 16, 2024
259b0a3
implement find_individual_price_adjustment_neighbors
RenanaTurgeman Apr 18, 2024
f4a8fbd
implement find_min_error_prices
RenanaTurgeman Apr 18, 2024
49ddf79
fix differ_in_one_value
RenanaTurgeman Apr 18, 2024
56750e2
allclose to ACEEI
ErgaDN May 3, 2024
5e81ec9
Write headers and unittests
ofirshitrit May 16, 2024
d1bf253
add break to the while
ofirshitrit May 16, 2024
fe53ed3
working on find_profitable_manipulation
ofirshitrit May 16, 2024
b38e81c
tests for find_profitable_manipulation
ofirshitrit May 20, 2024
0a6a664
update loggers
ErgaDN May 20, 2024
f0d7d7c
finish algo 1
ErgaDN May 23, 2024
1faa9df
start implement algorithm 2
RenanaTurgeman May 26, 2024
a9eadb5
change the while condition
RenanaTurgeman May 26, 2024
0318c8e
finish implement find_profitable_manipulation.py
ofirshitrit May 30, 2024
1d5fea9
fix the random_budgets
RenanaTurgeman May 30, 2024
5b8c4f5
fix population test
ofirshitrit May 30, 2024
390da3e
fix randomness tests
ofirshitrit May 30, 2024
52fc111
add tests
ofirshitrit May 30, 2024
9f92545
implement history
ofirshitrit May 30, 2024
4472c51
arrange the code
RenanaTurgeman May 30, 2024
ef9a3c3
erel changes
ofirshitrit May 30, 2024
a21b134
change the history implementation
RenanaTurgeman Jun 4, 2024
76441dc
remove history from find_all_equivalent_prices`s test
RenanaTurgeman Jun 4, 2024
0abd4c5
fix find_all_equivalent_prices function
RenanaTurgeman Jun 4, 2024
8dae984
make delta as parameter
RenanaTurgeman Jun 4, 2024
93a442b
working
RenanaTurgeman Jun 4, 2024
1e19e3b
change the delta to set
RenanaTurgeman Jun 5, 2024
572e45d
Updating a condition in the lambda function
ErgaDN Jun 5, 2024
aac99c9
work
RenanaTurgeman Jun 5, 2024
4dc540a
fix find_all_equivalent_prices
RenanaTurgeman Jun 5, 2024
e0bfccc
change to arg min in find_min_error_prices
RenanaTurgeman Jun 5, 2024
f6fb7bb
fix find_individual_price_adjustment_neighbors
RenanaTurgeman Jun 5, 2024
4777d05
add loggers to tabu search
RenanaTurgeman Jun 5, 2024
4c7811a
Adding an article name and moving a main function to the beginning
ErgaDN Jun 5, 2024
55fcce9
move the name of the article to the top
RenanaTurgeman Jun 6, 2024
1003e25
Adding targeted comments
RenanaTurgeman Jun 6, 2024
2e8965c
change the extend to add in the neighbors
RenanaTurgeman Jun 10, 2024
b7c4929
fix the neighbors in the main function
RenanaTurgeman Jun 10, 2024
98a3b82
change the initial of best_bundle from None to () in student_best_bundle
RenanaTurgeman Jun 10, 2024
49f6a2f
fix the give_bundle
RenanaTurgeman Jun 10, 2024
25e0d64
implement all the todo
RenanaTurgeman Jun 10, 2024
b824513
fix the test
RenanaTurgeman Jun 10, 2024
0f37fe3
work
RenanaTurgeman Jun 19, 2024
ea0c1c2
correcting the statement of "neighbors"
ErgaDN Jun 19, 2024
1d4caa7
Attempt to correct history
ErgaDN Jun 20, 2024
60eb027
fix find_all_equivalent_prices
ErgaDN Jun 20, 2024
bf96286
Add colored logging
ErgaDN Jun 20, 2024
8eab384
Arrangement of the loggers
ErgaDN Jun 20, 2024
6badf28
Added a function that checks several different allocations with the s…
ErgaDN Jun 23, 2024
5561cb3
work on ex8
RenanaTurgeman Jun 23, 2024
d4e4014
Update single price match search for incomplete numbers
RenanaTurgeman Jun 24, 2024
a980d0e
arrange the loggers
RenanaTurgeman Jun 24, 2024
25c8d6e
change the main function
RenanaTurgeman Jun 24, 2024
77b8ccb
arrange the code
RenanaTurgeman Jun 24, 2024
b644274
Prevention of adding neighbors that are in history
ErgaDN Jun 24, 2024
6682eb1
Merge remote-tracking branch 'origin/main'
ErgaDN Jun 24, 2024
02b7432
Fixed seed for running examples
ErgaDN Jun 24, 2024
1c01f38
Update loggers
ErgaDN Jun 24, 2024
5ad7b31
Big tests for tabu_search.py
ErgaDN Jun 24, 2024
129aaf7
add experiments about delta and beta
RenanaTurgeman Jun 25, 2024
6e83cde
check the branch
ofirshitrit Jun 25, 2024
aa28b0b
check the branch
ofirshitrit Jun 25, 2024
885aa7a
check branch
ErgaDN Jun 25, 2024
32cf1ec
move coloredlogs to the main
ofirshitrit Jun 25, 2024
dd76129
fix requirements.txt
RenanaTurgeman Jun 25, 2024
db23253
fix init
RenanaTurgeman Jun 25, 2024
cc0df6e
fix init
RenanaTurgeman Jun 25, 2024
591c203
fix init3
RenanaTurgeman Jun 25, 2024
6e48767
Merge branch 'ariel-research:main' into main
RenanaTurgeman Jun 25, 2024
5df7b9f
Merge remote-tracking branch 'origin/main'
ErgaDN Jun 26, 2024
4e43ccd
fix test 2
ErgaDN Jun 26, 2024
7eb1cc5
all the tests are working
ErgaDN Jun 26, 2024
286ee6e
fix test in find_profitable_manipulation.py
ErgaDN Jun 26, 2024
d113c06
Comparing beta and delta performance
ErgaDN Jun 27, 2024
c7a9bf3
Checking the file
ErgaDN Jun 27, 2024
99b8e1a
change the inputs of the algorithms to **kwargs
ofirshitrit Jun 27, 2024
a386de3
comparing delta and epsilon performance - ACEEI
ErgaDN Jun 30, 2024
9ac43bb
add cache
RenanaTurgeman Jul 3, 2024
dde377f
test
erelsgl Jul 3, 2024
df078cc
main programs
erelsgl Jul 3, 2024
ec3a222
main
erelsgl Jul 3, 2024
6ad6341
add titles to linear_program.py
ofirshitrit Jul 4, 2024
76a0be3
update project
ofirshitrit Jul 4, 2024
1771d88
plot
RenanaTurgeman Jul 4, 2024
e24da4b
add comments on the optimize_model function
ofirshitrit Jul 4, 2024
64338c5
change name of parameter
ofirshitrit Jul 4, 2024
df5a46b
remove log initialization
erelsgl Jul 4, 2024
20a9b53
debug linear_program
erelsgl Jul 4, 2024
ed33c0f
main
erelsgl Jul 4, 2024
ee9819c
kwargs in algorithm 2
erelsgl Jul 4, 2024
4fa2f48
remove redundant function
erelsgl Jul 4, 2024
e3e7124
erel changes
ofirshitrit Jul 7, 2024
610c368
Merge remote-tracking branch 'origin/main'
ofirshitrit Jul 7, 2024
20ae656
try commit
ofirshitrit Jul 7, 2024
cbaaabf
Creating calculate_combinations and extracting the code is the same a…
ErgaDN Jul 7, 2024
c713278
Time measurement and graph for use_cache
ErgaDN Jul 7, 2024
6d343a7
Merge branch 'Cache-in-Tabu-Search' of https://github.com/Final-proje…
ErgaDN Jul 7, 2024
4b1ee92
logs
erelsgl Jul 7, 2024
1e38c45
-
erelsgl Jul 7, 2024
e9aadf7
run doctest in main
erelsgl Jul 7, 2024
9b3ba4e
improve logs in ACEEI
erelsgl Jul 7, 2024
ab9933e
Moving files to the utils folder and fixing ACEEI
ErgaDN Jul 8, 2024
d15f849
Update get_combinations_courses_sorted
ErgaDN Jul 8, 2024
6eb06f3
Merge branch 'main' of https://github.com/Final-project-distribution-…
ErgaDN Jul 8, 2024
1b40c18
add combinations_courses_sorted to student_best_bundles_without_cache
ErgaDN Jul 8, 2024
aea4b25
If a student cannot get a basket, we will bring him an empty basket (…
ErgaDN Jul 8, 2024
d9b981c
Moving the calculation combinations courses sorted in the main function
ErgaDN Jul 8, 2024
9f7848e
Merge branch 'Cache-in-Tabu-Search'
ErgaDN Jul 8, 2024
0ec51ea
merge Cache-In-Tabu-Search to main
ErgaDN Jul 8, 2024
33e3e83
add combinations_courses_sorted to student_best_bundle_per_budget
ErgaDN Jul 8, 2024
037e269
add combinations_courses_sorted to funcuions in tabu_search
ErgaDN Jul 8, 2024
32dd7b3
add plots
ErgaDN Jul 8, 2024
e70a07f
logs
erelsgl Jul 9, 2024
0762bf2
make folder for ACEEI
RenanaTurgeman Jul 9, 2024
7d0fa73
fix
RenanaTurgeman Jul 9, 2024
912f5a7
fix
RenanaTurgeman Jul 9, 2024
20b555f
fix
RenanaTurgeman Jul 9, 2024
2969198
fix the import of ACEEI
RenanaTurgeman Jul 9, 2024
46897e3
move files to ACEEI folder
erelsgl Jul 9, 2024
1719f34
tests
erelsgl Jul 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
428 changes: 428 additions & 0 deletions experiments/ACEEI_tabu_example.py

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions experiments/compare_course_allocation_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def run_ariel_experiment():
import logging, experiments_csv
experiments_csv.logger.setLevel(logging.INFO)
run_uniform_experiment()
run_szws_experiment()
run_ariel_experiment()

# run_szws_experiment()
# run_ariel_experiment()
#

2,359 changes: 1,184 additions & 1,175 deletions experiments/results/course_allocation_szws.csv

Large diffs are not rendered by default.

323 changes: 323 additions & 0 deletions fairpyx/algorithms/ACEEI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,323 @@
"""
"Practical algorithms and experimentally validated incentives for equilibrium-based fair division (A-CEEI)"
by ERIC BUDISH, RUIQUAN GAO, ABRAHAM OTHMAN, AVIAD RUBINSTEIN, QIANFAN ZHANG. (2023)
link to the article: https://arxiv.org/pdf/2305.11406
ALGORITHM 1: find an A-CEEI with (contested) EF-TB property


Programmers: Erga Bar-Ilan, Ofir Shitrit and Renana Turgeman.
Since: 2024-01
"""
from enum import Enum
import logging
import numpy as np

from fairpyx import Instance, AllocationBuilder
from itertools import combinations
from fairpyx.algorithms import linear_program as lp


class EFTBStatus(Enum):
NO_EF_TB = 0
EF_TB = 1
CONTESTED_EF_TB = 2


logger = logging.getLogger(__name__)

# ---------------------The main function---------------------

def find_ACEEI_with_EFTB(alloc: AllocationBuilder, **kwargs):
"""
ALGORITHM 1: find an A-CEEI with (contested) EF-TB property

:param instance: a fair-course-allocation instance
:param initial_budgets: Students' initial budgets
:param delta: The step size
:param epsilon: maximum budget perturbation
:param t: type 𝑡 of the EF-TB constraint,
0 for no EF-TB constraint,
1 for EF-TB constraint,
2 for contested EF-TB
:return final courses prices, final budgets, final distribution

>>> from fairpyx.adaptors import divide

>>> from fairpyx.utils.test_utils import stringify

>>> logger.addHandler(logging.StreamHandler())
>>> logger.setLevel(logging.INFO)

>>> instance = Instance(
... valuations={"avi":{"x":1, "y":2, "z":4}, "beni":{"x":2, "y":3, "z":1}},
... agent_capacities=2,
... item_capacities={"x":1, "y":1, "z":2})
>>> initial_budgets = {"avi":2, "beni":3}
>>> delta = 0.5
>>> epsilon = 0.5
>>> t = EFTBStatus.NO_EF_TB
>>> stringify(divide(find_ACEEI_with_EFTB, instance=instance, initial_budgets=initial_budgets,
... delta=delta, epsilon=epsilon, t=t))
"{avi:['x', 'z'], beni:['y', 'z']}"

>>> instance = Instance(
... valuations={"avi":{"x":5, "y":2, "z":1}, "beni":{"x":4, "y":1, "z":3}},
... agent_capacities=2,
... item_capacities={"x":1, "y":1, "z":2})
>>> initial_budgets = {"avi":3, "beni":4}
>>> delta = 0.5
>>> epsilon = 1
>>> t = EFTBStatus.EF_TB
>>> stringify(divide(find_ACEEI_with_EFTB, instance=instance, initial_budgets=initial_budgets,
... delta=delta, epsilon=epsilon, t=t))
"{avi:['y', 'z'], beni:['x', 'z']}"

>>> instance = Instance(
... valuations={"avi":{"x":5, "y":5, "z":1}, "beni":{"x":4, "y":6, "z":4}},
... agent_capacities=2,
... item_capacities={"x":1, "y":2, "z":2})
>>> initial_budgets = {"avi":5, "beni":4}
>>> delta = 0.5
>>> epsilon = 2
>>> t = EFTBStatus.EF_TB
>>> stringify(divide(find_ACEEI_with_EFTB, instance=instance, initial_budgets=initial_budgets,
... delta=delta, epsilon=epsilon, t=t))
"{avi:['x', 'y'], beni:['y', 'z']}"

>>> instance = Instance(
... valuations={"avi":{"x":10, "y":20}, "beni":{"x":10, "y":20}},
... agent_capacities=1,
... item_capacities = {"x":1, "y":1})
>>> initial_budgets = {"avi":1.1, "beni":1}
>>> delta = 0.1
>>> epsilon = 0.2
>>> t = EFTBStatus.EF_TB
>>> stringify(divide(find_ACEEI_with_EFTB, instance=instance, initial_budgets=initial_budgets,
... delta=delta, epsilon=epsilon, t=t))
"{avi:['y'], beni:['x']}"

>>> instance = Instance(
... valuations={"avi":{"x":2}, "beni":{"x":3}},
... agent_capacities=1,
... item_capacities = {"x":1})
>>> initial_budgets = {"avi":1.1, "beni":1}
>>> delta = 0.1
>>> epsilon = 0.2
>>> t = EFTBStatus.EF_TB
>>> stringify(divide(find_ACEEI_with_EFTB, instance=instance,
... initial_budgets=initial_budgets,delta=delta, epsilon=epsilon, t=t))
"{avi:['x'], beni:[]}"

>>> instance = Instance(valuations={"avi":{"x":5, "y":4, "z":1},
... "beni":{"x":4, "y":6, "z":3}},
... agent_capacities=2,
... item_capacities={"x":1, "y":1, "z":2})
>>> initial_budgets = {"avi":5, "beni":4}
>>> delta = 0.5
>>> epsilon = 2
>>> t = EFTBStatus.CONTESTED_EF_TB
>>> stringify(divide(find_ACEEI_with_EFTB, instance=instance, initial_budgets=initial_budgets,
... delta=delta, epsilon=epsilon, t=t))
"{avi:['x', 'z'], beni:['y', 'z']}"
"""
# allocation = [[0 for _ in range(instance.num_of_agents)] for _ in range(instance.num_of_items)]
# 1) init prices vector to be 0
logger.info("START ACEEI")

initial_budgets = kwargs.get('initial_budgets')
delta = kwargs.get('delta')
epsilon = kwargs.get('epsilon')
t = kwargs.get('t')


prices = {key: 0 for key in alloc.remaining_items()}
clearing_error = 1
new_budgets = {}
while clearing_error:
# 2) 𝜖-budget perturbation
new_budgets, clearing_error, allocation, excess_demand_per_course = find_budget_perturbation(initial_budgets,
epsilon, prices,
alloc.instance, t)
# 3) If ∥𝒛˜(𝒖,𝒄, 𝒑, 𝒃) ∥2 = 0, terminate with 𝒑* = 𝒑, 𝒃* = 𝒃
if np.allclose(clearing_error, 0):
break
# 4) update 𝒑 ← 𝒑 + 𝛿𝒛˜(𝒖,𝒄, 𝒑, 𝒃), then go back to step 2.
for key in prices:
prices[key] += delta * excess_demand_per_course[key]
logger.info("UPDATE PRICES: %s", prices)

logger.info("Clearing error 0!")
for student, (price, bundle) in new_budgets.items():
logger.info(f"Giving {bundle} to {student}")
alloc.give_bundle(student, bundle)

# print the final budget (b* = new_budgets) for each student
final_budget = ""
for key, value in new_budgets.items():
final_budget += f"{key}: {value[0]}, "

# Remove the trailing comma and space
final_budget = final_budget.rstrip(", ")
logger.info(f"\nfinal budget b* = {final_budget}")
# print the final price (p* = prices) for each course
logger.info(f"\nfinal prices p* = {prices}")

# ---------------------helper functions:---------------------
def student_best_bundle_per_budget(prices: dict, instance: Instance, epsilon: any, initial_budgets: dict):
"""
Return a dict that says for each budget what is the bundle with the maximum utility that a student can take

:param different_budgets: different budgets that will give to every student different bundles
:param prices: courses prices
:param instance: a fair-course-allocation instance

:return matrix_a: that says for each budget what is the bundle with the maximum utility that a student can take

Example run 3 iteration 7
>>> instance = Instance(
... valuations={"Alice":{"x":5, "y":5, "z":1}, "Bob":{"x":4, "y":6, "z":4}},
... agent_capacities=2,
... item_capacities={"x":1, "y":2, "z":2})
>>> initial_budgets = {"Alice": 5, "Bob": 4}
>>> epsilon = 2
>>> prices = {"x": 2.5, "y": 0, "z": 0}
>>> student_best_bundle_per_budget(prices, instance, epsilon,initial_budgets)
{'Alice': {3: ('x', 'y')}, 'Bob': {2.5: ('x', 'y'), 2: ('y', 'z')}}

# Alice: 3-7: (10, [x,y] , p=2.5) (6, [x,z] p=2.5) (6, [y,z] p=0)
# BOB: 2-6: (10, [x,y] p=2,5), (10, [y,z] p=0) (8, [x,z] p=2.5)

Example run 6 iteration 5
>>> instance = Instance(
... valuations={"Alice":{"x":5, "y":4, "z":1}, "Bob":{"x":4, "y":6, "z":3}},
... agent_capacities=2,
... item_capacities={"x":1, "y":1, "z":2})
>>> initial_budgets = {"Alice": 5, "Bob": 4}
>>> epsilon = 2
>>> prices = {"x": 1.5, "y": 2, "z": 0}
>>> student_best_bundle_per_budget(prices, instance, epsilon,initial_budgets)
{'Alice': {3.5: ('x', 'y'), 3: ('x', 'z')}, 'Bob': {3.5: ('x', 'y'), 2: ('y', 'z')}}

# Alice: 3-7 -> (9, [x,y], p=3.5) (6, [x,z], p=1.5) (5, [y,z], p=2) (5 , x , p=1.5) (4, y, p=2) (1, z, p=0)
# Bob: 2-6 -> (10, [x,y]. p=3.5) , (9, [y,z], p=2) , (7, [x.z] , p=1.5) , (6, [y] p=1.5) , (4, [x]. p= 1.5), (3, [z]), p=0)


>>> instance = Instance(
... valuations={"Alice":{"x":1, "y":1, "z":3}},
... agent_capacities=2,
... item_capacities={"x":1, "y":1, "z":2})
>>> initial_budgets = {"Alice": 5}
>>> epsilon = 0.1
>>> prices = {"x": 2, "y": 2, "z": 5}
>>> student_best_bundle_per_budget(prices, instance, epsilon,initial_budgets)
{'Alice': {4.9: ('x', 'y')}}

"""

logger.info("START student_best_bundle_per_budget")
best_bundle_per_budget = {student: {} for student in instance.agents}
# logger.info("START combinations")
for student in instance.agents:

# Creating a list of combinations of courses up to the size of the student's capacity
combinations_courses_list = []
capacity = instance.agent_capacity(student)
for r in range(1, capacity + 1):
combinations_courses_list.extend(combinations(instance.items, r))
# logger.info(f"FINISH combinations for {student}")

# We would like to meet the requirement of the number of courses a student needs, therefore if
# the current combination meets the requirement we will give it more weight
large_num = instance.agent_maximum_value(student)

# Define a lambda function that calculates the valuation of a combination
valuation_function = lambda combination: instance.agent_bundle_value(student, combination) + (
large_num if len(combination) == instance.agent_capacity(student) else 0)

# Sort the combinations_set based on their valuations in descending order
combinations_courses_sorted = sorted(combinations_courses_list, key=valuation_function, reverse=True)

# Setting the min and max budget according to the definition
min_budget = initial_budgets[student] - epsilon
max_budget = initial_budgets[student] + epsilon

# Sort the combinations of the courses in descending order according to utility. We went through the
# budgets in descending order, for each budget we looked for the combination with the maximum value that
# could be taken in that budget.
min_price = float('inf')

for combination in combinations_courses_sorted:
price_combination = sum(prices[course] for course in combination)

if price_combination <= max_budget:
if price_combination <= min_budget:
best_bundle_per_budget.setdefault(student, {})[min_budget] = combination
break

if price_combination < min_price:
min_price = price_combination
best_bundle_per_budget.setdefault(student, {})[price_combination] = combination

return best_bundle_per_budget


def find_budget_perturbation(initial_budgets: dict, epsilon: float, prices: dict, instance: Instance, t: Enum):
# return: new_budgets, norma, allocation, excess_demand
logger.info("START find_budget_perturbation")
map_student_to_best_bundle_per_budget = student_best_bundle_per_budget(prices, instance, epsilon, initial_budgets)
new_budgets, clearing_error, excess_demand_per_course = lp.optimize_model(map_student_to_best_bundle_per_budget,
instance, prices, t, initial_budgets)
# logger.info(f"new_budgets in find_budget_perturbation: {new_budgets}")
return new_budgets, clearing_error, map_student_to_best_bundle_per_budget, excess_demand_per_course

if __name__ == "__main__":
import doctest
from fairpyx.adaptors import divide

# doctest.testmod()

# from fairpyx.adaptors import divide
#
# from fairpyx.utils.test_utils import stringify

# print(doctest.run_docstring_examples(find_ACEEI_with_EFTB, globals()))
#
# logger.addHandler(logging.StreamHandler())
# logger.setLevel(logging.INFO)
# logging.basicConfig(level=logging.WARNING)

# instance = Instance(
# valuations={"alice": {"CS161": 5, "ECON101": 3, "IR": 6},
# "bob": {"CS161": 3, "ECON101": 2, "IR": 0},
# "eve-1": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-2": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-3": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-4": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-5": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-6": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-7": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-8": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-9": {"CS161": 0, "ECON101": 10, "IR": 1},
# "eve-10": {"CS161": 0, "ECON101": 10, "IR": 1}},
# agent_capacities=2,
# item_capacities={"CS161": 1, "ECON101": 10, "IR": 100})
# initial_budgets = {"alice": 4.7, "bob": 4.4, "eve-1": 6, "eve-2": 1, "eve-3": 1, "eve-4": 1, "eve-5": 1, "eve-6": 1,
# "eve-7": 1, "eve-8": 1, "eve-9": 1, "eve-10": 1}
# delta = 0.5
# epsilon = 0.5
# t = EFTBStatus.EF_TB
#
# print(divide(find_ACEEI_with_EFTB, instance=instance, initial_budgets=initial_budgets, delta=delta, epsilon=epsilon,
# t=t))

instance = Instance(
valuations={"alice": {"CS161": 5, "ECON101": 3, "IR": 6}, "bob": {"CS161": 3, "ECON101": 5, "IR": 0},
"eve": {"CS161": 1, "ECON101": 10, "IR": 0}},
agent_capacities=2,
item_capacities={"CS161": 1, "ECON101": 1, "IR": 100000})
initial_budgets = {"alice": 2, "bob": 1, "eve": 4}
delta = 0.5
epsilon = 0.5
t = EFTBStatus.EF_TB
print(divide(find_ACEEI_with_EFTB, instance=instance, initial_budgets=initial_budgets, delta=delta, epsilon=epsilon,
t=t))
2 changes: 2 additions & 0 deletions fairpyx/algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from fairpyx.algorithms.iterated_maximum_matching import iterated_maximum_matching, iterated_maximum_matching_adjusted, iterated_maximum_matching_unadjusted
from fairpyx.algorithms.picking_sequence import round_robin, bidirectional_round_robin, serial_dictatorship
from fairpyx.algorithms.utilitarian_matching import utilitarian_matching
from fairpyx.algorithms.tabu_search import tabu_search
from fairpyx.algorithms.ACEEI import find_ACEEI_with_EFTB
from fairpyx.algorithms.Optimization_based_Mechanisms.OC import OC_function
from fairpyx.algorithms.Optimization_based_Mechanisms.SP_O import SP_O_function
from fairpyx.algorithms.Optimization_based_Mechanisms.SP import SP_function
Expand Down
Loading
Loading