Skip to content

jorge-martinez-gil/oruga

Repository files navigation

ORUGA: Optimizing Readability Using Genetic Algorithms

DOI Journal CI Open in Colab License Python

Try it now - no installation: open the demo notebook in Google Colab.

ORUGA (Optimizing Readability Using Genetic Algorithms) is a citable, reproducible framework for automatic, semantics-preserving readability optimization and text-simplification benchmarking. It treats simplification as a search problem: choose word replacements that make a text easier to read (lower FKGL / SMOG / Coleman-Liau / ...) while changing as little meaning as possible.

This repository is the official implementation of:

Jorge Martinez-Gil. Optimizing readability using genetic algorithms. Knowledge-Based Systems, 284:111273, 2024. https://doi.org/10.1016/j.knosys.2023.111273

ORUGA Process Example


Research at a glance

Need ORUGA provides
Citable baseline Official implementation of the Knowledge-Based Systems paper
Reproducible experiments Preserved legacy scripts plus a unified modern engine
Fair comparison Shared readability metrics for ORUGA, rules, transformers, or LLM outputs
Transparent optimization Explicit synonym substitutions and measurable objective values
Lightweight setup Core install needs only NumPy; heavier NLP tools are optional extras
Multi-objective search Pareto fronts over readability, modification rate, and semantic distance

Use ORUGA when you need a strong, inspectable baseline for readability optimization, an evaluation harness for simplification systems, or a reproducible reference implementation for evolutionary NLP research.


Table of contents


What problem does this solve?

Millions of documents - health leaflets, legal contracts, government forms, educational material, scientific abstracts - are written far above the reading level of their audience. ORUGA automatically rewrites a text to a lower reading grade by substituting hard words with simpler, meaning-preserving alternatives, and reports exactly how much readability improved and how much the text changed.

Why researchers cite ORUGA

  • It is a paper-backed reference implementation. The repository maps the published ORUGA method to a maintained Python package with CI, tests and citation metadata.
  • It makes simplification measurable. Outputs are scored with the same readability formulas and objective functions, which makes comparisons easier to reproduce.
  • It is a useful baseline for LLM papers. ORUGA gives a deterministic, no-training-data comparator for studies on controllable simplification, readability evaluation and accessibility-oriented NLP.
  • It exposes the trade-offs. Multi-objective optimizers can return Pareto fronts instead of hiding readability, modification rate and semantic distance inside one opaque score.
  • It keeps the original experiments findable. Legacy scripts are preserved under legacy/, while the modern API offers the same ideas through composable providers, metrics and optimizers.

Why optimize readability automatically?

Manual simplification is slow, inconsistent and expensive. An automatic, metric-driven optimizer gives reproducible, measurable improvements and can process large corpora in batch - useful for publishers, accessibility teams, public administrations and healthcare communicators.

Why evolutionary computation?

Choosing which words to replace, and with which synonym, is a large combinatorial search with multiple competing goals (readability vs. meaning vs. amount of change). Evolutionary and swarm algorithms:

  • need no training data or GPUs - they work directly on a single document;
  • optimize non-differentiable objectives (readability formulas) directly;
  • are naturally multi-objective, returning a Pareto front of trade-offs instead of a single answer;
  • are transparent - every change is an explicit, inspectable word choice.

How does ORUGA differ from LLM-based text simplification?

ORUGA LLM rewriting
Training data None Large corpora
Hardware CPU Usually GPU
Control of target metric Direct (optimizes FKGL/SMOG/...) Indirect (prompted)
Meaning preservation Explicit objective + measurable Implicit
Output Pareto front of trade-offs Single rewrite
Explainability Every edit is a traceable word choice Opaque
Hallucination risk None (only swaps real synonyms) Possible

ORUGA and LLMs are complementary; ORUGA is a strong, reproducible, dependency-light baseline and evaluation harness that LLM methods can be compared against.


Installation

git clone https://github.com/jorge-martinez-gil/oruga.git
cd oruga
pip install -e .                 # core engine (only needs NumPy)

Optional capabilities are installed as extras, so you only pull what you use:

pip install -e ".[wordnet]"      # WordNet synonyms (NLTK)
pip install -e ".[word2vec]"     # Word2Vec synonyms + Word Mover's Distance
pip install -e ".[web]"          # web-thesaurus synonyms
pip install -e ".[jmetal]"       # NSGA-II / GDE3 / SMPSO
pip install -e ".[pygad]"        # paper-faithful single-objective GA
pip install -e ".[grammar]"      # LanguageTool post-correction (needs Java)
pip install -e ".[dev]"          # tests + cross-validation
pip install -e ".[all]"          # everything

For WordNet, also download the corpus once: python -m nltk.downloader wordnet omw-1.4.


Quickstart

from oruga import optimize

