Commit 35314212 authored by Ashkan's avatar Ashkan
Browse files

Backup.

parent ee6ddf8b
Loading
Loading
Loading
Loading

prrt/HecSearch.py

deleted100644 → 0
+0 −288
Original line number Diff line number Diff line
from abc import ABC, abstractmethod
import prrt
import math


class AbstractSearch(ABC):
    @abstractmethod
    def search(self):
        pass


class HECFullSearch(AbstractSearch):
    def __init__(self, n_p_min, n_p_max, prrtApplicationParameters, prrtChannelParameters, prrtSystemParameters):
        self.n_max = 255
        self.step_size = 2 # Step size in the estimation of the optimum code word length
        self.n_p_min = n_p_min
        self.n_p_max = n_p_max
        self.prrtApplicationParameters = prrtApplicationParameters
        self.prrtChannelParameters = prrtChannelParameters
        self.prrtSystemParameters = prrtSystemParameters
        self.p_t = self.prrtApplicationParameters.max_residual_loss_rate
        self.is_order_ascending = False
        pass

    def search(self):
        ri_opt = math.inf
        k_opt = 0
        n_opt = 0
        n_p_opt = []
        # Eq.5.9, page 125
        fec_delay_min = self.prrtSystemParameters.source_packet_interval + \
                        self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay + \
                        (self.prrtChannelParameters.rtt_prop_fwd + self.prrtSystemParameters.processing_delay) / 2 + \
                        self.prrtSystemParameters.packet_loss_detection_delay
        # Eq.5.9 page 125 assumung D_sup = 0
        req_delay = self.prrtChannelParameters.rtt_prop_fwd + \
                    self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay + \
                    self.prrtSystemParameters.processing_delay
        # Eq.5.10, page 125
        n_c_max = math.ceil((self.prrtApplicationParameters.max_latency - fec_delay_min) / req_delay)
        # self.k_lim = somewhat(prrtApplicationParameters.loss_tolerance, self.n_max)

        # n_c = 0 is the proactive packet
        for n_c in range(n_c_max):
            # Eq.5.11, k(Nc, D_T), page 125
            k_max = min(self.get_k(n_c, req_delay), self.get_k_lim(1, self.n_max))
            for k in range(1, k_max + 1):
                n = self.estimate_n_for_k(k)
                repair_schedules = prrt.gen_repair_schedule(n - k, n_c, 1, self.n_p_max, self.is_order_ascending)
                for repair_schedule in repair_schedules:
                    coding_conf = prrt.PrrtCodingConfiguration(n, k, repair_schedule)
                    ri = coding_conf.get_redundant_information(self.prrtChannelParameters)
                    if ri < ri_opt:
                        k_opt = k
                        n_opt = n
                        n_p_opt = repair_schedule
        return prrt.PrrtCodingConfiguration(n_opt, k_opt, n_p_opt)

    def get_k(self, n_c, req_delay):
        return math.ceil((self.prrtApplicationParameters.max_latency -
                   self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay -
                   (self.prrtChannelParameters.rtt_prop_fwd + self.prrtSystemParameters.processing_delay) / 2 -
                   self.prrtSystemParameters.packet_loss_detection_delay -
                   n_c * req_delay) / self.prrtSystemParameters.source_packet_interval)

    def get_k_lim(self, start, end):
        mid_point = math.ceil((end - start) / 2)
        p_r = self.get_max_coding_block_length(mid_point)
        if p_r == self.p_t:
            return mid_point
        elif p_r  > self.p_t:
            self.get_k_lim(start, mid_point - 1)
        else:
            self.get_k_lim(mid_point + 1, end)

    # Pr(k, n_max)
    def get_max_coding_block_length(self, k):
        total_packet_erasure = 0
        for i in range(1, k):
            for j in range(max(self.n_max - k + 1, i), self.n_max - k + i):
                packet_erasure_at_i = i * self.hypergeometric_distribution(self.n_max, k, i, j) * self.get_error_prob(
                    j, self.n_max, self.prrtChannelParameters.loss_rate_fwd)
                total_packet_erasure += packet_erasure_at_i
        return (1 / k) * total_packet_erasure

    def estimate_n_for_k(self, k):
        n = k + 1
        while self.residual_packet_erasure_rate(k, n, self.prrtApplicationParameters, self.prrtChannelParameters) > self.prrtApplicationParameters.max_residual_loss_rate\
                and n <= self.n_max - self.step_size:

            print("")

        return 0

    def residual_packet_erasure_rate(self, k, n, prrtApplicationParameters, prrtChannelParameters):
        total_packet_erasure = 0
        for i in range(1, k):
            for j in range(max(n - k + 1, i), n - k + i):
                packet_erasure_at_i = i * self.hypergeometric_distribution(n, k, i, j) * self.get_error_prob(j, n, prrtChannelParameters.loss_rate_fwd)
                total_packet_erasure += packet_erasure_at_i
        residual_packet_erasure_rate = (1 / k) * total_packet_erasure # Pr(k, n)
        return residual_packet_erasure_rate


