Skip to content

Commit

Permalink
Merge pull request #265 from appKom/264-favoriser-mellomrom-mellom-in…
Browse files Browse the repository at this point in the history
…tervjuer-for-søker

264 Krev buffer mellom intervjuer for søker
  • Loading branch information
jorgengaldal authored Aug 15, 2024
2 parents fd42e13 + 236cd7c commit 2a15799
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 8 deletions.
24 changes: 17 additions & 7 deletions algorithm/src/Modellering.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +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

- [Ikke enda implementert] La det være færrest mulig og minst mulig mellomrom mellom intervjuene for komitéene.
3 changes: 3 additions & 0 deletions algorithm/src/mip_matching/TimeInterval.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ def get_contained_slots(self, slots: list[TimeInterval]):
def divide(self, length: timedelta) -> list[TimeInterval]:
return TimeInterval.divide_interval(self, length)

def is_within_distance(self, other: TimeInterval, distance: timedelta) -> bool:
return (self.end <= other.start and self.end + distance > other.start) or (other.end <= self.start and other.end + distance > self.start)

@staticmethod
def divide_interval(interval: TimeInterval, length: timedelta) -> list[TimeInterval]:
"""
Expand Down
8 changes: 7 additions & 1 deletion algorithm/src/mip_matching/match_meetings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@
from mip_matching.Applicant import Applicant
import mip

from datetime import timedelta
from itertools import combinations


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


class MeetingMatch(TypedDict):
"""Type definition of a meeting match object"""
solver_status: mip.OptimizationStatus
Expand Down Expand Up @@ -45,14 +50,15 @@ 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

Expand Down

0 comments on commit 2a15799

Please sign in to comment.