########################################################### # # # This file contains various classes and methods # # needed to handle threshold systems using either # # BDD or ROBDD methods # # # ########################################################### from c_bdd import BDDStructure from c_robdd import ROBDDStructure class BDDThreshold(BDDStructure): def __init__(self, w, wsum, th): super().__init__(len(w)) self.weights = w self.weightsum = wsum self.threshold = th def selectPivotIndex(self): max_w = -1 max_i = -1 for i in range(self.order): if self.weights[i] > max_w: max_w = self.weights[i] max_i = i self.pivotIndex = max_i def restriction(self): w = [] for i in range(self.order): if i != self.pivotIndex: w.append(self.weights[i]) wsum = self.weightsum - self.weights[self.pivotIndex] struct = BDDThreshold(w, wsum, self.threshold) for i in range(self.order): if i != self.pivotIndex: struct.addComponent(self.components[i]) return struct def contraction(self): w = [] for i in range(self.order): if i != self.pivotIndex: w.append(self.weights[i]) wsum = self.weightsum - self.weights[self.pivotIndex] struct = BDDThreshold(w, wsum, self.threshold - self.weights[self.pivotIndex]) for i in range(self.order): if i != self.pivotIndex: struct.addComponent(self.components[i]) return struct def isFunctioning(self): return self.threshold <= 0 def isFailed(self): return self.threshold > self.weightsum # If DO_SP_ADJUSTMENT is True, we check if the system is either a series or a parallel system. # If the system is a parallel system, the threshold is decreased to the minimum weight. # If the system is a series system, the threshold is increased to the weight sum. # This makes it possible to check if two systems are equivalent even if their thresholds are # different. This makes it possible to reduce the size of the ROBDD. DO_SP_ADJUSTMENT = True def SET_DO_SP_ADJUSTMENT(flag): global DO_SP_ADJUSTMENT DO_SP_ADJUSTMENT = flag class ROBDDThreshold(ROBDDStructure): def __init__(self, w, wsum, th): super().__init__(len(w)) self.weights = w self.weightsum = wsum self.threshold = th def restriction(self): w = [] for i in range(1, self.order): w.append(self.weights[i]) wsum = self.weightsum - self.weights[0] th = self.threshold # Check if the restriction is either a series or a parallel system, and adjust the threshold accordingly if self.order > 1 and DO_SP_ADJUSTMENT: wmin = min(w) if th > 0 and th <= wmin: th = wmin # A parallel system elif th <= wsum and th > wsum - wmin: th = wsum # A series system return ROBDDThreshold(w, wsum, th) def contraction(self): w = [] for i in range(1, self.order): w.append(self.weights[i]) wsum = self.weightsum - self.weights[0] th = self.threshold - self.weights[0] # Check if the contraction is either a series or a parallel system, and adjust the threshold accordingly if self.order > 1 and DO_SP_ADJUSTMENT: wmin = min(w) if th > 0 and th <= wmin: th = wmin # A parallel system elif th <= wsum and th > wsum - wmin: th = wsum # A series system return ROBDDThreshold(w, wsum, th) def isFunctioning(self): return self.threshold <= 0 def isFailed(self): return self.threshold > self.weightsum def isEquivalentTo(self, s): return self.threshold == s.threshold