class HECReducedSpaceSearch(AbstractSearch):
    def __init__(self, n_p_min, n_p_max, prrtApplicationParameters, prrtChannelParameters, prrtSystemParameters):
        self.n_max = 255
        self.step_size = 2 # Step size in the estimation of the optimum code word length
        self.n_p_min = n_p_min
        self.n_p_max = n_p_max
        self.prrtApplicationParameters = prrtApplicationParameters
        self.prrtChannelParameters = prrtChannelParameters
        self.prrtSystemParameters = prrtSystemParameters
        self.p_t = self.prrtApplicationParameters.max_residual_loss_rate
        self.is_order_ascending = True
        pass

    def search(self):
        ri_opt = math.inf
        k_opt = 0
        n_opt = 0
        n_p_opt = []
        ric = prrt.RestrictedIntegerComposition
        # Eq.5.9, page 125
        fec_delay_min = self.prrtSystemParameters.source_packet_interval + \
                        self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay + \
                        (self.prrtChannelParameters.rtt_prop_fwd + self.prrtSystemParameters.processing_delay) / 2 + \
                        self.prrtSystemParameters.packet_loss_detection_delay
        # Eq.5.9 page 125 assumung D_sup = 0
        req_delay = self.prrtChannelParameters.rtt_prop_fwd + \
                    self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay + \
                    self.prrtSystemParameters.processing_delay
        # Eq.5.10, page 125
        n_c_max = math.ceil((self.prrtApplicationParameters.max_latency - fec_delay_min) / req_delay)
        # self.k_lim = somewhat(prrtApplicationParameters.loss_tolerance, self.n_max)

        # n_c = 0 is the proactive packet
        for n_c in range(n_c_max):
            # Eq.5.11, k(Nc, D_T), page 125
            k_max = min(self.get_k(n_c, req_delay), self.get_k_lim(1, self.n_max))
            for k in [1, k_max]:
                n = self.estimate_n_for_k(k)
                repair_schedules = ric.gen_repair_schedule(n - k, n_c, self.n_p_min, self.n_p_max, self.is_order_ascending)
                for repair_schedule in repair_schedules:
                    coding_conf = prrt.PrrtCodingConfiguration(n, k, repair_schedule)
                    ri = coding_conf.get_redundant_information(self.prrtChannelParameters)
                    if ri < ri_opt:
                        k_opt = k
                        n_opt = n
                        n_p_opt = repair_schedule
        return prrt.PrrtCodingConfiguration(n_opt, k_opt, n_p_opt)

    def get_k(self, n_c, req_delay):
        return math.ceil((self.prrtApplicationParameters.max_latency -
                   self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay -
                   (self.prrtChannelParameters.rtt_prop_fwd + self.prrtSystemParameters.processing_delay) / 2 -
                   self.prrtSystemParameters.packet_loss_detection_delay -
                   n_c * req_delay) / self.prrtSystemParameters.source_packet_interval)

    def get_k_lim(self, start, end):
        mid_point = math.ceil((end - start) / 2)
        p_r = self.get_max_coding_block_length(mid_point)
        if p_r == self.p_t:
            return mid_point
        elif p_r  > self.p_t:
            self.get_k_lim(start, mid_point - 1)
        else:
            self.get_k_lim(mid_point + 1, end)

    # Pr(k, n_max)
    def get_max_coding_block_length(self, k):
        total_packet_erasure = 0
        for i in range(1, k):
            for j in range(max(self.n_max - k + 1, i), self.n_max - k + i):
                packet_erasure_at_i = i * self.hypergeometric_distribution(self.n_max, k, i, j) * self.get_error_prob(
                    j, self.n_max, self.prrtChannelParameters.loss_rate_fwd)
                total_packet_erasure += packet_erasure_at_i
        return (1 / k) * total_packet_erasure

    def estimate_n_for_k(self, k):
        n = k + 1
        while self.residual_packet_erasure_rate(k, n, self.prrtApplicationParameters, self.prrtChannelParameters) > self.prrtApplicationParameters.max_residual_loss_rate\
                and n <= self.n_max - self.step_size:
            n = k + self.step_size
        return n

        return 0

    def residual_packet_erasure_rate(self, k, n, prrtApplicationParameters, prrtChannelParameters):
        total_packet_erasure = 0
        for i in range(1, k):
            for j in range(max(n - k + 1, i), n - k + i):
                packet_erasure_at_i = i * self.hypergeometric_distribution(n, k, i, j) * self.get_error_prob(j, n, prrtChannelParameters.loss_rate_fwd)
                total_packet_erasure += packet_erasure_at_i
        residual_packet_erasure_rate = (1 / k) * total_packet_erasure # Pr(k, n)
        return residual_packet_erasure_rate

