Warning: This is an old version. The latest stable version is Version 1.3.0.
In this example shows how to use the API of pyerasure
to encode, recode and
decode with using the RLNC coefficient generator.
1#!/usr/bin/env python
2# encoding: utf-8
3
4# License for Commercial Usage
5# Distributed under the "PYERASURE EVALUATION LICENSE 1.3"
6# Licensees holding a valid commercial license may use this project in
7# accordance with the standard license agreement terms provided with the
8# Software (see accompanying file LICENSE.rst or
9# https://www.steinwurf.com/license), unless otherwise different terms and
10# conditions are agreed in writing between Licensee and Steinwurf ApS in which
11# case the license will be regulated by that separate written agreement.
12#
13# License for Non-Commercial Usage
14# Distributed under the "PYERASURE RESEARCH LICENSE 1.2"
15# Licensees holding a valid research license may use this project in accordance
16# with the license agreement terms provided with the Software
17# See accompanying file LICENSE.rst or https://www.steinwurf.com/license
18
19import os
20import sys
21import random
22
23import pyerasure
24import pyerasure.finite_field
25import pyerasure.generator
26
27
28def main():
29 """
30 Encode recode decode example.
31
32 In Network Coding applications, one of the key features is the
33 ability of intermediate nodes in the network to recode packets
34 as they traverse them. Using pyerasure, it is possible to recode
35 packets in decoders with the recode_symbol function.
36
37 This example shows how to use one encoder and two decoders to
38 simulate a simple relay network as shown below:
39
40 +-----------+ +-----------+ +-----------+
41 | encoder |+--->| recoder |+--->| decoder |
42 +-----------+ +-----------+ +-----------+
43
44 In a practical application recoding can be used in several different
45 ways and one must consider several different factors, such as
46 reducing linear dependency by coordinating several recoding nodes
47 in the network.
48 Suggestions for dealing with such issues can be found in current
49 research literature (e.g. MORE: A Network Coding Approach to
50 Opportunistic Routing).
51 """
52 # Choose the finite field, the number of symbols (i.e. generation size)
53 # and the symbol size in bytes
54 field = pyerasure.finite_field.Binary8()
55 symbols = 42
56 symbol_bytes = 160
57
58 # Create an encoder and two decoders
59 encoder = pyerasure.Encoder(field, symbols, symbol_bytes)
60 recoder = pyerasure.Decoder(field, symbols, symbol_bytes)
61 decoder = pyerasure.Decoder(field, symbols, symbol_bytes)
62
63 # Create generator
64 generator = pyerasure.generator.RandomUniform(field, symbols)
65
66 # Generate some random data to encode. We create a bytearray of the same
67 # size as the encoder's block size and assign it to the encoder.
68 # This bytearray must not go out of scope while the encoder exists!
69 data_in = bytearray(os.urandom(encoder.block_bytes))
70 encoder.set_symbols(data_in)
71
72 coefficients = None
73
74 loss_probability = 25
75 systematic_index = 0
76
77 while not decoder.is_complete():
78
79 if encoder.rank > systematic_index:
80 print("systematic symbol", end="")
81
82 index = systematic_index
83 systematic_index += 1
84 symbol = encoder.symbol_data(index)
85
86 # Drop packet based on loss probability
87 if random.randint(0, 100) < loss_probability:
88 print(" - lost")
89 else:
90 recoder.decode_systematic_symbol(symbol, index)
91 print(f" - decoded, rank now {recoder.rank}")
92 elif not recoder.is_complete():
93
94 # The RLNC code is rateless, which means, in theory, that it can
95 # generate an infinite number of coded packets.
96 print("coded symbol", end="")
97
98 # Generate the coefficients into the symbol buffer
99 coefficients = generator.generate()
100
101 # Encode a symbol into the symbol buffer
102 symbol = encoder.encode_symbol(coefficients)
103
104 # Drop packet based on loss probability
105 if random.randint(0, 100) < loss_probability:
106 print(" - lost")
107 else:
108 # Note, in this example the coefficients are available, but in
109 # certain use cases - especially network based it might not be
110 # feasible to transmit the coefficients. In this case the seed
111 # can be used for generating the coefficients again.
112 recoder.decode_symbol(symbol, bytearray(coefficients))
113 print(f" - decoded, rank now {recoder.rank}")
114
115 if recoder.rank != 0:
116 print("recoded symbol", end="")
117 recoding_coefficients = generator.generate_recode(recoder)
118 symbol, coefficients = recoder.recode_symbol(
119 bytearray(recoding_coefficients)
120 )
121
122 if random.randint(0, 100) < loss_probability:
123 print(" - lost")
124 else:
125 # When recoding sending the whole coefficient vector is often
126 # needed as the state of the recorder determines the
127 # coefficients.
128 decoder.decode_symbol(symbol, coefficients)
129 print(f" - decoded, rank now {decoder.rank}")
130
131 # Both recoder and decoder should now be complete,
132 # check if the output buffers match the data_in buffer
133 if recoder.block_data() == data_in and decoder.block_data() == data_in:
134 print("Data decoded correctly")
135 else:
136 print("Unexpected failure to decode please file a bug report :)")
137 sys.exit(1)
138
139
140if __name__ == "__main__":
141 main()