def FairSelect(*guards): """ It sorts the list of guards in order based on the history for the chosen guards in this FairSelect located at a specific line in a specific process. Internally it invokes a priority select on the new order of guards. Timer and Skip guards are placed with lowest priority, since it does make sence to make them fair. """ alt_key = str(current_process_id()) + '_' + str( inspect.currentframe().f_back.f_lineno) A = AltHistory() H = A.get_history(alt_key) L = [] L_last = [] for item in guards: try: chan_name = item.g[0].channel.name if H.has_key(chan_name): L.append((H[chan_name], item.g)) else: L.append((0, item.g)) except AttributeError: try: L_last.append(item.g) except AttributeError: raise Exception( 'Can not use ' + str(item) + ' as guard. Only use *Guard types for AltSelect') L.sort() L = [x[1] for x in L] + L_last if pycsp.current.trace: import pycsp.common.trace as trace a = trace.Alternation(L) a.set_execute_frame(-3) else: a = Alternation(L) a.set_execute_frame(-2) result = a.execute() try: chan_name = result[0].channel.name A.update_history(alt_key, chan_name) except: # Can not record skip or timer guard. pass return result
def PriSelect(*guards): """ PriSelect is a wrapper to Alternation with a much more intuitive interface. It performs a prioritized choice from a list of guard objects and returns a tuple with the selected channel end and the read msg if there is one, otherwise None. >>> from __init__ import * >>> C = Channel() >>> cin = C.reader() >>> ch_end, msg = PriSelect(InputGuard(cin), SkipGuard()) >>> if ch_end == cin: ... print msg ... else: ... print msg == None True PriSelect supports skip, timeout, input and output guards. >>> @choice ... def callback(type, channel_input = None): ... print type, channel_input >>> A, B = Channel('A'), Channel('B') >>> cin, cout = A.reader(), B.writer() >>> g1 = InputGuard(cin, action=callback('input')) >>> g2 = OutputGuard(cout, msg=[range(10),range(100)], action=callback('output')) >>> g3 = TimeoutGuard(seconds=0.1, action=callback('timeout')) >>> _ = PriSelect(g1, g2, g3) timeout None Note that PriSelect always performs the guard that was chosen, i.e. channel input or output is executed within the PriSelect so even the empty choice with an PriSelect or where the results are simply ignored, still performs the guarded input or output. >>> L = [] >>> @choice ... def action(channel_input): ... L.append(channel_input) >>> @process ... def P1(cout, n=5): ... for i in range(n): ... cout(i) >>> @process ... def P2(cin1, cin2, n=10): ... for i in range(n): ... _ = AltSelect( InputGuard(cin1, action=action()), InputGuard(cin2, action=action()) ) >>> C1, C2 = Channel(), Channel() >>> Parallel(P1(C1.writer()), P1(C2.writer()), P2(C1.reader(), C2.reader())) >>> len(L) 10 >>> L.sort() >>> L [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] """ L = [] # Build guard list for item in guards: try: L.append(item.g) except AttributeError: raise Exception( 'Cannot use ' + str(item) + ' as guard. Only use *Guard types for Pri/AltSelect') if pycsp.current.trace: import pycsp.common.trace as trace a = trace.Alternation(L) a.set_execute_frame(-3) else: a = Alternation(L) a.set_execute_frame(-2) return a.execute()
def FairSelect(*guards): """ FairSelect(G1, [G2, .. ,GN]) FairSelect sorts the list of guards in order based on the history for the chosen guards in this FairSelect. Internally it invokes a priority select on the new order of guards. Timer and Skip guards are always given lowest priority. Usage: >>> g,msg = FairSelect(InputGuard(cin1), InputGuard(cin2)) >>> print("Message:%s" % (str(msg))) Returns: ChannelEnd, message More detailed usage: see help(pycsp.AltSelect) """ alt_key = str(current_process_id()) + '_' + str(inspect.currentframe().f_back.f_lineno) A = AltHistory() H = A.get_history(alt_key) L = [] L_last = [] def add(obj): try: chan_name = obj.g[0].channel.name if chan_name in H: L.append((H[chan_name], obj.g)) else: L.append((0, obj.g)) except AttributeError: try: L_last.append(obj.g) except AttributeError: raise InfoException('Can not use ' + str(item) + ' as guard. Only use *Guard types for AltSelect') # Add and organise 2 levels for item in guards: if type(item) == list: for item2 in item: add(item2) else: add(item) L.sort() L = [x[1] for x in L] + L_last if pycsp.current.trace: import pycsp.common.trace as trace a = trace.Alternation(L, ensurePriority=True) a._set_execute_frame(-3) else: a = Alternation(L, ensurePriority=True) a._set_execute_frame(-2) result = a.execute() try: chan_name = result[0].channel.name A.update_history(alt_key, chan_name) except: # Can not record skip og timer guard. pass return result
def AltSelect(*guards): """ AltSelect(G1, [G2, .. ,GN]) AltSelect performs a fast choice from a list of guard objects and returns a tuple with the selected channel end and the read msg if there is one, otherwise None. Usage: >>> g,msg = AltSelect(InputGuard(cin1), InputGuard(cin2)) >>> print("Message:%s" % (str(msg))) Returns: ChannelEnd, message More detailed usage: AltSelect supports skip, timeout, input and output guards. Though, it is recommended to use the slightly slower PriSelect when using skip guards. >>> @choice ... def callback(type, channel_input = None): ... print type, channel_input >>> A, B = Channel('A'), Channel('B') >>> cin, cout = A.reader(), B.writer() >>> g1 = InputGuard(cin, action=callback('input')) >>> g2 = OutputGuard(cout, msg=[range(10),range(100)], action=callback('output')) >>> g3 = TimeoutGuard(seconds=0.1, action=callback('timeout')) >>> _ = AltSelect(g1, g2, g3) timeout None Note that AltSelect always performs the guard that was chosen, i.e. channel input or output is executed within the AltSelect so even the empty choice with an AltSelect or where the results are simply ignored, still performs the guarded input or output. >>> L = [] >>> @choice ... def action(channel_input): ... L.append(channel_input) >>> @process ... def P1(cout, n=5): ... for i in range(n): ... cout(i) >>> @process ... def P2(cin1, cin2, n=10): ... for i in range(n): ... _ = AltSelect( InputGuard(cin1, action=action()), InputGuard(cin2, action=action()) ) >>> C1, C2 = Channel(), Channel() >>> Parallel(P1(C1.writer()), P1(C2.writer()), P2(C1.reader(), C2.reader())) >>> len(L) 10 >>> L.sort() >>> L [0, 0, 1, 1, 2, 2, 3, 3, 4, 4] """ L = [] # Build guard list for item in guards: try: if type(item) == list: for item2 in item: L.append(item2.g) else: L.append(item.g) except AttributeError: if type(item)==list: raise InfoException('Cannot use ' + str(item2) + ' as guard. Only use *Guard types for AltSelect') else: raise InfoException('Cannot use ' + str(item) + ' as guard. Only use *Guard types for AltSelect') if pycsp.current.trace: import pycsp.common.trace as trace a = trace.Alternation(L) a._set_execute_frame(-3) else: a = Alternation(L) a._set_execute_frame(-2) return a.execute()