Please note, this is an experimental algorithm
AI Iterative Testing Repository Based on MorseFold
A reversible lightweight compression experiment for Morse code sequences: text is first converted into standard Morse code, then transformed into a shorter simplified representation using consecutive equal-length grouping, alternating-pattern detection, compact meta tokens, and message-local repeated-word references, while still supporting full decoding back to the original text.
This project studies a narrow but practical question: although standard Morse code is already a discrete symbol sequence, it still contains visible structural redundancy at the character level, including repeated length patterns, dot-dash bias, fully alternating structures, and repeated words inside the same message. Based on these properties, the project implements a reversible simplification method. Rather than pursuing globally optimal compression, it applies local structural rules, compact tokenization, and a message-local back-reference layer, with a fallback policy that keeps the raw Morse group whenever simplification is not shorter.
From the current implementation and benchmark outputs in this repository, the method produces consistent character-level savings across single words, phrases, long sentences, paragraphs, and long texts. The implementation uses only the Python standard library, which makes it suitable for teaching demos, small research prototypes, and further algorithm iteration.
Standard Morse code has two direct limitations in this context:
- It was designed for transmission robustness, not text compression.
- Even though each symbol is small, total encoded length still grows quickly for long texts.
This project tries to answer two questions:
- Can standard Morse code be structurally simplified without losing reversibility?
- Can that simplification produce stable character-level gains across different text scales?
The core implementation is encoder.py, specifically text_to_morseSimplify(). The current pipeline is:
- Convert plain text to standard Morse code with
main.pyandtext_to_morse(). - Inside each word, split the Morse stream into groups of consecutive codes with the same length.
- For each same-length run, search for the shortest mix of raw output and compressed subsegments.
- Convert Morse codes in compressed segments into compact identifiers
ID. - Encode the group rule symbol
RSwith a single-character token. - If the compressed group is not shorter than the raw group, keep the raw Morse group.
- After each word is simplified, optionally replace repeated words within the same message by a short
~<index>reference when that is shorter. - Emit a reversible simplified string.
Inside each word, grouping is based on consecutive Morse codes with identical length. For example:
.... . .-.. .-.. ---
is split into:
.... | . | .-.. .-.. | ---
Only consecutive codes with the same length can belong to the same group.
Each candidate compressed segment has a logical RS value with the form <length><tail>, for example 4- or 3..
Where:
lengthis the Morse length shared by all codes in the group.tailis the group bias symbol.
The bias is computed as follows:
- If a Morse code has at least as many
-as., it is marked as1. - If it has more
.than-, it is marked as0. - If the code is strictly alternating, it is handled as a special regular case.
- The encoder compares both
tail = -andtail = .directly and keeps the shorter result.
In the current format, this logical RS value is stored as a single token:
G -> 4-H -> 4.J -> 5.
decoder.py still supports the earlier %RS form for backward compatibility.
After RS is determined, each Morse code in the group is converted into an ID:
- If
RSends with-, record the positions of.. - If
RSends with., record the positions of-. - Positions are 1-based.
- Multiple positions are concatenated directly as a string.
- In the current format, common
IDstrings are further mapped to single-character tokens.
For example, in a 4- group:
--.- -> 3---- -> ""
And in the compact token layer:
3 -> d+ -> b"" -> a
If a Morse code contains no adjacent repeated symbol from start to end, it is treated as a regular alternating code:
- Codes starting with
-are encoded as+ - Codes starting with
.are encoded as-
For example:
-.-. -> +.-.- -> -
The simplified output has the logical form:
ID\ID\...%RS|raw_group|ID\ID\...%RS/...
Separators:
\: separates multipleIDvalues inside one compressed group%: separatesIDdata fromRS|: separates groups inside one word/: separates words
The current encoder may emit more compact forms:
- compact group form:
fbG - mixed raw/compressed word form:
....|.|eeH|--- - repeated-word reference form:
~0
So the practical current output is better described as:
compact_group|raw_group|compact_group/.../~index
This format is fully decoded by decoder.py back into standard Morse code and then plain text. The decoder is backward-compatible with the earlier %RS and backslash-separated forms.
After a word has been simplified, the encoder may reuse it later in the same message.
- The first occurrence is emitted normally.
- Later identical simplified words can be replaced by
~<index>. - The index uses
0-9a-zA-Z. - A reference is only used if it is shorter than the original simplified word.
This is a message-local reversible back-reference, not a static dataset-tuned dictionary.
This is one of the main engineering constraints in the current implementation:
if len(encoded_group) >= len(raw_group):
keep raw_group
So the algorithm is not a forced compression scheme. It only compresses when the result is actually shorter.
Input text:
QC
Standard Morse code:
--.- -.-.
Simplified encoding:
fbG
Explanation:
- Both characters have length
4, so they form one group. - The logical group bias becomes
4-, whose current token isG. - In
--.-, the dot is at position3, which maps to tokenf. -.-.is a regular alternating code, so its identifier is+, which maps to tokenb.
Input text:
HELLO WORLD
Standard Morse code:
.... . .-.. .-.. --- / .-- --- .-. .-.. -..
Simplified encoding:
....|.|eeH|---/dacE|.-..|-..
This shows that simplification is not applied uniformly character by character. Each candidate group inside a word is evaluated independently, so some groups are compressed and others remain raw.
Input text:
HELLO HELLO
Standard Morse code:
.... . .-.. .-.. --- / .... . .-.. .-.. ---
Simplified encoding:
....|.|eeH|---/~0
This demonstrates the current repeated-word reference rule: the second HELLO is replaced by ~0, which points to the first simplified word in the same message.
python main.pyThe program prints:
- Standard Morse code
- Simplified encoding
- Both lengths
- Character reduction
- Compression ratio
python decoder.pyThe program prints:
- Decoded standard Morse code
- Decoded plain text
from main import text_to_morse
from encoder import text_to_morseSimplify
from decoder import simplified_to_morse, simplified_to_text
text = "HELLO WORLD"
morse = text_to_morse(text)
simplified = text_to_morseSimplify(morse)
print(morse)
print(simplified)
print(simplified_to_morse(simplified))
print(simplified_to_text(simplified))Benchmark scripts are under benchmarks/:
benchmarks/benchmark_experiments.py: unified experiment entry point, generates summary CSV filesbenchmarks/visualize_results.py: converts CSV outputs into SVG chartsbenchmarks/benchmark_dataset.py: base-sample statisticsbenchmarks/benchmark_long_sentences.py: long-sentence statisticsbenchmarks/benchmark_paragraphs.py: paragraph statisticsbenchmarks/benchmark_long_texts.py: long-text statistics
Datasets are stored under datasets/:
base: short baseline sampleslong: long-sentence samplesparagraph: paragraph sampleslong_text: extra-long text samples
Run:
python benchmarks/benchmark_experiments.py
python benchmarks/visualize_results.pyOutputs are written to output/.
The following numbers come from the current repository output file output/experiment_group_summary.csv, regenerated with the current implementation.
| Group | Samples | Compression Ratio | Normalized Compression Ratio | Total Reduction |
|---|---|---|---|---|
| single_word | 10000 | 65.62% | 65.62% | 104753 |
| multi_word_phrase | 10000 | 59.77% | 63.64% | 332554 |
| number_heavy | 10000 | 59.57% | 63.43% | 336266 |
| punctuation_heavy | 10000 | 59.57% | 63.43% | 336408 |
| mixed_digits_punctuation | 10000 | 59.57% | 63.43% | 336410 |
| long_sentence_gt20_words | 1000 | 72.44% | 78.86% | 170942 |
| paragraph_samples | 200 | 69.96% | 77.07% | 84327 |
| long_text_gt200_words | 10 | 65.34% | 71.99% | 12135 |
Notes:
- Lower
Compression Ratiois better; it means the simplified representation occupies a smaller fraction of the original Morse string. Normalized Compression Ratioremoves the formatting advantage of replacing" / "with"/", so it better isolates the algorithmic gain.
From the current results:
- Single words and structured short samples show the strongest normalized gains because compact
IDandRStokens amortize well. - Multi-word and long-text groups still keep clear positive savings, which indicates that the current format scales beyond toy examples.
- Repeated words inside the same message can now be folded by
~<index>references, which the current encoder and decoder both support.
These charts are suitable for reports, demos, presentations, or a repository landing page.
morsecode_simplify/
├─ main.py
├─ encoder.py
├─ decoder.py
├─ benchmarks/
├─ datasets/
└─ output/
Module roles:
main.py: plain text to standard Morse code; CLI encoding entry pointencoder.py: standard Morse code to simplified encodingdecoder.py: simplified encoding back to Morse code and plain textbenchmarks/: experiment statistics and chart generation
The current codebase follows these visible implementation conventions:
- Python standard library only, with no third-party dependencies
- Public functions validate
strinputs - Invalid inputs raise
TypeErrororValueError - Type annotations are used throughout
- Files are read with
utf-8 - Benchmark scripts use
pathlib.Path - Both CLI usage and module import usage are supported
The current method still has clear boundaries:
- Compression is still mainly driven by local groups plus message-local repeated-word reuse, not globally optimal parsing
- The supported character set is mainly English letters, digits, and common English punctuation
- Gains can be limited for irregular Morse sequences with little repeated local structure
IDvalues are compacted, but longer Morse lengths can still leave residual metadata overhead- Evaluation currently focuses on character length, not stricter information-theoretic metrics
Possible next steps include:
- stronger reuse across segments instead of only same-word groups and repeated-word references
- more general message-level template reuse without dataset-specific tuning
- a more compact scheme for low-frequency
IDpatterns that still fall back to multi-character forms - systematic comparisons against alternatives such as RLE-style or Huffman-style approaches
- more formal metrics such as entropy estimates, decoding complexity, and throughput
The current repository state includes six documented optimization rounds in LOG.md:
- Optimization #1: shortest segmentation search inside same-length runs
- Optimization #2: caching and incremental DP construction
- Optimization #3: enable length-1 and length-2 runs to participate in shortest-form search
- Optimization #4: single-character
RStokens - Optimization #5: compact single-character
IDtokens - Optimization #6: message-local repeated-word references with
~<index>
- Python 3.10+
The current repository supports the full round trip:
text -> morse -> simplified -> morse -> text
Using the included datasets and scripts, the project can reproduce benchmark CSV files and SVG charts directly. That makes it suitable for:
- algorithm coursework
- small paper prototypes
- encoding-rule demos
- GitHub project showcases