def sim_in_and_out(n,latencies,traces,outfiles):
    print "Simulating In and Out multi-path scheme..."
    traces_file = natsorted(glob.glob(traces[0]+'/*.cell'))
    # By default ind and out makes only one out traffic and n-1 in traffic in a random manner
    for instance_file in traces_file: 
        instance = open(instance_file,'r')
        instance = instance.read().split('\n')[:-1]
        # Get n circuits latencies as a multipath virtual structure of the same client for this instance
        mplatencies = getCircuitLatencies(latencies, n)	# it is a list of list of latencies for each of m circuits. length = m
        routes = []
        routes_client = []
        routes_server = []
        for i in xrange(0,len(instance)):
            packet = instance[i]
            packet = packet.replace(' ','\t') #For compatibility when data is space sperated not tab separated
            direction = multipath.getDirfromPacket(packet)

            if (direction == 1): # if it is outgoing set a fixed route
                routes_server.append(-1) # Just to know that for this packet the exit does not decide the route
                routes_client.append(0) 
            if (direction == -1): # if it is incomming just sent through a random route, it'd better trying to have same amount of 
                routes_server.append(1) # Just to know that for this packet the exit does not decide the route
                routes_client.append(-1)
        routes = multipath.joingClientServerRoutes(routes_client,routes_server)
        ##### Routes Created, next to the multipath simulation
        new_instance = multipath.simulate(instance,mplatencies,routes) # Simulate the multipath effect for the given latencies and routes
        saveInFile2(instance_file,new_instance,routes,outfiles)
def sim_weighted_random(n,latencies,traces,outfiles,weights,alphas):
    print "Simulating Weighted Random multi-path scheme... alphas:", alphas
    traces_file = natsorted(glob.glob(traces[0]+'/*.cell'))
    for instance_file in traces_file: 
        instance = open(instance_file,'r')
        instance = instance.read().split('\n')[:-1]
        w_out = multipath.getWeights(n,alphas)
        w_in = multipath.getWeights(n,alphas)
        # Get n circuits latencies as a multipath virtual structure of the same client for this instance
        mplatencies = getCircuitLatencies(latencies, n)	# it is a list of list of latencies for each of m circuits. length = m
        # for each instance I need to create a new randomly created weights vector
        routes_server = []
        routes_client = []
        last_client_route =  np.random.choice(np.arange(0,n),p = w_out)
        last_server_route = np.random.choice(np.arange(0,n),p = w_in)
        routes = []
        for i in xrange(0,len(instance)):
            packet = instance[i]
            packet = packet.replace(' ','\t') #For compatibility when data is space sperated not tab separated
            direction = multipath.getDirfromPacket(packet)			
            if (direction == 1):
                    routes_server.append(-1) # Just to know that for this packet the exit does not decide the r$
                    last_client_route =  np.random.choice(np.arange(0,n),p = w_out)
                    routes_client.append(last_client_route)

            if (direction == -1):
                    routes_client.append(-1) # Just to know that for this packet the client does not decide the$
                    last_server_route =  np.random.choice(np.arange(0,n),p = w_in)
                    routes_server.append(last_server_route)

        routes = multipath.joingClientServerRoutes(routes_client,routes_server)
        ##### Routes Created, next to the multipath simulation
        new_instance = multipath.simulate(instance,mplatencies,routes) # Simulate the multipath effect for the give$
        saveInFile2(instance_file,new_instance,routes,outfiles)