class HECGreadySearch(AbstractSearch):
    def __init__(self, n_p_min, n_p_max, prrtApplicationParameters, prrtChannelParameters, prrtSystemParameters):
        self.n_max = 255
        self.step_size = 2 # Step size in the estimation of the optimum code word length
        self.n_p_min = n_p_min
        self.n_p_max = n_p_max
        self.prrtApplicationParameters = prrtApplicationParameters
        self.prrtChannelParameters = prrtChannelParameters
        self.prrtSystemParameters = prrtSystemParameters
        self.p_t = self.prrtApplicationParameters.max_residual_loss_rate
        self.is_order_ascending = True
        pass

    def search(self):
        ri_opt = math.inf
        k_opt = 0
        n_opt = 0
        n_p_opt = []
        ric = prrt.RestrictedIntegerComposition
        # Eq.5.9, page 125
        fec_delay_min = self.prrtSystemParameters.source_packet_interval + \
                        self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay + \
                        (self.prrtChannelParameters.rtt_prop_fwd + self.prrtSystemParameters.processing_delay) / 2 + \
                        self.prrtSystemParameters.packet_loss_detection_delay
        # Eq.5.9 page 125 assumung D_sup = 0
        req_delay = self.prrtChannelParameters.rtt_prop_fwd + \
                    self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay + \
                    self.prrtSystemParameters.processing_delay
        # Eq.5.10, page 125
        n_c_max = math.ceil((self.prrtApplicationParameters.max_latency - fec_delay_min) / req_delay)
        # self.k_lim = somewhat(prrtApplicationParameters.loss_tolerance, self.n_max)

        # n_c = 0 is the proactive packet
        for n_c in range(n_c_max):
            # Eq.5.11, k(Nc, D_T), page 125
            k_max = min(self.get_k(n_c, req_delay), self.get_k_lim(1, self.n_max))
            for k in [1, k_max]:
                n = self.estimate_n_for_k(k)
                repair_schedule = ric.gen_repair_schedule(n - k, n_c, self.n_p_min, self.n_p_max)
                coding_conf = prrt.PrrtCodingConfiguration(n, k, repair_schedule)
                ri = coding_conf.get_redundant_information(self.prrtChannelParameters)
                if ri < ri_opt:
                    k_opt = k
                    n_opt = n
                    n_p_opt = repair_schedule
        return prrt.PrrtCodingConfiguration(n_opt, k_opt, n_p_opt)

    def get_k(self, n_c, req_delay):
        return math.ceil((self.prrtApplicationParameters.max_latency -
                   self.n_p_max * self.prrtSystemParameters.redundancy_packet_transmission_delay -
                   (self.prrtChannelParameters.rtt_prop_fwd + self.prrtSystemParameters.processing_delay) / 2 -
                   self.prrtSystemParameters.packet_loss_detection_delay -
                   n_c * req_delay) / self.prrtSystemParameters.source_packet_interval)

    def get_k_lim(self, start, end):
        mid_point = math.ceil((end - start) / 2)
        p_r = self.get_max_coding_block_length(mid_point)
        if p_r == self.p_t:
            return mid_point
        elif p_r  > self.p_t:
            self.get_k_lim(start, mid_point - 1)
        else:
            self.get_k_lim(mid_point + 1, end)

    # Pr(k, n_max)
    def get_max_coding_block_length(self, k):
        total_packet_erasure = 0
        for i in range(1, k):
            for j in range(max(self.n_max - k + 1, i), self.n_max - k + i):
                packet_erasure_at_i = i * self.hypergeometric_distribution(self.n_max, k, i, j) * self.get_error_prob(
                    j, self.n_max, self.prrtChannelParameters.loss_rate_fwd)
                total_packet_erasure += packet_erasure_at_i
        return (1 / k) * total_packet_erasure

    def estimate_n_for_k(self, k):
        n = k + 1
        while self.residual_packet_erasure_rate(k, n, self.prrtApplicationParameters, self.prrtChannelParameters) > self.prrtApplicationParameters.max_residual_loss_rate\
                and n <= self.n_max - self.step_size:

            print("")

        return 0

    def residual_packet_erasure_rate(self, k, n, prrtApplicationParameters, prrtChannelParameters):
        total_packet_erasure = 0
        for i in range(1, k):
            for j in range(max(n - k + 1, i), n - k + i):
                packet_erasure_at_i = i * self.hypergeometric_distribution(n, k, i, j) * self.get_error_prob(j, n, prrtChannelParameters.loss_rate_fwd)
                total_packet_erasure += packet_erasure_at_i
        residual_packet_erasure_rate = (1 / k) * total_packet_erasure # Pr(k, n)
        return residual_packet_erasure_rate
 No newline at end of file

