Skip to content

Commit

Permalink
fix: made buffer a normal constraint
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgengaldal committed Aug 15, 2024
1 parent 21b9864 commit 236cd7c
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 37 deletions.
25 changes: 13 additions & 12 deletions algorithm/src/Modellering.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,52 +10,53 @@
## Variabler

`p`

- Person

`k`

- Komité

`t`

- Timeslot (Må gjøres til intervaller etter hvert)

`m(p, k, t)`

- Binær variabel
- Person `p` har møte med komité `k` i timeslot `t`

## Hjelpevariabler

`c(p, t)`

- Binære variabler
- Tidspunkt `t` passer for person `p`

`c(k, t)`

- Heltallsvariabel
- Kapasitet for komité `k` på tidspunkt `t` (hvor mange intervju de kan ha på det gitte tidspunktet)

## Begrensninger

For alle `p`:
<!-- `m(p, k_1, t_1) + m(p, k_2, t_2) < 2` for alle par `k`, hvor t_1 og t_2 overlapper - Dette blir først aktuelt etter at timeslots har ulike tidsintervaller -->
- `m(p, k, t) <= 1` dersom
- `p` har søkt på komité `k`
- `c(p, t) => 1`
- `c(k, t) => 1`

- `m(p, k, t_1) + m(p, k, t_2) < 2` for alle gyldige `k, t_1` og `k, t_2`, hvor t_1 og t_2 overlapper eller er innenfor et gitt buffer-intervall.
- `m(p, k, t) <= 1` dersom
- `p` har søkt på komité `k`
- `c(p, t) => 1`
- `c(k, t) => 1`
- `m(p, k, t) <= 0` ellers

For alle `k`:
- `sum(m(p, k, t)) <= c(k, t)` for alle personer `p` og tidspunkt `t`


- `sum(m(p, k, t)) <= c(k, t)` for alle personer `p` og tidspunkt `t`

## Mål

Maksimere `sum(m(p, k, t))` for alle `p`, `k` og `t`

### Sekundærmål

- La det være et gitt mellomrom mellom hvert intervju for samme person.

- [Ikke enda implementert] La det være færrest mulig og minst mulig mellomrom mellom intervjuene for komitéene.



28 changes: 3 additions & 25 deletions algorithm/src/mip_matching/match_meetings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@
from itertools import combinations


# Mål på hvor mye buffer skal vektlegges i matchingen (1 tilsvarer vekten av ett intervju)
APPLICANT_BUFFER_MODEL_WEIGHT = 1.5

# Hvor stort buffer man ønsker å ha mellom intervjuene
APPLICANT_BUFFER_LENGTH = timedelta(minutes=15)

Expand Down Expand Up @@ -53,39 +50,20 @@ def match_meetings(applicants: set[Applicant], committees: set[Committee]) -> Me
for interval in applicant.get_fitting_committee_slots(committee)) <= 1

# Legger inn begrensninger for at en søker ikke kan ha overlappende intervjutider
# og minst har et buffer mellom hvert intervju som angitt
for applicant in applicants:
potential_interviews: set[tuple[Committee, TimeInterval]] = set()
for applicant_candidate, committee, interval in m:
if applicant == applicant_candidate:
potential_interviews.add((committee, interval))

for interview_a, interview_b in combinations(potential_interviews, r=2):
if interview_a[1].intersects(interview_b[1]):
if interview_a[1].intersects(interview_b[1]) or interview_a[1].is_within_distance(interview_b[1], APPLICANT_BUFFER_LENGTH):
model += m[(applicant, *interview_a)] + \
m[(applicant, *interview_b)] <= 1

# Legger til sekundærmålsetning om at man skal ha mellomrom mellom perioder
distance_variables = set()

for applicant in applicants:
potential_committees_with_intervals: set[tuple[Committee, TimeInterval]] = set()
for applicant_candidate, committee, interval in m:
if applicant == applicant_candidate:
potential_committees_with_intervals.add((committee, interval))

# Trekker fra vekten dersom det prøves å planlegges et møte med mindre buffer enn ønsket
distance_variables.add(
mip.xsum(
-APPLICANT_BUFFER_MODEL_WEIGHT * (m[(applicant, *a)] and m[(applicant, *b)])
for a, b in combinations(potential_committees_with_intervals, r=2) # type: ignore
if a[0] != b[0] # Ikke intervju med samme komite (blir ordnet over)
and a[1].is_within_distance(b[1], APPLICANT_BUFFER_LENGTH) # Intervjuene er innenfor bufferlengden
)
)

# Setter mål til å være maksimering av antall møter
# med sekundærmål om buffer
model.objective = mip.maximize(mip.xsum(m.values()) + mip.xsum(distance_variables))
model.objective = mip.maximize(mip.xsum(m.values()))

# Kjør optimeringen
solver_status = model.optimize()
Expand Down

0 comments on commit 236cd7c

Please sign in to comment.