Commit b3ad742a authored by Ashkan's avatar Ashkan
Browse files

Add GreedySearch with only one repair schedule.

parent 9cd3bba5
Loading
Loading
Loading
Loading
Loading
+95 −3
Original line number Diff line number Diff line
@@ -102,10 +102,11 @@ class HECFullSearch(AbstractSearch):
        return residual_packet_erasure_rate


class HECGreedySearch(AbstractSearch):
    def __init__(self, n_p_max, prrtApplicationParameters, prrtChannelParameters, prrtSystemParameters):
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
@@ -138,7 +139,7 @@ class HECGreedySearch(AbstractSearch):
            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, 1, self.n_p_max, self.is_order_ascending)
                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)
@@ -192,3 +193,94 @@ class HECGreedySearch(AbstractSearch):
                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 = []
        # 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
+18 −2
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ def generate_restricted_integer_compositions(redundancy, positions, min, max):
                yield (i,) + result

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

@@ -34,3 +34,19 @@ def gen_repair_schedule(redundancy, positions, min, max, is_order_ascending):
        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