chore
This commit is contained in:
parent
80da1ea764
commit
18aca25240
2 changed files with 176 additions and 0 deletions
57
encoder_backup.py
Normal file
57
encoder_backup.py
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
# encoder_backup.py
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# System parameters
|
||||||
|
G = 10.0 # power gain for even samples
|
||||||
|
ENERGY_LIMIT = 2000.0 # total energy per block
|
||||||
|
ALPHABET = (
|
||||||
|
[chr(i) for i in range(ord('a'), ord('z')+1)] +
|
||||||
|
[chr(i) for i in range(ord('A'), ord('Z')+1)] +
|
||||||
|
[str(i) for i in range(10)] +
|
||||||
|
[' ', '.']
|
||||||
|
)
|
||||||
|
assert len(ALPHABET) == 64, "Alphabet must be size 64"
|
||||||
|
|
||||||
|
|
||||||
|
def hadamard(r: int) -> np.ndarray:
|
||||||
|
if r == 0:
|
||||||
|
return np.array([[1]], dtype=float)
|
||||||
|
M = hadamard(r-1)
|
||||||
|
return np.block([[M, M], [M, -M]])
|
||||||
|
|
||||||
|
|
||||||
|
def Br(r: int) -> np.ndarray:
|
||||||
|
M = hadamard(r)
|
||||||
|
return np.vstack([M, -M])
|
||||||
|
|
||||||
|
|
||||||
|
def make_codebook(r: int, num_blocks: int) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Build 64x64 codebook and scale blocks so energy per block ≤ ENERGY_LIMIT/num_blocks
|
||||||
|
"""
|
||||||
|
B_full = Br(r) #
|
||||||
|
B = B_full[: len(ALPHABET), :] # now shape (64, 2^r)
|
||||||
|
C = np.hstack([B, B]).astype(float) # shape (64, 2^{r+1})
|
||||||
|
raw_norm = np.sum(C[0]**2)
|
||||||
|
margin = 0.99
|
||||||
|
alpha = margin * (ENERGY_LIMIT / num_blocks) / raw_norm
|
||||||
|
return np.sqrt(alpha) * C
|
||||||
|
|
||||||
|
|
||||||
|
def interleave(c: np.ndarray) -> np.ndarray:
|
||||||
|
half = c.size // 2
|
||||||
|
x = np.empty(c.size)
|
||||||
|
x[0::2] = c[:half]
|
||||||
|
x[1::2] = c[half:]
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
def encode_message(msg: str, C: np.ndarray) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Encode 40-character message into interleaved code symbols
|
||||||
|
"""
|
||||||
|
if len(msg) != 40:
|
||||||
|
raise ValueError("Message must be exactly 40 characters.")
|
||||||
|
idx = [ALPHABET.index(ch) for ch in msg]
|
||||||
|
blocks = [interleave(C[i]) for i in idx]
|
||||||
|
return np.concatenate(blocks)
|
119
main_backup.py
Normal file
119
main_backup.py
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import numpy as np
|
||||||
|
import encoder
|
||||||
|
import decoder
|
||||||
|
import channel
|
||||||
|
import subprocess
|
||||||
|
import pathlib
|
||||||
|
import os
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
# Global paths for debugging
|
||||||
|
INPUT_FILE = None
|
||||||
|
OUTPUT_FILE = None
|
||||||
|
|
||||||
|
def transmit(msg, C):
|
||||||
|
return encoder.encode_message(msg, C)
|
||||||
|
|
||||||
|
def receive_local(c):
|
||||||
|
return channel.channel(c)
|
||||||
|
|
||||||
|
def receive_server(c, hostname, port):
|
||||||
|
global INPUT_FILE, OUTPUT_FILE
|
||||||
|
# write or temp-file for input
|
||||||
|
if INPUT_FILE:
|
||||||
|
in_name, delete_in = INPUT_FILE, False
|
||||||
|
np.savetxt(in_name, c)
|
||||||
|
else:
|
||||||
|
tf = tempfile.NamedTemporaryFile(suffix='.txt', delete=False)
|
||||||
|
np.savetxt(tf.name, c)
|
||||||
|
in_name, delete_in = tf.name, True
|
||||||
|
tf.close()
|
||||||
|
# write or temp-file for output
|
||||||
|
if OUTPUT_FILE:
|
||||||
|
out_name, delete_out = OUTPUT_FILE, False
|
||||||
|
else:
|
||||||
|
fd, out_name = tempfile.mkstemp(suffix='.txt')
|
||||||
|
os.close(fd)
|
||||||
|
delete_out = True
|
||||||
|
|
||||||
|
# call client.py
|
||||||
|
cmd = [
|
||||||
|
sys.executable,
|
||||||
|
str(pathlib.Path(__file__).parent / 'client.py'),
|
||||||
|
'--input_file', in_name,
|
||||||
|
'--output_file', out_name,
|
||||||
|
'--srv_hostname', hostname,
|
||||||
|
'--srv_port', str(port)
|
||||||
|
]
|
||||||
|
try:
|
||||||
|
subprocess.run(cmd, check=True)
|
||||||
|
Y = np.loadtxt(out_name)
|
||||||
|
finally:
|
||||||
|
if delete_in and os.path.exists(in_name): os.remove(in_name)
|
||||||
|
if delete_out and os.path.exists(out_name): os.remove(out_name)
|
||||||
|
|
||||||
|
return Y
|
||||||
|
|
||||||
|
def receive(c, mode, hostname, port):
|
||||||
|
if mode == 'local':
|
||||||
|
return receive_local(c)
|
||||||
|
elif mode == 'server':
|
||||||
|
return receive_server(c, hostname, port)
|
||||||
|
else:
|
||||||
|
raise ValueError("mode must be 'local' or 'server'")
|
||||||
|
|
||||||
|
def test_performance(msg, num_trials, mode, hostname, port):
|
||||||
|
if len(msg) != 40:
|
||||||
|
raise ValueError('Message must be exactly 40 characters.')
|
||||||
|
|
||||||
|
# build the same codebook
|
||||||
|
C = encoder.make_codebook(r=11, num_blocks=40)
|
||||||
|
|
||||||
|
successes = 0
|
||||||
|
print(f"Original message: {msg!r}")
|
||||||
|
print(f"Running {num_trials} trials over '{mode}' channel...\n")
|
||||||
|
|
||||||
|
for i in range(num_trials):
|
||||||
|
# TX → channel → RX
|
||||||
|
c = transmit(msg, C)
|
||||||
|
Y = receive(c, mode, hostname, port)
|
||||||
|
|
||||||
|
# decode with state‐estimation
|
||||||
|
est, s_est = decoder.decode_blocks_with_state(Y, C)
|
||||||
|
|
||||||
|
# count char errors
|
||||||
|
errors = sum(1 for a,b in zip(est, msg) if a!=b)
|
||||||
|
if errors == 0:
|
||||||
|
successes += 1
|
||||||
|
|
||||||
|
print(f"Trial {i+1:3d}: state={s_est} decoded={est!r} errors={errors}")
|
||||||
|
|
||||||
|
pct = 100 * successes / num_trials
|
||||||
|
print("\n=== Summary ===")
|
||||||
|
print(f" Total trials: {num_trials}")
|
||||||
|
print(f" Perfect decodings: {successes}")
|
||||||
|
print(f" Overall accuracy: {pct:.2f}%")
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
p = argparse.ArgumentParser(description='Test comms system')
|
||||||
|
p.add_argument('--message','-m', required=True, help='40-char message')
|
||||||
|
p.add_argument('--trials','-n', type=int, default=200, help='Number of trials')
|
||||||
|
p.add_argument('--mode', choices=['local','server'], default='local')
|
||||||
|
p.add_argument('--hostname', default='iscsrv72.epfl.ch')
|
||||||
|
p.add_argument('--port', type=int, default=80)
|
||||||
|
p.add_argument('--input_file','-i', default=None,
|
||||||
|
help='(server mode) where to write input.txt')
|
||||||
|
p.add_argument('--output_file','-o',default=None,
|
||||||
|
help='(server mode) where to write output.txt')
|
||||||
|
return p.parse_args()
|
||||||
|
|
||||||
|
if __name__=='__main__':
|
||||||
|
args = parse_args()
|
||||||
|
INPUT_FILE = args.input_file
|
||||||
|
OUTPUT_FILE = args.output_file
|
||||||
|
test_performance(args.message, args.trials,
|
||||||
|
args.mode, args.hostname, args.port)
|
Loading…
Add table
Reference in a new issue