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()
Exemple #3
0
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
Exemple #4
0
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()