2424import numpy as np
2525import os
2626
27- wordy = 1 # level of verbosity for print statements
27+ wordy = 2 # level of verbosity for print statements
2828
2929class Scheduler :
3030
@@ -387,13 +387,21 @@ def set_up_optimizer(self, goal : str = "cost"):
387387 self .b_eq_1 = np .zeros (self .A_eq_1 .shape [0 ], dtype = int )
388388
389389 if wordy > 1 :
390+ '''
390391 print("A_eq_1^T:")
391392 for i in range(self.Xta_start,self.Xta_end):
392393 pstring = str(self.X_indices[i])
393394 for column in self.A_eq_1.transpose()[i]:
394395 pstring += f"{ column:5}"
395396 print(pstring)
396397 print("b_eq_1: ", self.b_eq_1)
398+ '''
399+ print ("Constraint 1 details:" )
400+ for i , row in enumerate (self .A_eq_1 ):
401+ xta_idx = np .where (row == 1 )[0 ][0 ] - self .Xta_start
402+ t = xta_idx // self .A
403+ a = xta_idx % self .A
404+ print (f" Invalid pairing: Xta[{ t } ,{ a } ] = 0" )
397405
398406 A_eq_list .append (self .A_eq_1 )
399407 b_eq_list .append (self .b_eq_1 )
@@ -582,6 +590,52 @@ def set_up_optimizer(self, goal : str = "cost"):
582590 A_ub_list .append (self .A_ub_2 )
583591 b_ub_list .append (self .b_ub_2 )
584592
593+ if wordy > 1 :
594+ print ("Constraint 2 details:" )
595+ if hasattr (self , 'A_ub_2' ):
596+ for i , row in enumerate (self .A_ub_2 ):
597+ # Find the variables that are non-zero in this constraint
598+ xta_indices = np .where (row [self .Xta_start :self .Xta_start + self .T * self .A ] != 0 )[0 ]
599+ xts_indices = np .where (row [self .Xts_start :self .Xts_start + self .T * self .S ] != 0 )[0 ]
600+
601+ if len (xta_indices ) > 0 or len (xts_indices ) > 0 :
602+ constraint_parts = []
603+
604+ # Add Xta terms
605+ for xta_idx in xta_indices :
606+ coeff = row [self .Xta_start + xta_idx ]
607+ t = xta_idx // self .A
608+ a = xta_idx % self .A
609+ if coeff == 1 :
610+ constraint_parts .append (f"Xta[{ t } ,{ a } ]" )
611+ elif coeff == - 1 :
612+ constraint_parts .append (f"-Xta[{ t } ,{ a } ]" )
613+ else :
614+ constraint_parts .append (f"{ coeff } *Xta[{ t } ,{ a } ]" )
615+
616+ # Add Xts terms
617+ for xts_idx in xts_indices :
618+ coeff = row [self .Xts_start + xts_idx ]
619+ t = xts_idx // self .S
620+ s = xts_idx % self .S
621+ if coeff == 1 :
622+ constraint_parts .append (f"Xts[{ t } ,{ s } ]" )
623+ elif coeff == - 1 :
624+ constraint_parts .append (f"-Xts[{ t } ,{ s } ]" )
625+ else :
626+ constraint_parts .append (f"{ coeff } *Xts[{ t } ,{ s } ]" )
627+
628+ if constraint_parts :
629+ constraint_eq = " + " .join (constraint_parts ).replace ("+ -" , "- " )
630+ bound = self .b_ub_2 [i ]
631+ print (f" Dependency constraint: { constraint_eq } ≤ { bound } " )
632+
633+ if i >= 4 : # Limit output to avoid too much detail
634+ remaining = len (self .A_ub_2 ) - i - 1
635+ if remaining > 0 :
636+ print (f" ... and { remaining } more dependency constraints" )
637+ break
638+
585639 if wordy > 0 :
586640 print ("Constraint 2 built." )
587641
@@ -605,6 +659,7 @@ def set_up_optimizer(self, goal : str = "cost"):
605659 self .A_eq_3 [t , (self .Xta_start + t * self .A ):(self .Xta_start + t * self .A + self .A )] = 1 # Set the coefficients for the Xta variables to 1 for each task t
606660
607661 if wordy > 1 :
662+ '''
608663 print("A_eq_3^T:")
609664 print(" T1 T2") # Header for 2 tasks
610665 for i in range(self.Xta_start,self.Xta_end):
@@ -613,6 +668,11 @@ def set_up_optimizer(self, goal : str = "cost"):
613668 pstring += f"{ column:5}"
614669 print(pstring)
615670 print("b_eq_3: ", self.b_eq_3)
671+ '''
672+ print ("Constraint 3 details:" )
673+ for t in range (self .T ):
674+ asset_vars = [f"Xta[{ t } ,{ a } ]" for a in range (self .A )]
675+ print (f" Task { t } assignment: { ' + ' .join (asset_vars )} = 1" )
616676
617677 A_eq_list .append (self .A_eq_3 )
618678 b_eq_list .append (self .b_eq_3 )
@@ -643,6 +703,9 @@ def set_up_optimizer(self, goal : str = "cost"):
643703
644704 rows_4 = []
645705 bounds_4 = []
706+
707+ if wordy > 1 :
708+ print ('Constraint 4 details:' )
646709
647710 # For each individual asset, create constraints to prevent conflicts
648711 for individual_asset_idx in range (len (self .assets )):
@@ -689,7 +752,7 @@ def set_up_optimizer(self, goal : str = "cost"):
689752 bounds_4 .append (3 ) # Sum ≤ 3 prevents all 4 from being 1 simultaneously
690753
691754 if wordy > 1 :
692- print (f" Conflict constraint for { individual_asset_name } in period { period_idx } :" )
755+ # print(f" Conflict constraint for {individual_asset_name} in period {period_idx}:")
693756 print (f" Xta[{ task1 } ,{ ag1 } ] + Xta[{ task2 } ,{ ag2 } ] + Xtp[{ task1 } ,{ period_idx } ] + Xtp[{ task2 } ,{ period_idx } ] ≤ 3" )
694757
695758 # Create constraint matrix
@@ -701,6 +764,7 @@ def set_up_optimizer(self, goal : str = "cost"):
701764 self .A_ub_4 = np .zeros ((0 , num_variables ), dtype = int )
702765 self .b_ub_4 = np .array ([], dtype = int )
703766
767+ '''
704768 if wordy > 1:
705769 print("A_ub_4^T:")
706770 print(" P1 P2 P3 P4 P5") # Header for 5 periods
@@ -710,6 +774,7 @@ def set_up_optimizer(self, goal : str = "cost"):
710774 pstring += f"{ column:5}"
711775 print(pstring)
712776 print("b_ub_4: ", self.b_ub_4)
777+ '''
713778
714779 A_ub_list .append (self .A_ub_4 )
715780 b_ub_list .append (self .b_ub_4 )
@@ -740,6 +805,7 @@ def set_up_optimizer(self, goal : str = "cost"):
740805 self .b_ub_10 = np .ones (self .A_ub_10 .shape [0 ], dtype = int ) # Each infeasible combination: Xta + Xts <= 1
741806
742807 if wordy > 1 :
808+ '''
743809 print("A_ub_10^T:")
744810 print(" T1A1 T1A2 T2A1") # Header for 3 task-asset pairs example with T2A2 invalid
745811 for i in range(self.Xta_start,self.Xta_end):
@@ -753,6 +819,22 @@ def set_up_optimizer(self, goal : str = "cost"):
753819 pstring += f"{ column:5}"
754820 print(pstring)
755821 print("b_ub_10: ", self.b_ub_10)
822+ '''
823+ print ("Constraint 10 details:" )
824+ for i , row in enumerate (self .A_ub_10 ):
825+ # Find the Xta and Xts variables that are 1 in this row
826+ xta_indices = np .where (row [self .Xta_start :self .Xta_start + self .T * self .A ] == 1 )[0 ]
827+ xts_indices = np .where (row [self .Xts_start :self .Xts_start + self .T * self .S ] == 1 )[0 ]
828+
829+ if len (xta_indices ) > 0 and len (xts_indices ) > 0 :
830+ xta_idx = xta_indices [0 ]
831+ xts_idx = xts_indices [0 ]
832+ t_ta = xta_idx // self .A
833+ a = xta_idx % self .A
834+ t_ts = xts_idx // self .S
835+ s = xts_idx % self .S
836+ duration = self .task_asset_matrix [t_ta , a , 1 ]
837+ print (f" Task { t_ta } exceeds period limit: Xta[{ t_ta } ,{ a } ] + Xts[{ t_ts } ,{ s } ] ≤ 1 (start { s } + duration { duration } > { self .P } )" )
756838
757839 A_ub_list .append (self .A_ub_10 )
758840 b_ub_list .append (self .b_ub_10 )
@@ -938,6 +1020,7 @@ def set_up_optimizer(self, goal : str = "cost"):
9381020 b_ub_list .append (self .b_ub_14b )
9391021
9401022 if wordy > 1 :
1023+ '''
9411024 print("A_lb_14^T:")
9421025 print(" T1A1S1 T1A2S1 ...") # Header for 3 task-asset pairs example with T2A2 invalid
9431026 for i in range(self.Xta_start,self.Xta_end):
@@ -956,6 +1039,39 @@ def set_up_optimizer(self, goal : str = "cost"):
9561039 pstring += f"{ column:5}"
9571040 print(pstring)
9581041 print("b_lb_14: ", self.b_ub_14)
1042+ '''
1043+ print ("Constraint 14a details:" )
1044+ if hasattr (self , 'A_ub_14a' ):
1045+ for i , row in enumerate (self .A_ub_14a ):
1046+ xts_indices = np .where (row [self .Xts_start :self .Xts_start + self .T * self .S ] == 1 )[0 ]
1047+ xtp_indices = np .where (row [self .Xtp_start :self .Xtp_start + self .T * self .P ] == - 1 )[0 ]
1048+ if len (xts_indices ) > 0 and len (xtp_indices ) > 0 :
1049+ xts_idx = xts_indices [0 ]
1050+ xtp_idx = xtp_indices [0 ]
1051+ t_ts = xts_idx // self .S
1052+ s = xts_idx % self .S
1053+ t_tp = xtp_idx // self .P
1054+ p = xtp_idx % self .P
1055+ print (f" Start-period mapping: Xts[{ t_ts } ,{ s } ] - Xtp[{ t_tp } ,{ p } ] ≤ 0" )
1056+
1057+ print ("Constraint 14b details:" )
1058+ if hasattr (self , 'A_ub_14b' ):
1059+ for i , row in enumerate (self .A_ub_14b ):
1060+ xta_indices = np .where (row [self .Xta_start :self .Xta_start + self .T * self .A ] == 1 )[0 ]
1061+ xts_indices = np .where (row [self .Xts_start :self .Xts_start + self .T * self .S ] == 1 )[0 ]
1062+ xtp_indices = np .where (row [self .Xtp_start :self .Xtp_start + self .T * self .P ] == - 1 )[0 ]
1063+
1064+ if len (xta_indices ) > 0 and len (xts_indices ) > 0 and len (xtp_indices ) > 0 :
1065+ xta_idx = xta_indices [0 ]
1066+ xts_idx = xts_indices [0 ]
1067+ xtp_idx = xtp_indices [0 ]
1068+ t_ta = xta_idx // self .A
1069+ a = xta_idx % self .A
1070+ t_ts = xts_idx // self .S
1071+ s = xts_idx % self .S
1072+ t_tp = xtp_idx // self .P
1073+ p = xtp_idx % self .P
1074+ print (f" Duration enforcement: Xta[{ t_ta } ,{ a } ] + Xts[{ t_ts } ,{ s } ] - Xtp[{ t_tp } ,{ p } ] ≤ 1" )
9591075
9601076 if wordy > 0 :
9611077 print ("Constraint 14 built." )
@@ -979,13 +1095,19 @@ def set_up_optimizer(self, goal : str = "cost"):
9791095 self .A_eq_15 [t , (self .Xts_start + t * self .S ):(self .Xts_start + t * self .S + self .S )] = 1
9801096
9811097 if wordy > 1 :
1098+ '''
9821099 print("A_eq_15^T:")
9831100 for i in range(self.Xts_start,self.Xts_end):
9841101 pstring = str(self.X_indices[i])
9851102 for column in self.A_eq_15.transpose()[i]:
9861103 pstring += f"{ column:5}"
9871104 print(pstring)
9881105 print("b_eq_15: ", self.b_eq_15)
1106+ '''
1107+ print ("Constraint 15 details:" )
1108+ for t in range (self .T ):
1109+ start_vars = [f"Xts[{ t } ,{ s } ]" for s in range (self .S )]
1110+ print (f" Task { t } start assignment: { ' + ' .join (start_vars )} = 1" )
9891111
9901112 A_eq_list .append (self .A_eq_15 )
9911113 b_eq_list .append (self .b_eq_15 )
@@ -1025,6 +1147,18 @@ def set_up_optimizer(self, goal : str = "cost"):
10251147 A_eq_list .append (self .A_eq_16 )
10261148 b_eq_list .append (self .b_eq_16 )
10271149
1150+ if wordy > 1 :
1151+ print ("Constraint 16 details:" )
1152+ for t in range (self .T ):
1153+ period_vars = [f"Xtp[{ t } ,{ p } ]" for p in range (self .P )]
1154+ asset_terms = []
1155+ for a in range (self .A ):
1156+ duration = self .task_asset_matrix [t , a , 1 ]
1157+ if duration > 0 :
1158+ asset_terms .append (f"{ duration } *Xta[{ t } ,{ a } ]" )
1159+ if asset_terms :
1160+ print (f" Task { t } duration: { ' + ' .join (period_vars )} = { ' + ' .join (asset_terms )} " )
1161+
10281162 if wordy > 0 :
10291163 print ("Constraint 16 built." )
10301164
@@ -1080,6 +1214,32 @@ def set_up_optimizer(self, goal : str = "cost"):
10801214 A_ub_list .append (self .A_ub_17 )
10811215 b_ub_list .append (self .b_ub_17 )
10821216
1217+ if wordy > 1 :
1218+ print ("Constraint 17 details:" )
1219+ for i , row in enumerate (self .A_ub_17 ):
1220+ xta_indices = np .where (row [self .Xta_start :self .Xta_start + self .T * self .A ] == 1 )[0 ]
1221+ xtp_indices = np .where (row [self .Xtp_start :self .Xtp_start + self .T * self .P ] == 1 )[0 ]
1222+
1223+ if len (xta_indices ) > 0 and len (xtp_indices ) > 0 :
1224+ xta_idx = xta_indices [0 ]
1225+ xtp_idx = xtp_indices [0 ]
1226+ t_ta = xta_idx // self .A
1227+ a = xta_idx % self .A
1228+ t_tp = xtp_idx // self .P
1229+ p = xtp_idx % self .P
1230+
1231+ # Get weather info
1232+ period_weather = self .weather [p ] if p < len (self .weather ) else 0
1233+ asset_max_weather = self .asset_groups [a ].get ('max_weather' , float ('inf' ))
1234+
1235+ print (f" Weather constraint: Xta[{ t_ta } ,{ a } ] + Xtp[{ t_tp } ,{ p } ] ≤ 1 (weather { period_weather } > max { asset_max_weather } )" )
1236+
1237+ if i >= 4 : # Limit output to avoid too much detail
1238+ remaining = len (rows_17 ) - i - 1
1239+ if remaining > 0 :
1240+ print (f" ... and { remaining } more weather constraints" )
1241+ break
1242+
10831243 if wordy > 0 :
10841244 print (f"Constraint 17 built with { len (rows_17 )} weather restrictions." )
10851245 else :
0 commit comments