Kami menyandikan dan memecahkan kode pesan untuk peradaban luar angkasa

Hai Habr.



Motif artikel ini sebenarnya adalah peristiwa yang menyedihkan. Teleskop radio terkenal di dunia dari Observatorium Arecibo di Puerto Rico telah runtuh dan tidak dapat dipulihkan. Selama bertahun-tahun itu adalah teleskop radio terbesar di dunia dengan bukaan penuh (diameter 304 m, rentang frekuensi hingga 10 GHz), yang dengannya banyak penemuan dibuat. Di sini, di foto dari Wikipedia, itu masih berfungsi:





Sumber: en.wikipedia.org/wiki/Arecibo_Observatory



Tetapi teks tersebut sebenarnya tentang peristiwa lain. Pada tahun 1974, sebuah pesan untuk peradaban luar angkasa dikirim ke luar angkasa dari teleskop ini. Apa dan bagaimana dikodekan di dalamnya, detail di bawah potongan.



Pengodean



Pertama-tama, sangat menarik untuk memahami bagaimana pesan itu disampaikan. Seperti yang Anda ketahui, ukuran pesan hanya 1679 bit (sekitar 210 byte), dan ditransmisikan pada frekuensi 2,38 GHz dengan daya 450 kW. Modulasi frekuensi dengan kecepatan 10 bit / s digunakan untuk transmisi. Bilangan 1679 tidak dipilih secara kebetulan - ini adalah hasil perkalian dua bilangan prima 23 dan 73, jadi hanya ada satu cara untuk memperbesar gambar dalam bentuk persegi panjang.



Saya tidak dapat menemukan pesan radio yang sudah jadi dalam format WAV, tetapi dalam bentuk biner, dan menggunakan Python, mudah untuk menghasilkan suara sendiri. Mereka yang ingin mendengarkan apa yang akan didengar oleh alien dapat mengunduh dan menjalankan kode di bawah ini, yang akan menghasilkan file WAV. Kebisingan juga telah ditambahkan ke pesan untuk menambah kredibilitas.



generate.py
import scipy.io.wavfile as wav
import scipy.signal as signal
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
import os


message = """0000001010101000000000000101000001010000000100100010001000100
             1011001010101010101010100100100000000000000000000000000000000
             0000011000000000000000000011010000000000000000000110100000000
             0000000000101010000000000000000001111100000000000000000000000
             0000000001100001110001100001100010000000000000110010000110100
             0110001100001101011111011111011111011111000000000000000000000
             0000010000000000000000010000000000000000000000000000100000000
             0000000001111110000000000000111110000000000000000000000011000
             0110000111000110001000000010000000001000011010000110001110011
             0101111101111101111101111100000000000000000000000000100000011
             0000000001000000000001100000000000000010000011000000000011111
             1000001100000011111000000000011000000000000010000000010000000
             0100000100000011000000010000000110000110000001000000000011000
             1000011000000000000000110011000000000000011000100001100000000
             0110000110000001000000010000001000000001000001000000011000000
             0010001000000001100000000100010000000001000000010000010000000
             1000000010000000100000000000011000000000110000000011000000000
             1000111010110000000000010000000100000000000000100000111110000
             0000000010000101110100101101100000010011100100111111101110000
             1110000011011100000000010100000111011001000000101000001111110
             0100000010100000110000001000001101100000000000000000000000000
             0000000001110000010000000000000011101010001010101010100111000
             0000001010101000000000000000010100000000000000111110000000000
             0000001111111110000000000001110000000111000000000110000000000
             0110000000110100000000010110000011001100000001100110000100010
             1000001010001000010001001000100100010000000010001010001000000
             0000001000010000100000000000010000000001000000000000001001010
             00000000001111001111101001111000"""

def fftnoise(f):
    f = np.array(f, dtype='complex')
    n_p = (len(f) - 1) // 2
    phases = np.random.rand(n_p) * 2 * np.pi
    phases = np.cos(phases) + 1j * np.sin(phases)
    f[1:n_p+1] *= phases
    f[-1:-1-n_p:-1] = np.conj(f[1:n_p+1])
    return np.fft.ifft(f).real

def band_limited_noise(min_freq, max_freq, samples, samplerate=1):
    freqs = np.abs(np.fft.fftfreq(samples, 1/samplerate))
    f = np.zeros(samples)
    idx = np.where(np.logical_and(freqs>=min_freq, freqs<=max_freq))[0]
    f[idx] = 1
    return fftnoise(f)


message = ''.join(i for i in message if i.isdigit())
print("Original message:")
print(message)
print()

# Generate message
fs = 11025
f1, f2 = 3000, 4000
t_sym = 0.1
data = np.zeros(int(fs * t_sym * len(message)))
for p in range(len(message)):
    samples = np.linspace(0, t_sym, int(fs * t_sym), endpoint=False)
    freq = f2 if message[p] == '1' else f1
    data[int(fs * t_sym)*p:int(fs * t_sym)*(p + 1)] = 10000*(0.25*np.sin(2 * np.pi * freq * samples) + band_limited_noise(50, 5000, len(samples), fs))

wav.write('arecibo.wav', fs, np.int16(data))
print("WAV file saved")
      
      





