def merge_func(list_of_input_streams, output_stream, func):
    def f(list_of_lists):
        return func(np.array(list_of_lists), axis=0)
    ## stream_agent(
    ##     inputs=list_of_input_streams, outputs=output_stream,
    ##     f_type ='list', f=f)
    lf(list_of_input_streams, output_stream, f)
from Stream import Stream
from Operators import lf, stream_agent
from examples_element_wrapper import print_stream

def h(x, weights, threshold):
    lst = [sum([weights[i]*v[i]
                for i in range(min(len(weights), len(x)))])
           for v in zip(*x)]
    above = [v for v in lst if v > threshold]
    below = [v for v in lst if v <= threshold]
    return (above, below)

u = Stream('u')
v = Stream('v')
w = Stream('w')
a = Stream('a')
b = Stream('b')

print_stream(u)
print_stream(v)
print_stream(w)
print_stream(a)
print_stream(b)

lf([u,v,w], [a,b], h, weights=(2,5,1), threshold=40)

u.extend(range(10,15))
v.extend(range(4))
w.extend(range(20, 25))
    y = list()
    z = list()
    for v in x:
        if bool_func(v):
            y.append(v)
        else:
            z.append(v)
    return (y, z)

# Function used as parameter bool_func
def g(v):
    return v > 5
    
# Create streams
x = Stream('x')
y = Stream('y')
z = Stream('z')
# Create printing agents
print_stream(x)
print_stream(y)
print_stream(z)

# Create agent using lf: list function
# single input stream: x, Output streams: y, z
# f = split_on_func, kwargs: {bool_func:g}
lf(x, [y, z], split_on_func, bool_func=g)

# Put random numbers into stream x to
# drive the computation.
x.extend([randint(0, 10) for _ in range(10)])
from examples_element_wrapper import print_stream
import numpy as np
""" Example of a list-wrapper to create an agent
with a single input stream and a single output stream.
The function that is wrapped is np.sin.

Illustrates: lf(x, y, np.sin)

"""
# CREATE STREAMS AND PRINTING AGENTS
# Create a stream x and call it 'input'
x = Stream('input')
# Create a stream y and call it 'sine of input'
y = Stream('sine of input')
# Create an agent that prints stream x
print_stream(x)
# Create an agent that prints stream y
print_stream(y)

# Create an agent that puts the sine of x into y.
lf(x, y, np.sin)

# ALTERNATIVE WAY OF SPECIFYING THE AGENT
#stream_agent(inputs=x, outputs=y, f_type='list', f=np.sin)

# Put elements into the input stream, x.
# As elements enter x, an agent will put elements into y, and
# the printer agents will print elements from x and y.
for _ in range(2):
    x.extend(np.linspace(0, np.pi, 8))
w = Stream('w')
a = Stream('sum')
b = Stream('mean')
c = Stream('variance')
d = Stream('all')
x = [ u, v, w]

# Create printing agents
print_stream(u)
print_stream(v)
print_stream(w)
print_stream(a)
print_stream(b)
print_stream(c)
print_stream(d)
# Create agents to put values into a,b,c,d
lf(x, a, np.sum, axis=0)
lf(x, b, np.mean, axis=0)
lf(x, c, np.var, axis=0)
lf(x, d, np.all, axis=0)

# Put elements into x
u.extend([random.randint(0,10) for _ in range(5)])
v.extend([random.randint(0,10) for _ in range(5)])
w.extend([random.randint(0,10) for _ in range(5)])




    
from Stream import Stream
from Operators import lf, stream_agent
from examples_element_wrapper import print_stream

def h(u):
    return [2*v[0]+v[1] for v in zip(*u)]

x = Stream('x')
y = Stream('y')
z = Stream('z')
print_stream(x)
print_stream(y)
print_stream(z)

lf([x,y], z, h)

x.extend(range(100, 104))
y.extend(range(5))

x.extend(range(200, 204))
y.extend(range(10, 15))
from Stream import Stream
from Operators import lf, stream_agent
from examples_element_wrapper import print_stream
import numpy as np
import random

x = Stream('x')
z = Stream('z')

print_stream(x)
print_stream(z)

def average(a, state):
        n, cum = state
        b = np.array(a)
        b[0] += cum
        b = np.cumsum(b)
        n_array = np.arange(n+1, n+len(b)+1, 1)
        avg = b/np.rint(n_array)
        state = (n_array[-1], b[-1])
        return (avg, state)
# Initial state is (0, 0.0).
lf(x, z, average, (0, 0.0))

#x.extend(range(10))
x.extend([random.randint(1, 4) for _ in range(10)])
from Stream import Stream
from Operators import lf, stream_agent
from examples_element_wrapper import print_stream
import numpy as np

x = Stream('x')
z = Stream('z')

print_stream(x)
print_stream(z)

def cumulative(a, state):
    b = np.array(a)
    b[0] += state
    b = np.cumsum(b)
    return (b, b[-1])

lf(x, z, cumulative, 0.0)

x.extend(range(5))
# Create streams
x = Stream('x')
y = Stream('y')
z = Stream('z')
a = Stream('sum')
b = Stream('mean')
c = Stream('variance')
d = Stream('all')

# Create printing agents
print_stream(x)
print_stream(y)
print_stream(z)
print_stream(a)
print_stream(b)
print_stream(c)
print_stream(d)

# Put elements into x
x.extend([random.randint(0,10) for _ in range(5)])
y.extend([random.randint(0,10) for _ in range(5)])
z.extend([random.randint(0,10) for _ in range(5)])

def execute_list_of_np_func(v, list_of_np_func):
    return ([f(v, axis=0) for f in list_of_np_func])

lf([x,y,z], [a,b,c,d], execute_list_of_np_func,
   list_of_np_func=[np.sum, np.mean, np.var, np.all])