-
Notifications
You must be signed in to change notification settings - Fork 48
fixed comments #38
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
base: master
Are you sure you want to change the base?
fixed comments #38
Changes from all commits
88c14db
a070a95
e2c4019
3bfa183
88985fa
5da495a
ada9a47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| from copy import deepcopy | ||
|
|
||
| class Course: | ||
| def __init__(self, name:str, price:float, max_capacity:int, capacity:int = 0) -> None: | ||
| self.name = name | ||
| self.price = price | ||
| self.capacity = capacity | ||
| self.max_capacity = max_capacity | ||
|
|
||
| def comperator(a, b): | ||
| return (a.capacity - a.max_capacity) - (b.capacity - b.max_capacity) | ||
|
|
||
|
|
||
| def __str__(self) -> str: | ||
| return f"course name: {self.name} capacity {self.capacity}/{self.max_capacity} and priced {self.price}" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| from copy import deepcopy | ||
| from Course import Course | ||
| class Student: | ||
| def __init__(self,name, budget, preferences, courses = [], year=1): | ||
| self.name = name | ||
| self.budget = budget | ||
| self.courses = courses | ||
| self.preferences = preferences | ||
| self.year = year | ||
|
|
||
| def __str__(self) -> str: | ||
| return self.name + " year: " + str(self.year) + "with budget of (" + str(self.budget) + ") \n" + str(self.courses) + "\n " + str(self.preferences) | ||
|
|
||
| def student_courses(self): | ||
| return f"student : {self.name} and courses " + str([c.name for c in self.courses]) | ||
|
|
||
| def comperator(a, b): | ||
| if(a.year - b.year == 0): | ||
| return (a.budget - b.budget) | ||
| return a.year - b.year |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| class TabuList: | ||
| def __init__(self, size): | ||
| self.size = size | ||
| self.items = [] | ||
|
|
||
| def add(self, item): | ||
| if item not in self.items: | ||
| self.items.append(item) | ||
| while len(self.items) > self.size: | ||
| self.items.pop(0) | ||
|
|
||
| def __iter__(self): | ||
| return iter(self.items) | ||
|
|
||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,232 @@ | ||
| ''' | ||
| Course Match: A Large-Scale Implementation of Approximate Competitive Equilibrium from Equal Incomes for Combinatorial Allocation | ||
| Published by:Eric Budish, Gérard P. Cachon, Judd B. Kessler, Abraham Othmanba | ||
| Link: https://pubsonline.informs.org/doi/epdf/10.1287/opre.2016.1544 | ||
| Heuristic search algorithm through price space, originally developed in Othman et al. 2010 | ||
| designed to give each student a fixed budget at first and try find the must corresponding | ||
| price vector to approximate competitive equilibrium with lowest clearing error. | ||
| programmers : Aviv Danino & Ori Ariel | ||
| ''' | ||
|
|
||
|
|
||
| from Course import Course | ||
| from Student import Student | ||
| from functools import cmp_to_key | ||
| from TabuList import TabuList | ||
| import numpy as np | ||
| import time | ||
| import random | ||
| import copy | ||
| import doctest | ||
|
|
||
|
|
||
| import logging | ||
| logger = logging.getLogger(__name__) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. כל השורות שמשנות את תצורת הלוג הגלובלית (בקובץ זה שורות 22-28, וכן בשאר הקבצים) לא צריכות להיות ביחידה, אלא רק בתוכנית הראשית. |
||
|
|
||
|
|
||
| def reset_update_prices(price_vector, courses): | ||
| ''' | ||
| reset prices of courses and capacity | ||
| >>> a = Course(name='a', price=0, max_capacity=5) | ||
| >>> b = Course(name='b', price=0, max_capacity=3) | ||
| >>> c = Course(name='c', price=0, max_capacity=5) | ||
| >>> courses = [a, b, c] | ||
|
|
||
| >>> s1 = Student(name='s1', budget=15, preferences=([c, b])) | ||
| >>> s2 = Student(name='s2', budget=15, preferences=([b, c, a])) | ||
| >>> s3 = Student(name='s3', budget=15, preferences=([b, a])) | ||
| >>> s4 = Student(name='s4', budget=15, preferences=([a, c])) | ||
| >>> s5 = Student(name='s5', budget=15, preferences=([a, b, c])) | ||
| >>> students = [s1, s2, s3, s4, s5] | ||
| >>> max_budget = 15 | ||
| >>> reset_update_prices([7,8,9], courses) | ||
| >>> [course.capacity for course in courses] | ||
| [0, 0, 0] | ||
| >>> [course.price for course in courses] | ||
| [7, 8, 9] | ||
| ''' | ||
| i = 0 | ||
| for course in courses: | ||
| course.capacity = 0 | ||
| course.price = price_vector[i] | ||
| i += 1 | ||
|
|
||
| def reset_students(students, max_budget: float): | ||
| ''' | ||
| reset budget and courses for students | ||
| >>> a = Course(name='a', price=0, max_capacity=5) | ||
| >>> b = Course(name='b', price=0, max_capacity=3) | ||
| >>> c = Course(name='c', price=0, max_capacity=5) | ||
| >>> courses = [a, b, c] | ||
|
|
||
| >>> s1 = Student(name='s1', budget=0, preferences=([c, b])) | ||
| >>> s2 = Student(name='s2', budget=0, preferences=([b, c, a])) | ||
| >>> s3 = Student(name='s3', budget=0, preferences=([b, a])) | ||
| >>> s4 = Student(name='s4', budget=0, preferences=([a, c])) | ||
| >>> s5 = Student(name='s5', budget=0, preferences=([a, b, c])) | ||
| >>> students = [s1, s2, s3, s4, s5] | ||
| >>> max_budget = 15 | ||
| >>> reset_students(students, max_budget) | ||
| >>> [student.budget for student in students] | ||
| [15, 15, 15, 15, 15] | ||
| >>> [student.courses for student in students] | ||
| [[], [], [], [], []] | ||
| ''' | ||
| for student in students: | ||
| student.budget = max_budget | ||
| student.courses = [] | ||
|
|
||
| def map_price_demand(price_vector, max_budget: float, students, | ||
| courses): | ||
| ''' | ||
| ****adding more documention about here | ||
| mapping price vector to demands of students | ||
| >>> a = Course(name='a', price=0, capacity = 0, max_capacity=5) | ||
| >>> b = Course(name='b', price=0, capacity = 0,max_capacity=3) | ||
| >>> c = Course(name='c', price=0, capacity = 0,max_capacity=5) | ||
| >>> courses = [a, b, c] | ||
|
|
||
| >>> s1 = Student(name='s1', budget=0, preferences=([c, b])) | ||
| >>> s2 = Student(name='s2', budget=0, preferences=([b, c, a])) | ||
| >>> s3 = Student(name='s3', budget=0, preferences=([b, a])) | ||
| >>> s4 = Student(name='s4', budget=0, preferences=([a, c])) | ||
| >>> s5 = Student(name='s5', budget=0, preferences=([a, b, c])) | ||
| >>> students = [s1, s2, s3, s4, s5] | ||
| >>> max_budget = 15 | ||
| >>> price_vector = [7,8,7] | ||
| >>> map_price_demand(price_vector, max_budget, students, courses) | ||
| >>> [str(course) for course in courses] | ||
| ['course name: a capacity 3/5 and priced 7', 'course name: b capacity 4/3 and priced 8', 'course name: c capacity 3/5 and priced 7'] | ||
| ''' | ||
| #different functions to each | ||
| #testing working for changes in function -- DELETE | ||
| reset_update_prices(price_vector, courses) | ||
| reset_students(students, max_budget) | ||
| def get_course(s:Student): | ||
| for preference in s.preferences: | ||
| if (s.budget >= preference.price and | ||
| preference not in s.courses): | ||
| s.courses.append(preference) | ||
| s.budget = s.budget - preference.price | ||
| preference.capacity += 1 | ||
| for student in students: | ||
| if (len(student.preferences) > len(student.courses)): | ||
| get_course(student) | ||
|
|
||
| #function returning alpha error | ||
| def alpha_error(price_vector, max_budget, students, courses): | ||
| map_price_demand(price_vector, max_budget, students, courses) | ||
| sum = 0 | ||
| for course in courses: | ||
| sum += (course.max_capacity - course.capacity)**2 | ||
| return sum | ||
|
|
||
| #return list of string representation of demands | ||
| ''' | ||
| >>> a = Course(name='a', price=0, capacity = 3, max_capacity=5) | ||
| >>> b = Course(name='b', price=0, capacity = 4,max_capacity=3) | ||
| >>> c = Course(name='c', price=0, capacity = 4,max_capacity=5) | ||
| >>> courses = [a, b, c] | ||
| >>> lst = get_demand_vector(courses) | ||
| >>> ["3/5", "4/3", "4/5"] | ||
| ''' | ||
| def get_demand_vector(courses): | ||
| lst = [] | ||
| for course in courses: | ||
| lst.append(f"{course.capacity}/{course.max_capacity}") | ||
| return lst | ||
|
|
||
|
|
||
| def algorithm1(students, courses, max_budget:float, time_to:float, seed:int = 3, counter = 0): | ||
| ''' | ||
| Heuristic search algorithm through price space, originally developed in Othman et al. 2010 | ||
| designed to give each student a fixed budget at first and try find the must corresponding | ||
| price vector to approximate competitive equilibrium with lowest clearing error. | ||
| programmers : Aviv Danino & Ori Ariel | ||
|
|
||
| counter : parameter designed to help for testing in different machines | ||
|
|
||
| >>> a = Course(name='a', price=0, capacity=0, max_capacity=5) | ||
| >>> b = Course(name='b', price=0, capacity=0, max_capacity=4) | ||
| >>> c = Course(name='c', price=0, capacity=0, max_capacity=5) | ||
| >>> courses = [a, b, c] | ||
| >>> s1 = Student(name='s1', budget=18, year=1, courses=[], preferences=([c, b])) | ||
| >>> s2 = Student(name='s2', budget=18, year=1, courses=[], preferences=([b, c, a])) | ||
| >>> s3 = Student(name='s3', budget=18, year=1, courses=[], preferences=([b, a])) | ||
| >>> s4 = Student(name='s4', budget=18, year=1, courses=[], preferences=([a, b, c])) | ||
| >>> s5 = Student(name='s5', budget=18, year=1, courses=[], preferences=([a, b, c])) | ||
| >>> s6 = Student(name='s6', budget=18, year=1, courses=[], preferences=([a, c, b])) | ||
| >>> students = [s1, s2, s3, s4, s5, s6] | ||
| >>> max_budget = 18 | ||
| >>> algorithm1(students, courses, max_budget, time_to= 2.0, seed = 3) | ||
| [4.86, 2.34, 6.66] | ||
| ''' | ||
| logger_counter = 0 | ||
| if time_to < 0.01: | ||
| logger.warning("to little time can crash the program") | ||
| pStar = [] | ||
| start_time = time.time() | ||
| best_error = float("inf") | ||
| #for better testing | ||
| random_state = np.random.RandomState(seed=3) | ||
| while(time.time() - start_time < time_to): | ||
| price_vector = [((random_state.randint(low=1,high=99)/100)*max_budget) for i in range(len(courses))] | ||
| search_error = alpha_error(price_vector, max_budget, students, courses) | ||
| tabu_list = TabuList(5) | ||
| c = 0 | ||
| while c < tabu_list.size: | ||
| queue = [] | ||
| for i in range(0, len(price_vector)): | ||
| temp = copy.deepcopy(price_vector) | ||
| temp[i] = (random_state.randint(low=1,high=99)/100)*max_budget | ||
| queue.append(temp) | ||
| queue = sorted(queue, key=lambda x: alpha_error(x, max_budget, students, courses)) | ||
| found_step = False | ||
| while(queue and not found_step):#3 | ||
| temp = queue.pop() | ||
| #need function for demand check in tabu list | ||
| map_price_demand(temp, max_budget, students, courses) | ||
| if get_demand_vector(courses) not in tabu_list: | ||
| logger.debug("%s", str(temp)) | ||
| found_step = True | ||
| #end of while 3 | ||
| if(not queue) : c = tabu_list.size | ||
| else: | ||
| price_vector = temp | ||
| #add the demands and not the price vector | ||
| current_error = alpha_error(price_vector, max_budget, students, courses) | ||
| demand_vector = get_demand_vector(courses) | ||
| tabu_list.add(demand_vector) | ||
| logger.debug(demand_vector) | ||
| if(current_error < search_error): | ||
| search_error = current_error | ||
| logger.debug("search error is %d", search_error) | ||
| c = 0 | ||
| else: | ||
| c = c + 1 | ||
| #end of if | ||
| if(current_error < best_error): | ||
| logger_counter += 1 | ||
| best_error = current_error | ||
| pStar = price_vector | ||
| logger.info("best error is %d ", best_error) | ||
| logger.debug("and its price vector is %s", pStar) | ||
| if(logger_counter == counter): | ||
| time_to = 0 | ||
| c = tabu_list.size | ||
|
|
||
| #end of if | ||
| #end of while 2 | ||
| #end of while 1 | ||
|
|
||
| logger.debug(logger_counter) | ||
| return pStar | ||
|
|
||
| algorithm1.logger = logger | ||
|
|
||
| if __name__=="__main__": | ||
| import pytest | ||
| #run algorithm and test of the algorithm | ||
| print(__file__) | ||
| # s1 = __file__[:-3] + "_test.py" | ||
| pytest.main(args=[__file__, __file__[:-3]+"_test.py"]) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| from algorithm1 import algorithm1,Course,Student,random,TabuList,copy,map_price_demand,reset_update_prices,cmp_to_key,reset_students,time | ||
|
|
||
| def pretty_testing(lst:list): | ||
| return [round(item, 2) for item in lst] | ||
|
|
||
| def test1(): | ||
| a = Course(name='a', price=0, max_capacity=5) | ||
| b = Course(name='b', price=0, max_capacity=3) | ||
| c = Course(name='c', price=0, max_capacity=5) | ||
| courses = [a, b, c] | ||
|
|
||
| s1 = Student(name='s1', budget=15, preferences=([c, b])) | ||
| s2 = Student(name='s2', budget=15, preferences=([b, c, a])) | ||
| s3 = Student(name='s3', budget=15, preferences=([b, a])) | ||
| s4 = Student(name='s4', budget=15, preferences=([a, c])) | ||
| s5 = Student(name='s5', budget=15, preferences=([a, b, c])) | ||
| students = [s1, s2, s3, s4, s5] | ||
| max_budget = 15 | ||
| assert(pretty_testing(algorithm1(students, courses, max_budget, time_to= 1, seed = 3, counter=4)) == [4.05, 1.95, 5.55]) | ||
|
|
||
| def test2(): | ||
| a = Course(name='a', price=0, max_capacity=3) | ||
| b = Course(name='b', price=0, max_capacity=3) | ||
| c = Course(name='c', price=0, max_capacity=3) | ||
| courses = [a, b, c] | ||
| s1 = Student(name='s1', budget=10, courses=[], preferences=([a])) | ||
| s2 = Student(name='s2', budget=10, courses=[], preferences=([b,a])) | ||
| s3 = Student(name='s3', budget=10, courses=[], preferences=([c])) | ||
| s4 = Student(name='s4', budget=10, courses=[], preferences=([c,b])) | ||
| s5 = Student(name='s5', budget=10, courses=[], preferences=([c, a, b])) | ||
| students = [s1, s2, s3, s4, s5] | ||
|
|
||
| max_budget = 10 | ||
| assert(pretty_testing(algorithm1(students, courses, max_budget, time_to= 1, seed = 3, counter=2)) == [2.7, 1.3, 3.7]) | ||
|
|
||
| def test3(): | ||
| a = Course(name='a', price=0, capacity=0, max_capacity=5) | ||
| b = Course(name='b', price=0, capacity=0, max_capacity=4) | ||
| c = Course(name='c', price=0, capacity=0, max_capacity=5) | ||
| d = Course(name='d', price=0, capacity=0, max_capacity=3) | ||
| e = Course(name='e', price=0, capacity=0, max_capacity=7) | ||
| f = Course(name='f', price=0, capacity=0, max_capacity=2) | ||
| courses = [a, b, c, d, e, f] | ||
| s1 = Student(name='s1', budget=18, year=1, courses=[], preferences=([c, b, e, f])) | ||
| s2 = Student(name='s2', budget=18, year=1, courses=[], preferences=([b, c, a, e])) | ||
| s3 = Student(name='s3', budget=18, year=1, courses=[], preferences=([b, a, d])) | ||
| s4 = Student(name='s4', budget=18, year=1, courses=[], preferences=([a, b, c])) | ||
| s5 = Student(name='s5', budget=18, year=1, courses=[], preferences=([d, a,e, b, c])) | ||
| s6 = Student(name='s6', budget=18, year=1, courses=[], preferences=([a, e,c,f, b])) | ||
| s7 = Student(name='s7', budget=18, year=1, courses=[], preferences=([c,d ,b])) | ||
| s8 = Student(name='s8', budget=18, year=1, courses=[], preferences=([b, c, a])) | ||
| s9 = Student(name='s9', budget=18, year=1, courses=[], preferences=([b,f,e, a])) | ||
| s10 = Student(name='s10', budget=18, year=1, courses=[], preferences=([d ,f])) | ||
| s11 = Student(name='s11', budget=18, year=1, courses=[], preferences=([d,e,f])) | ||
| s12 = Student(name='s12', budget=18, year=1, courses=[], preferences=([d,f,e])) | ||
| students = [s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12] | ||
| max_budget = 18 | ||
| assert(pretty_testing(algorithm1(students, courses, max_budget, time_to= 1, seed = 3, counter = 3)) == [3.96, 12.6, 9.9, 4.68, 1.08, 4.14])#7 | ||
|
|
||
| if __name__=="__main__": | ||
| import pytest | ||
| pytest.main(args=["fairpy/course_allocation"]) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. כמו שכתבתי לכם כבר (נראה לי): תשנו כאן ל: וכן בשאר הקבצים. כך שזה יעבוד על כל המחשבים בלי תלות במסלולים. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
יש להוסיף כאן (ובכל שאר הקבצים) את השם המלא של המאמר, שמות המחברים, וקישור למאמר.