Untuk kenyamanan mendengarkan, saya tingkatkan pemisahan frekuensi, di pesan asli hanya 10 Hz. Sayangnya, habr tidak mengizinkan melampirkan file suara; mereka yang ingin dapat membuat file itu sendiri atau menggunakan tautan sementara .



Ngomong-ngomong, pesan itu dikirim pada tahun 1974. Di sana:





Sumber: en.wikipedia.org/wiki/Messier_13



Gugus bintang indah M13 di konstelasi Hercules, terkenal oleh semua pecinta astronomi, dan dapat diakses untuk observasi bahkan dengan teleskop kecil. Cluster ini berjarak 22 ribu tahun cahaya, jadi pesannya akan berlanjut untuk waktu yang lama ...



Kami menemukan pengkodeannya, sekarang mari kita bayangkan bahwa kita menerima pesan seperti itu - mari kita lihat bagaimana itu dapat didekodekan.



Decoding



Prinsip modulasi frekuensi itu sendiri sederhana - frekuensi yang berbeda sesuai dengan nol dan satu. Pada spektrum, terlihat seperti ini:







Ada beberapa cara berbeda untuk memecahkan kode FSK, sebagai metode paling sederhana, cukup saring salah satu frekuensi:



fs, data = wav.read('arecibo.wav')

def butter_bandpass(lowcut, highcut, fs, order=5):
    nyq = 0.5 * fs
    low = lowcut / nyq
    high = highcut / nyq
    b, a = signal.butter(order, [low, high], btype='band')
    return b, a

def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
    b, a = butter_bandpass(lowcut, highcut, fs, order=order)
    y = signal.lfilter(b, a, data)
    return y

f1, f2 = 3000, 4000
data_f2 = butter_bandpass_filter(data, f2 - 200, f2 + 200, fs, order=3)

plt.plot(data)
plt.plot(data_f2)
plt.xlabel("Time")
plt.ylabel("Amplitude")
plt.title("Signal")
plt.show()

      
      





Hasilnya cukup cocok untuk kami:







Tentu saja, sinyal yang telah melewati 22 ribu tahun di luar angkasa kemungkinan besar akan sedikit melemah, tetapi untuk sederhananya kami akan berasumsi bahwa alien memiliki radio China yang bagus dan bukan ...



Anda dapat dengan mudah menentukan lebar satu bit dari gambar. Kita perlu mengeluarkan bit sebagai gambar. Karena pesan itu dikirim ke peradaban luar angkasa - mereka yang, menurut definisi, tidak tahu sistem pengkodean "terestrial" - mengirimkan gambar raster adalah satu-satunya keputusan logis. Di konstelasi Hercules, kemungkinan besar mereka tidak tahu apa itu ASCII atau, amit-amit, Unicode, tetapi kemungkinan besar akan menampilkan raster di layar di mana pun di Galaxy. Setidaknya sebuah peradaban yang mampu menerima sinyal digital sepertinya memiliki semacam monitor untuk menampilkannya.



Kita tidak tahu ukuran gambarnya, tapi kita tahu ukurannya satu bit dan kita tahu ukuran keseluruhan pesannya. Anda bisa memilah semua opsi yang mungkin, karena jumlahnya tidak banyak:



ss = 1102  # Width of one symbol in samples
for iw in range(12*ss, 25*ss, ss):
    w, h = iw, 80
    image = Image.new('RGB', (w, h))

    px, py = 0, 0
    for p in range(data_f2.shape[0]):
        image.putpixel((px, py), (0, int(data_f2[p]//32), 0))
        px += 1
        if px >= w:
            px = 0
            py += 1
            if py >= h:
                break

    image = image.resize((w//10, 100*h))
    image.save("1/image-%d.png" % iw)
      
      







Untuk kejelasan, gambar harus dibentangkan, karena lebar 23 piksel menurut standar sekarang, secara halus, tidak cukup. Hasil akhirnya cukup terlihat:







Final Cut:







Berbeda dengan gambar di Wikipedia , gambar aslinya tentu saja monokrom, tidak ada kode warna pada sinyalnya.



Banyak hal yang dikodekan dalam gambar (tentu saja secara kondisional), misalnya, garis vertikal selebar 2 piksel di atas kepala seseorang adalah spiral DNA (lagipula, sudah jelas, bukan?). Penguraian piktogram yang tersisa dapat dilihat di tautan di atas di Wikipedia.



Kesimpulan



Seperti yang Anda lihat, cukup banyak informasi yang dapat dikodekan menjadi 210 byte. Secara umum, tugas mengirim sinyal ke luar angkasa jauh dari sederhana, karena orang hanya bisa berharap untuk metode modulasi yang paling sederhana. Akankah pesan tersebut sampai ke penerima? Tentu saja, kemungkinan besar tidak mungkin. Saya tidak tahu apakah energi dari "jalur komunikasi" seperti itu dan perkiraan sensitivitas penerima yang diperlukan untuk menerima sinyal dievaluasi saat mengirimnya. Ya, ini sebenarnya tidak begitu penting - jika tindakan seperti itu menginspirasi seseorang untuk menjelajahi luar angkasa, maka itu tidak sia-sia. Ya, kita bisa mendapatkan jawaban pasti dalam 44 ribu tahun, dan saya akan mencoba memperbarui teks saat data baru tersedia;)



All Articles