diff --git a/acres/evaluation/evaluation.py b/acres/evaluation/evaluation.py
index d6a596f..09c345a 100644
--- a/acres/evaluation/evaluation.py
+++ b/acres/evaluation/evaluation.py
@@ -71,8 +71,8 @@ def analyze(contextualized_acronym: topic_list.Acronym, true_expansions: Set[str
     # Normalize true expansions so that we can match them to the training data
     true_expansions = set(map(text.clean, true_expansions))
 
-    # XXX We currently do not support contextualized word2vec
-    if strategy == resolver.Strategy.WORD2VEC:
+    # XXX We currently support context only for n-grams
+    if strategy != resolver.Strategy.NGRAM:
         left_context = ""
         right_context = ""
 
diff --git a/acres/model/expansion_standard.py b/acres/model/expansion_standard.py
index 433e90c..84f74e9 100644
--- a/acres/model/expansion_standard.py
+++ b/acres/model/expansion_standard.py
@@ -56,18 +56,25 @@ def write_results(filename: str, acronyms: Dict[str, Dict[str, int]]) -> None:
 
         # Write all old expansions
         _write_expansions(acronym, old_expansions, file)
+        previous_expansions = old_expansions.keys()
+
+        # Write all expansions in the dictionary
+        dictionary = resolver.resolve(acronym, "", "", resolver.Strategy.DICTIONARY)
+        dictionary = [exp for exp in dictionary if exp not in previous_expansions]
+        _write_expansions(acronym, dict.fromkeys(dictionary, -1), file)
+        previous_expansions |= set(dictionary)
 
         k = 5
 
         # Write up to k filtered expansions not in old
-        filtered_expansions = [exp for exp in filtered_expansions[:k] if
-                               exp not in old_expansions.keys()]
-        _write_expansions(acronym, dict.fromkeys(filtered_expansions, -1), file)
+        filtered_expansions = [exp for exp in filtered_expansions[:k]
+                               if exp not in previous_expansions]
+        _write_expansions(acronym, dict.fromkeys(filtered_expansions, -2), file)
+        previous_expansions |= set(filtered_expansions)
 
         # Write up to k remaining expansions
-        expansions = [exp for exp in expansions[:k] if
-                      exp not in old_expansions.keys() and exp not in set(filtered_expansions)]
-        _write_expansions(acronym, dict.fromkeys(expansions, -2), file)
+        expansions = [exp for exp in expansions[:k] if exp not in previous_expansions]
+        _write_expansions(acronym, dict.fromkeys(expansions, -3), file)
 
     file.close()
 
diff --git a/acres/preprocess/resource_factory.py b/acres/preprocess/resource_factory.py
index 1f7e319..9ca2824 100644
--- a/acres/preprocess/resource_factory.py
+++ b/acres/preprocess/resource_factory.py
@@ -9,12 +9,14 @@ import pickle
 from typing import Dict, Set, List, Tuple, Any
 
 from gensim.models import Word2Vec
-# from gensim.models import FastText
 
 from acres.nn import train
 from acres.preprocess import dumps
+from acres.stats import dictionary
 from acres.util import functions
 
+# from gensim.models import FastText
+
 logger = logging.getLogger(__name__)
 
 PICKLE_FOLDER = "models/pickle/"
@@ -34,6 +36,7 @@ NN_MODEL = None  # type: Word2Vec
 NGRAMSTAT = {}  # type: Dict[int, Tuple[int,str]]
 CHARACTER_NGRAMS = {}  # type: Dict[str, int]
 WORD_NGRAMS = {}  # type: Dict[str, int]
+DICTIONARY = {}  # type: Dict[str, List[str]]
 
 
 def get_log_corpus_filename() -> str:
@@ -286,6 +289,20 @@ def get_nn_model(ngram_size: int = 3, min_count: int = 1, net_size: int = 100, a
     return NN_MODEL
 
 
+def get_dictionary() -> Dict[str, List[str]]:
+    """
+    Lazy load the sense inventory.
+
+    :return:
+    """
+    global DICTIONARY
+
+    if not DICTIONARY:
+        DICTIONARY = dictionary.parse("resources/acro_full_reference.txt")
+
+    return DICTIONARY
+
+
 def reset() -> None:
     """
     Resets global variables to force model recreation.
diff --git a/acres/resolution/resolver.py b/acres/resolution/resolver.py
index b785cc2..e9c7470 100644
--- a/acres/resolution/resolver.py
+++ b/acres/resolution/resolver.py
@@ -4,6 +4,7 @@ from typing import List, Dict, Tuple
 from acres.ngram import finder
 from acres.nn import test
 from acres.rater import rater
+from acres.stats import dictionary
 from acres.util import text
 
 
@@ -13,10 +14,12 @@ class Strategy(Enum):
     """
     NGRAM = 1
     WORD2VEC = 2
+    DICTIONARY = 3
 
 
 NGRAM_CACHE = {}  # type: Dict[Tuple, List[str]]
 WORD2VEC_CACHE = {}  # type: Dict[Tuple, List[str]]
+DICTIONARY_CACHE = {}  # type: Dict[Tuple, List[str]]
 
 
 def cached_resolve(acronym: str, left_context: str, right_context: str,
@@ -35,7 +38,8 @@ def cached_resolve(acronym: str, left_context: str, right_context: str,
     """
     switcher = {
         Strategy.NGRAM: NGRAM_CACHE,
-        Strategy.WORD2VEC: WORD2VEC_CACHE
+        Strategy.WORD2VEC: WORD2VEC_CACHE,
+        Strategy.DICTIONARY: DICTIONARY_CACHE
     }
 
     cache = switcher.get(strategy)
@@ -85,7 +89,8 @@ def resolve(acronym: str, left_context: str, right_context: str, strategy: Strat
     """
     switcher = {
         Strategy.NGRAM: finder.robust_find_embeddings,
-        Strategy.WORD2VEC: test.find_candidates
+        Strategy.WORD2VEC: test.find_candidates,
+        Strategy.DICTIONARY: dictionary.expand
     }
 
     func = switcher.get(strategy)
diff --git a/acres/stats/dictionary.py b/acres/stats/dictionary.py
index 05a675f..8d13a9a 100644
--- a/acres/stats/dictionary.py
+++ b/acres/stats/dictionary.py
@@ -1,15 +1,57 @@
 """
 Metrics from large German acronym / definition list
 """
-from typing import List, Tuple, Optional
+from typing import List, Tuple, Optional, Dict
 
-from acres.rater import rater
+from acres.preprocess import resource_factory
 from acres.rater import expansion
+from acres.rater import rater
 from acres.util import acronym as acro_util
 from acres.util import functions
 
 
-def dump_sample(filename: str, max_len: int = 15, min_len: int = 1) -> List[Tuple[str, str]]:
+def expand(acronym: str, left_context: str = "", right_context: str = "") -> List[str]:
+    """
+
+    :param acronym:
+    :param left_context:
+    :param right_context:
+    :return:
+    """
+    dictionary = resource_factory.get_dictionary()
+    if acronym not in dictionary:
+        return []
+    return dictionary[acronym]
+
+
+def _tuple2dictionary(senses: List[Tuple[str, str]]) -> Dict[str, List[str]]:
+    """
+    Convert the sense inventory as a list of tuples to a Python dictionary for better search \
+    performance.
+
+    :param senses:
+    :return:
+    """
+    dictionary = {}  # type: Dict[str, List[str]]
+    for acro, full in senses:
+        # Initialize sub-list
+        if acro not in dictionary:
+            dictionary[acro] = []
+        dictionary[acro].append(full)
+    return dictionary
+
+
+def parse(filename: str) -> Dict[str, List[str]]:
+    """
+    Parse a tab-separated sense inventory as a Python dictionary.
+
+    :param filename:
+    :return:
+    """
+    return _tuple2dictionary(_dump_sample(filename))
+
+
+def _dump_sample(filename: str, max_len: int = 15, min_len: int = 1) -> List[Tuple[str, str]]:
     """
 
     :param filename:
@@ -97,7 +139,7 @@ def analyze_file(filename: str) -> None:
     :param filename:
     :return:
     """
-    senses = dump_sample(filename, 3, 3)
+    senses = _dump_sample(filename, 3, 3)
     for (acro, full) in senses:
         if not acro_util.is_acronym(acro):
             print(acro + " is not an acronym according to our definition")

Calculate out-of-dictionary acronyms
If we're not dealing with disambiguation (#10), then, if existent, a domain-dictionary would suffice.

Check if any exists for clinical german and, if yes, estimate the amount of out-of-dictionary acronyms. If the amount is large (or if the dictionary introduces extra ambiguity), an unsupervised approach like ours is reasonable.
diff --git a/tests/benchmark/test_benchmark.py b/tests/benchmark/test_benchmark.py
index 1a0f71a..c922348 100644
--- a/tests/benchmark/test_benchmark.py
+++ b/tests/benchmark/test_benchmark.py
@@ -168,3 +168,13 @@ def test_evaluation():
     absolute_tolerance = 0.02
     assert precision == pytest.approx(0.81, abs=absolute_tolerance)
     assert recall == pytest.approx(0.73, abs=absolute_tolerance)
+
+    (precision, recall) = evaluation.do_analysis("resources/topic_list.tsv",
+                                                 "resources/detection_standard.tsv",
+                                                 "resources/expansion_standard.tsv",
+                                                 resolver.Strategy.DICTIONARY,
+                                                 evaluation.Level.TYPE,
+                                                 10, True)
+    absolute_tolerance = 0.02
+    assert precision == pytest.approx(0.68, abs=absolute_tolerance)
+    assert recall == pytest.approx(0.42, abs=absolute_tolerance)
diff --git a/tests/stats/test_dictionary.py b/tests/stats/test_dictionary.py
index 0b4ea78..35892af 100644
--- a/tests/stats/test_dictionary.py
+++ b/tests/stats/test_dictionary.py
@@ -3,7 +3,7 @@ from acres.stats import dictionary
 
 def test_dump_sample():
     expected = [('AA', 'Alopecia areata'), ('γ-GT', 'γ-Glutamyltransferase')]
-    actual = dictionary.dump_sample("resources/acro_full_reference.txt")
+    actual = dictionary._dump_sample("resources/acro_full_reference.txt")
     assert set(expected).issubset(actual)
 
 

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.7
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/bst-mug/acres.git@868bb4a60cbd893515687f137962d15f6467f30b#egg=acres
alabaster==0.7.13
astroid==2.15.8
Babel==2.14.0
certifi @ file:///croot/certifi_1671487769961/work/certifi
charset-normalizer==3.4.1
click==8.1.8
coverage==7.2.7
cycler==0.11.0
dill==0.3.7
docutils==0.19
exceptiongroup==1.2.2
fonttools==4.38.0
gensim==4.2.0
html2text==2020.1.16
idna==3.10
imagesize==1.4.1
importlib-metadata==6.7.0
iniconfig==2.0.0
isort==5.11.5
Jinja2==3.1.6
joblib==1.3.2
kiwisolver==1.4.5
lazy-object-proxy==1.9.0
MarkupSafe==2.1.5
matplotlib==3.5.3
mccabe==0.7.0
mypy==1.4.1
mypy-extensions==1.0.0
nltk==3.8.1
numpy==1.21.6
packaging==24.0
Pillow==9.5.0
platformdirs==4.0.0
pluggy==1.2.0
Pygments==2.17.2
pylint==2.17.7
pyparsing==3.1.4
pytest==7.4.4
pytest-cov==4.1.0
python-coveralls==2.9.3
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==6.0.1
regex==2024.4.16
requests==2.31.0
scikit-learn==1.0.2
scipy==1.7.3
six==1.17.0
smart-open==7.1.0
snowballstemmer==2.2.0
Sphinx==5.3.0
sphinx-autodoc-typehints==1.23.0
sphinxcontrib-applehelp==1.0.2
sphinxcontrib-devhelp==1.0.2
sphinxcontrib-htmlhelp==2.0.0
sphinxcontrib-jsmath==1.0.1
sphinxcontrib-qthelp==1.0.3
sphinxcontrib-serializinghtml==1.1.5
threadpoolctl==3.1.0
tomli==2.0.1
tomlkit==0.12.5
tqdm==4.67.1
typed-ast==1.5.5
typing_extensions==4.7.1
urllib3==2.0.7
wrapt==1.16.0
zipp==3.15.0

name: acres
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2022.12.7=py37h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=22.3.1=py37h06a4308_0
  - python=3.7.16=h7a1cb2a_0
  - readline=8.2=h5eee18b_0
  - setuptools=65.6.3=py37h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.38.4=py37h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - alabaster==0.7.13
      - astroid==2.15.8
      - babel==2.14.0
      - charset-normalizer==3.4.1
      - click==8.1.8
      - coverage==7.2.7
      - cycler==0.11.0
      - dill==0.3.7
      - docutils==0.19
      - exceptiongroup==1.2.2
      - fonttools==4.38.0
      - gensim==4.2.0
      - html2text==2020.1.16
      - idna==3.10
      - imagesize==1.4.1
      - importlib-metadata==6.7.0
      - iniconfig==2.0.0
      - isort==5.11.5
      - jinja2==3.1.6
      - joblib==1.3.2
      - kiwisolver==1.4.5
      - lazy-object-proxy==1.9.0
      - markupsafe==2.1.5
      - matplotlib==3.5.3
      - mccabe==0.7.0
      - mypy==1.4.1
      - mypy-extensions==1.0.0
      - nltk==3.8.1
      - numpy==1.21.6
      - packaging==24.0
      - pillow==9.5.0
      - platformdirs==4.0.0
      - pluggy==1.2.0
      - pygments==2.17.2
      - pylint==2.17.7
      - pyparsing==3.1.4
      - pytest==7.4.4
      - pytest-cov==4.1.0
      - python-coveralls==2.9.3
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==6.0.1
      - regex==2024.4.16
      - requests==2.31.0
      - scikit-learn==1.0.2
      - scipy==1.7.3
      - six==1.17.0
      - smart-open==7.1.0
      - snowballstemmer==2.2.0
      - sphinx==5.3.0
      - sphinx-autodoc-typehints==1.23.0
      - sphinxcontrib-applehelp==1.0.2
      - sphinxcontrib-devhelp==1.0.2
      - sphinxcontrib-htmlhelp==2.0.0
      - sphinxcontrib-jsmath==1.0.1
      - sphinxcontrib-qthelp==1.0.3
      - sphinxcontrib-serializinghtml==1.1.5
      - threadpoolctl==3.1.0
      - tomli==2.0.1
      - tomlkit==0.12.5
      - tqdm==4.67.1
      - typed-ast==1.5.5
      - typing-extensions==4.7.1
      - urllib3==2.0.7
      - wrapt==1.16.0
      - zipp==3.15.0
prefix: /opt/conda/envs/acres

tests/stats/test_dictionary.py::test_dump_sample
tests/stats/test_dictionary.py::test_show_extremes tests/stats/test_dictionary.py::test_ratio_acro_words tests/stats/test_dictionary.py::test_edit_distance_generated_acro tests/stats/test_dictionary.py::test_analyze_file
acres/model/expansion_standard.py acres/stats/dictionary.py acres/evaluation/evaluation.py acres/preprocess/resource_factory.py acres/resolution/resolver.py
acres/model/expansion_standard.py acres/stats/dictionary.py acres/evaluation/evaluation.py acres/preprocess/resource_factory.py acres/resolution/resolver.py