def sim_bwr_blocked(n,latencies,traces,outfiles,range_):
    print "Simulating BWR multi-path scheme blocking last selected route..."
    print traces
    traces_file = natsorted(glob.glob(traces[0]+'/*.cell'))
    ranlow = int(range_.split(',')[0])
    ranhigh = int(range_.split(',')[1])

    for instance_file in traces_file:
        w_out = multipath.getWeights(n)
        w_in = multipath.getWeights(n)
        instance = open(instance_file,'r')
        instance = instance.read().split('\n')[:-1]
        mplatencies = getCircuitLatencies(latencies, n)	# it is a list of list of latencies for each of m circuits. length = m
        routes_client = []
        routes_server = []
        sent_incomming = 0
        sent_outgoing = 0
        last_client_route =  np.random.choice(np.arange(0,n),p = w_out)
        last_server_route = np.random.choice(np.arange(0,n),p = w_in)

        for i in xrange(0,len(instance)):
            packet = instance[i]
            packet = packet.replace(' ','\t') #For compatibility when data is space sperated not tab separated
            direction = multipath.getDirfromPacket(packet)

            if (direction == 1):
                routes_server.append(-1) # Just to know that for this packet the exit does not decide the route
                sent_outgoing += 1
                C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
                routes_client.append(last_client_route) 
                if (sent_outgoing % C == 0): #After C cells are sent, change the circuits
                    while(1):
                        client_route =  np.random.choice(np.arange(0,n),p = w_out)
                        if (client_route != last_client_route):
                            last_client_route = client_route
                            break # In this way, we block the possibility of choosing the same circuit previously chosen
                            
            if (direction == -1): 
                routes_client.append(-1) # Just to know that for this packet the client does not decide the route
                routes_server.append(last_server_route)
                sent_incomming += 1
                C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
                if (sent_incomming % C == 0): #After C cells are sent, change the circuits
                    while(1):
                        server_route =  np.random.choice(np.arange(0,n),p = w_in)
                        if (server_route != last_server_route):
                            last_server_route = server_route
                            break # In this way, we block the possibility of choosing the same circuit previously chosen

        routes = multipath.joingClientServerRoutes(routes_client,routes_server)
        ##### Routes Created, next to the multipath simulation
        new_instance = multipath.simulate(instance,mplatencies,routes) # Simulate the multipath effect for the given latencies and routes
        saveInFile2(instance_file,new_instance,routes,outfiles)
def sim_bwr_var_paths(n,nmin,latencies,traces,outfiles,range_, alphas):
    print "Simulating bwr with variable number of paths", nmin, n
    traces_file = natsorted(glob.glob(traces[0]+'/*.cell'))
    ranlow = int(range_.split(',')[0])
    ranhigh = int(range_.split(',')[1])
    for instance_file in traces_file:
	## First lets choose the number of circuits randomly
        n_random = random.randint(nmin,n)
        alphas = np.ones(n_random)
        alphas = alphas.astype(str)
        alphas = ','.join(alphas)
        w_out = multipath.getWeights(n_random, alphas)
        w_in = multipath.getWeights(n_random, alphas)
        instance = open(instance_file,'r')
        instance = instance.read().split('\n')[:-1]
        mplatencies = getCircuitLatencies(latencies, n_random)
        routes_client = []
        routes_server = []
        sent_incomming = 0
        sent_outgoing = 0
        last_client_route =  np.random.choice(np.arange(0,n_random),p = w_out)
        last_server_route = np.random.choice(np.arange(0,n_random),p = w_in)
        #C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
        for i in xrange(0,len(instance)):
            packet = instance[i]
            packet = packet.replace(' ','\t') #For compatibility when data is space sperated not tab separated
            direction = multipath.getDirfromPacket(packet)
            if (direction == 1):
                routes_server.append(-1) # Just to know that for this packet the exit does not decide the r$
                sent_outgoing += 1
                C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
                routes_client.append(last_client_route)
                if (sent_outgoing % C == 0): #After C cells are sent, change the circuits
                    last_client_route =  np.random.choice(np.arange(0,n_random),p = w_out)
            if (direction == -1):
                routes_client.append(-1) # Just to know that for this packet the client does not decide the$
                routes_server.append(last_server_route)
                sent_incomming += 1
                C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
                if (sent_incomming % C == 0): #After C cells are sent, change the circuits
                    last_server_route = np.random.choice(np.arange(0,n_random),p = w_in) 

        routes = multipath.joingClientServerRoutes(routes_client,routes_server)
        #### Routes Created, next to the multipath simulation
        new_instance = multipath.simulate(instance,mplatencies,routes) # Simulate the multipath effect for the give$
        saveInFile2(instance_file,new_instance,routes,outfiles)
