Skip to content

Commit 7f38a21

Browse files
committed
Updates to schedulerREADME to reflect new changes
- Finalizing updates to all the new constraints with a write up in the scheduler README, in order - Deleted all of Ryan's old constraints that I figured didn't apply any more (either didn't make sense, or were redundant) - Kept the numbering scheme the same for now - Need to address a problem in the future (probably) regarding the duration of tasks that have the same asset
1 parent e97942b commit 7f38a21

File tree

2 files changed

+92
-255
lines changed

2 files changed

+92
-255
lines changed

famodel/irma/scheduler.py

Lines changed: 2 additions & 189 deletions
Original file line numberDiff line numberDiff line change
@@ -269,37 +269,6 @@ def set_up_optimizer(self, goal : str = "cost"):
269269
b_eq_list = []
270270
b_lb_list = []
271271

272-
# 0) Total number of assignments needs to be less than or equal to the number of periods available
273-
'''
274-
the sum of the total amount of periods assigned to tasks cannot be more than the total number of periods available:
275-
(Xtp_00 + ... + Xtp_TP) <= P
276-
'''
277-
278-
# TODO: I dont know if this is necessary
279-
280-
"""
281-
# 1 row
282-
A_ub_0 = np.zeros((1, num_variables), dtype=int) # Every period assigned to a task counts as 1 towards the total assigned periods. This assumes one pair per period
283-
b_ub_0 = np.array([self.P], dtype=int)
284-
285-
# Set the coefficients for the Xtp variables to 1
286-
A_ub_0[0, self.Xtp_start:self.Xtp_end] = 1
287-
288-
if wordy > 1:
289-
print("A_ub_0^T:")
290-
for i in range(self.Xtp_start, self.Xtp_end):
291-
pstring = str(self.X_indices[i])
292-
for column in A_ub_0.transpose()[i]:
293-
pstring += f"{ column:5}"
294-
print(pstring)
295-
print("b_ub_0: ", b_ub_0)
296-
297-
A_ub_list.append(A_ub_0)
298-
b_ub_list.append(b_ub_0)
299-
300-
if wordy > 0:
301-
print("Constraint 0 built.")
302-
"""
303272
# 1) asset can only be assigned to a task if asset is capable of performing the task (value of pairing is non-negative)
304273
'''
305274
if task t cannot be performed by asset a, then Xta_ta = 0
@@ -541,13 +510,13 @@ def set_up_optimizer(self, goal : str = "cost"):
541510
# (This is automatic for binary variables but explicit for clarity)
542511
A_ub_4 = np.zeros((self.A * self.P, num_variables), dtype=int)
543512
b_ub_4 = np.ones(self.A * self.P, dtype=int)
544-
513+
'''
545514
row = 0
546515
for a in range(self.A):
547516
for p in range(self.P):
548517
A_ub_4[row, self.Xap_start + a * self.P + p] = 1 # Xap[a,p] ≤ 1
549518
row += 1
550-
519+
'''
551520
# Add temporal conflict prevention for tasks that could share assets
552521
# For each asset that multiple tasks could use, add constraints to prevent
553522
# simultaneous usage by different tasks
@@ -604,129 +573,6 @@ def set_up_optimizer(self, goal : str = "cost"):
604573
if wordy > 0:
605574
print("Constraint 4 built.")
606575

607-
# 5) Every task must be assigned to at least one time period
608-
'''
609-
Sum of all task-period pairs for each task must be >= 1:
610-
611-
(Xtp_00 + ... + Xtp_0P) >= 1 # for task 0
612-
(Xtp_10 + ... + Xtp_1P) >= 1 # for task 1
613-
...
614-
(Xtp_T0 + ... + Xtp_TP) >= 1 # for task T
615-
'''
616-
# NOTE: Constraint 5 is redundant with Constraint 16, which provides exact duration matching
617-
"""
618-
A_lb_5 = np.zeros((self.T, num_variables), dtype=int)
619-
b_lb_5 = np.ones(self.T, dtype=int)
620-
621-
for t in range (self.T):
622-
# set the coefficient for each task t to one
623-
A_lb_5[t, (self.Xtp_start + t * self.P):(self.Xtp_start + t * self.P + self.P)] = 1 # Set the coefficients for the Xtp variables to 1 for each task t
624-
625-
if wordy > 1:
626-
print("A_lb_5^T:")
627-
print(" T1 T2") # Header for 2 tasks
628-
for i in range(self.Xtp_start,self.Xtp_end):
629-
pstring = str(self.X_indices[i])
630-
for column in A_lb_5.transpose()[i]:
631-
pstring += f"{ column:5}"
632-
print(pstring)
633-
print("b_lb_5: ", b_lb_5)
634-
635-
A_lb_list.append(A_lb_5)
636-
b_lb_list.append(b_lb_5)
637-
638-
if wordy > 0:
639-
print("Constraint 5 built.")
640-
"""
641-
# 6) The total number of assets assigned cannot be greater than the number of assets available but must be greater than the number of tasks.
642-
'''
643-
Sum of all asset-period pairs must be >= T:
644-
645-
A >= (Xap_00 + ... + Xap_AP) >= T
646-
'''
647-
"""
648-
A_6 = np.zeros((1, num_variables), dtype=int)
649-
b_lb_6 = np.array([self.T], dtype=int)
650-
b_ub_6 = np.array([self.A], dtype=int)
651-
652-
A_6[0,self.Xap_start:self.Xap_end] = 1
653-
654-
if wordy > 1:
655-
print("A_6^T:")
656-
for i in range(self.Xap_start,self.Xap_end):
657-
pstring = str(self.X_indices[i])
658-
for column in A_6.transpose()[i]:
659-
pstring += f"{ column:5}"
660-
print(pstring)
661-
print("b_lb_6: ", b_lb_6)
662-
print("b_ub_6: ", b_ub_6)
663-
664-
A_lb_list.append(A_6)
665-
b_lb_list.append(b_lb_6)
666-
A_ub_list.append(A_6)
667-
b_ub_list.append(b_ub_6)
668-
669-
if wordy > 0:
670-
print("Constraint 6 built.")
671-
672-
# 7) Ensure tasks are assigned as early as possible
673-
'''
674-
A task cannot be assigned if it could have been assigned in an earlier period.
675-
This encourages the solver to assign tasks to the earliest possible periods.
676-
677-
Practical implementation: Rather than hard constraints (which can cause infeasibility),
678-
we add this preference to the objective function by giving later start times
679-
higher costs. This encourages early scheduling without making the problem infeasible.
680-
'''
681-
682-
# No hard constraints for Constraint 7 - implemented in objective function
683-
# The preference for earlier start times will be added as small penalties
684-
# in the objective function coefficients for Xts variables
685-
686-
if wordy > 0:
687-
print("Constraint 7 built (implemented as objective function preference).")
688-
689-
"""
690-
# 7) Ensure tasks are assigned as early as possible
691-
'''
692-
A task cannot be assigned if it could have been assigned in an earlier period. This encourages the solver to assign tasks to the earliest possible periods.
693-
'''
694-
695-
# 8) All tasks must be assigned to at least one time period
696-
'''
697-
698-
The sum of all task-period decision variables for each task must be greater than 1, indicating all tasks were assigned at least once:
699-
700-
(Xtp_00 + ... + Xtp_0P) >= 1 # for task 0
701-
(Xtp_10 + ... + Xtp_1P) >= 1 # for task 1
702-
...
703-
(Xtp_T0 + ... + Xtp_TP) >= 1 # for task T
704-
'''
705-
"""
706-
# num_tasks rows
707-
A_lb_8 = np.zeros((self.T, num_variables), dtype=int)
708-
b_lb_8 = np.ones(self.T, dtype=int)
709-
710-
A_lb_8[:,self.Xtp_start:self.Xtp_end] = 1
711-
712-
if wordy > 1:
713-
print("A_lb_8^T:")
714-
print(" T1 T2") # Header for 2 tasks
715-
for i in range(self.Xtp_start,self.Xtp_end):
716-
pstring = str(self.X_indices[i])
717-
for column in A_lb_8.transpose()[i]:
718-
pstring += f"{ column:5}"
719-
print(pstring)
720-
print("b_lb_8: ", b_lb_8)
721-
722-
A_lb_list.append(A_lb_8)
723-
b_lb_list.append(b_lb_8)
724-
725-
if wordy > 0:
726-
print("Constraint 8 built.")
727-
"""
728-
# 9) TODO: Empty constraint: fill me in later
729-
730576
# 10) A task duration plus the start-time it is assigned to must be less than the total number of time periods available
731577
'''
732578
This ensures that a task is not assigned to a period that would cause it to exceed the total number of periods available.
@@ -872,36 +718,6 @@ def set_up_optimizer(self, goal : str = "cost"):
872718
if wordy > 0:
873719
print("Constraint 12 built.")
874720

875-
# 13) The total number of asset period pairs must be greater than or equal to the number of task-period pairs
876-
'''
877-
This ensures that the 0 asset-period pairs solution is not selected
878-
879-
(Xap_00 + ... + Xap_AP) >= (Xtp_00 + ... + Xtp_TP) # for all periods p in range(0:P)
880-
'''
881-
"""
882-
A_lb_13 = np.zeros((self.P, num_variables), dtype=int)
883-
b_lb_13 = np.ones(self.P, dtype=int) * 2
884-
885-
for p in range(self.P):
886-
A_lb_13[p, (self.Xap_start + p * self.A):(self.Xap_start + p * self.A + self.A)] = 1
887-
A_lb_13[p, (self.Xtp_start + p):(self.Xtp_start + p + self.P)] = 1
888-
889-
if wordy > 1:
890-
print("A_lb_13^T:")
891-
print(" P1 P2 P3 P4 P5") # Header for 5 periods
892-
for i in range(self.Xtp_start,self.Xap_end):
893-
pstring = str(self.X_indices[i])
894-
for column in A_lb_13.transpose()[i]:
895-
pstring += f"{ column:5}"
896-
print(pstring)
897-
print("b_lb_13: ", b_lb_13)
898-
899-
A_lb_list.append(A_lb_13)
900-
b_lb_list.append(b_lb_13)
901-
902-
if wordy > 0:
903-
print("Constraint 13 built.")
904-
"""
905721
# 14) if a task-starttime pair is selected, the corresponding task-period pair must be selected for the period equal to the start time plus the duration of the task
906722
'''
907723
This ensures that if a task is assigned a start time, the corresponding task-period pair for the period equal to the start time plus the duration of the task is also selected.
@@ -997,9 +813,6 @@ def set_up_optimizer(self, goal : str = "cost"):
997813
print(pstring)
998814
print("b_lb_14: ", b_ub_14)
999815

1000-
#A_lb_list.append(A_lb_14)
1001-
#b_lb_list.append(b_lb_14)
1002-
1003816
if wordy > 0:
1004817
print("Constraint 14 built.")
1005818

0 commit comments

Comments
 (0)