prrt/SearchEvaluation.py

deleted100644 → 0
+0 −42
Original line number Diff line number Diff line
import numpy as np
import pandas as pd
import prrt
from prrt.HecSearch import HECFullSearch
from prrt.HecSearch import HECGreadySearch
import time

def evaluate(searchAlgorithm, appParams, channelParams, systemParams):
	n_p_min = 1
	n_p_max = get_n_p_max(channelParams.rtt_prop_fwd, channelParams.pkt_length, channelParams.data_rate_btl_fwd)

	if searchAlgorithm == "FullSearch":
		full_search = HECFullSearch(n_p_min, n_p_max, appParams, channelParams, systemParams)
		start = time.now()
		full_search_result = full_search.search()
		duration = time.now() - start

		return [full_search_result, duration]

	if searchAlgorithm == "GreedySearch":
		greedy_search = HECGreadySearch(n_p_min, n_p_max, appParams, channelParams, systemParams)
		start = time.now()
		greedy_search_result = greedy_search.search()
		duration = time.now() - start

		return [greedy_search_result, duration]


def test_case(csv_file_path):

	appParams = prrt.PrrtApplicationParameters(max_latency, max_residual_loss_rate, data_rate)
	chnlParams = prrt.PrrtChannelParameters(...)
	sysParams = prrt.PrrtSystemParameters(...)

	for searchAlgorithm in ["FullSearch", "GreedySearch"]:
		config, duration = evaluate(searchAlgorithm, appParams, chnlParams, sysParams)
		rows.append(..., search, config, duration)

	pd.DataFrame(rows).to_csv()

def get_n_p_max(rtt_prop_fwd, pkt_length, data_rate_btl_fwd):
	return rtt_prop_fwd * data_rate_btl_fwd / pkt_length
 No newline at end of file

prrt/ric.pyx

deleted100644 → 0
+0 −52
Original line number Diff line number Diff line
import pyximport; pyximport.install()
import itertools

def generate_restricted_integer_compositions(redundancy, positions, min, max):
    cdef c_redundancy = redundancy
    cdef c_positions = positions
    cdef c_min = min
    cdef c_max = max

    if c_positions < 1:
        raise StopIteration
    if c_positions == 1:
        if c_redundancy >= c_min and c_redundancy <= c_max:
            yield (c_redundancy,)
        raise StopIteration

    for i in range(c_min, c_redundancy + 1):
        for result in generate_restricted_integer_compositions(c_redundancy - i, c_positions - 1, i, c_max):
            if (i <= c_max):
                yield (i,) + result

# is_order_ascending = False for full search and True for greedy search
def gen_repair_schedules(redundancy, positions, min, max, is_order_ascending):
    arbitrary_schedules = []
    ordered_schedules = set()

    gen_rics = generate_restricted_integer_compositions(redundancy, positions, min, max)
    for ric in gen_rics:
        arbitrary_schedules.append(ric)

    if not is_order_ascending:
        for ric in arbitrary_schedules:
            ordered_schedules.add(itertools.permutations(ric))
        return list(ordered_schedules)
    else:
        return arbitrary_schedules


def gen_repair_schedule(redundancy, positions, min, max):
	if(redundancy < positions * min or min > max):
		raise Exception("Illegal input combinations. Make sure the min > max. And, number of total redundancy is greater that positions*min.")
	opt_schedule = [min for p in range(positions)]
	redundancy_left_over = redundancy - min * positions
	last_index = positions - 1
	while(redundancy_left_over > 0):
		if(opt_schedule[last_index] < max):
			opt_schedule[last_index] += 1
			redundancy_left_over -= 1
		else:
			last_index -= 1

	return opt_schedule
 No newline at end of file
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ import prrt
import time
import numpy as np

dataset_file_path = 'in_12_param_4_sz_mini_1000.csv'
dataset_file_path = 'documents/in_12_param_4_sz_mini_1000.csv'


def get_n_p_max(rtt_prop_fwd, pkt_length, data_rate_btl_fwd):