def sim_bwr_var_paths_strict(n,nmin,latencies,traces,outfiles,range_):
    ## Take the dataset and do: m=2 to 20%, m=3 to 20%, m=4 to 20% and m=5 to 20% of the whole dataset.
    ## It means that e.g., BWR2-5 Strict has almost 20% of instances split into two parts, 20% into three and so on
    ## BWR 4-5 Strict schould have 50/50 % to m=4 and m=5. However, experimentally we obtained couple of dozens of samples divided into m=2, and m=3.
    print "Simulating bwr with variable number of paths strict to avoid less than nmin Cmax and Cmind should be reduced to 15-20"
    traces_file = natsorted(glob.glob(traces[0]+'/*.cell'))
    ranlow = int(range_.split(',')[0])
    ranhigh = int(range_.split(',')[1])
    number_of_traces = len(traces_file)
    #print number_of_traces, n, nmin
    chunks_dataset = 100 / (n - nmin + 1)
    n_sel = []
    #print chunks_dataset
    for i in range(nmin,n+1):
            n_sel.extend([i] * chunks_dataset)
    #print n_sel, len(n_sel)
    #print n_sel
    kk = 0
    for instance_file in traces_file:
        ## First lets choose the number of circuits randomly
        #print instance_file, "divided into",
        n_random =  n_sel[kk%len(n_sel)]
        kk += 1 
        #print n_random, instance_file
        w_out = multipath.getWeights(n_random)
        w_in = multipath.getWeights(n_random)
        instance = open(instance_file,'r')
        instance = instance.read().split('\n')[:-1]
        mplatencies = getCircuitLatencies(latencies, n_random)
        routes_client = []
        routes_server = []
        sent_incomming = 0
        sent_outgoing = 0
        last_client_route =  np.random.choice(np.arange(0,n_random),p = w_out)
        last_server_route = np.random.choice(np.arange(0,n_random),p = w_in)
        #C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
        for i in xrange(0,len(instance)):
            packet = instance[i]
            packet = packet.replace(' ','\t') #For compatibility when data is space sperated not tab separated
            direction = multipath.getDirfromPacket(packet)
            if (direction == 1):
                routes_server.append(-1) # Just to know that for this packet the exit does not decide the r$
                sent_outgoing += 1
                C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
                routes_client.append(last_client_route)
                if (sent_outgoing % C == 0): #After C cells are sent, change the circuits
                    while(1):
                        client_route =  np.random.choice(np.arange(0,n_random),p = w_out)
                        if (client_route != last_client_route):
                            last_client_route = client_route
                            break # In this way, we block the possibility of choosing the same circuit previously chosen
                    
            if (direction == -1):
                routes_client.append(-1) # Just to know that for this packet the client does not decide the$
                routes_server.append(last_server_route)
                sent_incomming += 1
                C = random.randint(ranlow,ranhigh) #After how many cells the scheduler sets new weights
                if (sent_incomming % C == 0): #After C cells are sent, change the circuits
                    while(1):
                        server_route =  np.random.choice(np.arange(0,n_random),p = w_in)
                        if (server_route != last_server_route):
                            last_server_route = server_route
                            break # In this way, we block the possibility of choosing the same circuit previously chosen
        
        routes = multipath.joingClientServerRoutes(routes_client,routes_server)
        #### Routes Created, next to the multipath simulation
        new_instance = multipath.simulate(instance,mplatencies,routes) # Simulate the multipath effect for the give$
        saveInFile2(instance_file,new_instance,routes,outfiles)