report = optimize(
    "The committee deliberated extensively regarding the ramifications "
    "of the proposed legislation.",
    provider="wordnet",     # dictionary | wordnet | word2vec | web
    optimizer="ga",         # ga | nsga2 | gde3 | smpso | jaya | cuckoo | tlbo | pygad | random
    metric="fkgl",          # fkgl | flesch | smog | coleman_liau | ari | gunning_fog
    modification=True,      # also minimize how many words are changed
    seed=0,
)

print(report.optimized_text)
print("FKGL", report.metrics_before["fkgl"], "->", report.metrics_after["fkgl"])

No optional dependencies? Use the built-in dictionary provider and the built-in GA - it runs anywhere:

python examples/quickstart.py

Command-line interface

oruga optimize --text "The committee deliberated extensively." \
    --provider wordnet --optimizer ga --metric fkgl --modification --seed 0

oruga optimize --config examples/config.example.yaml --file mydoc.txt --json

oruga metrics  --text "Score this passage."        # all readability metrics
oruga list                                         # providers, optimizers, metrics

Architecture

ORUGA used to be ~27 near-identical scripts. It is now one composable engine:

text + SynonymProvider  ->  CandidateText        (encoding: which words, which synonyms)
                        ->  OrugaProblem          (objectives: readability + modification + semantics)
                        ->  Optimizer             (GA / NSGA-II / GDE3 / SMPSO / Jaya / Cuckoo / TLBO / ...)
                        ->  OptimizationReport    (before/after metrics + Pareto front)

Every axis is pluggable and selectable by string or config file:

Component Options
Synonym provider dictionary, wordnet, word2vec, web
Readability metric fkgl, flesch, smog, coleman_liau, ari, gunning_fog
Objectives readability; + modification rate; + semantic distance (Jaccard or WMD)
Optimizer random, ga, jaya, cuckoo, tlbo, pygad, nsga2, gde3, smpso

The readability metrics are implemented in pure Python (no readability-lxml namespace conflict) and cross-validated against an independent library (see tests/test_readability.py).


Optimize your own documents

from oruga import optimize_corpus, OrugaConfig

cfg = OrugaConfig(provider="wordnet", optimizer="nsga2",
                  modification=True, seed=0)

with open("documents.txt") as f:
    docs = [line.strip() for line in f if line.strip()]

for report in optimize_corpus(docs, config=cfg):
    print(report.improvement("fkgl"), report.optimized_text)

Benchmark a new simplification algorithm

Already have a method (rule-based, LLM, your own optimizer)? Score its output with the same metrics ORUGA uses, so results are directly comparable:

from oruga import readability as rd

original  = "The committee deliberated extensively regarding the ramifications."
yours     = my_method(original)

print("FKGL  ", rd.score(original, "fkgl"),  "->", rd.score(yours, "fkgl"))
print("SMOG  ", rd.score(original, "smog"),  "->", rd.score(yours, "smog"))
print("Flesch", rd.score(original, "flesch"),"->", rd.score(yours, "flesch"))

To plug a brand-new optimizer into the engine, subclass oruga.optimizers.base.Optimizer and register it - it then works with every provider, metric and objective.


Reproducibility checklist

For a minimal, no-network smoke test after cloning:

pip install -e ".[dev]"
pytest -q
python examples/quickstart.py
oruga list

For paper-oriented runs, install the relevant optional backends, download WordNet once, and use the reproduction entry point:

pip install -e ".[wordnet,pygad,jmetal,word2vec]"
python -m nltk.downloader wordnet omw-1.4
python examples/reproduce_paper.py

The repository keeps three reproducibility layers visible:


Reproduce the published experiments

The original paper scripts are preserved unmodified under legacy/ and remain exactly reproducible. The same experiments can also be run through the new engine:

python examples/reproduce_paper.py

Citation

If ORUGA supports your research, please cite the paper. GitHub's "Cite this repository" button generates the reference automatically from CITATION.cff, or copy the BibTeX below:

@article{martinez2024oruga,
    author  = {Jorge Martinez-Gil},
    title   = {Optimizing readability using genetic algorithms},
    journal = {Knowledge-Based Systems},
    volume  = {284},
    pages   = {111273},
    year    = {2024},
    issn    = {0950-7051},
    doi     = {10.1016/j.knosys.2023.111273}
}

Background reading (Medium series): Part 1 | Part 2 | Part 3


Contributing

Contributions are welcome - new synonym providers, optimizers, metrics, datasets and benchmarks especially. See CONTRIBUTING.md.

License

MIT - see LICENSE.


Keywords: automatic readability optimization, text readability optimization, genetic algorithm readability, readability benchmark, text simplification benchmark, readability evaluation, semantic-preserving simplification, evolutionary text simplification, FKGL optimization, accessibility NLP.