Study Vault Search notes, aliases and full text
Graph
ConceptDBISAI-written · not yet proofread

Q-Gram Index

A q-gram index stores for each q-gram of the (padded) dictionary words an inverted list of the ids of the words containing it, so that merging the lists of a query's q-grams yields the number of common q-grams with every word.

Know these firstInverted IndexQ-Gram

Formula#

Size (total number of entries in all inverted lists) for a vocabulary v1,…,vnv_1, \dots, v_n:

PaddingEntries
left only, q−1q-1 $ (PED)$\sum_{i=1}^{n} (
both sides, q−1q-1 $ each (ED)$\sum_{i=1}^{n} (

Using the index. For a query xx, padded like the index:

  1. compute Qq(x)Q_q(x),
  2. fetch the inverted list of each q-gram of Qq(x)Q_q(x),
  3. merge these ∣Qq(x)∣|Q_q(x)| lists and count how often each id occurs.

If yy occurs kk times in the merged result, then commq(x,y)=∣Qq(x)∩Qq(y)∣=k\mathrm{comm}_q(x, y) = |Q_q(x) \cap Q_q(y)| = k. Words absent from the result have commq(x,y)=0\mathrm{comm}_q(x, y) = 0; they only matter if the filter threshold of the Q-Gram Lemma is ≤0\le 0.

Properties#

  • A q-gram index is an Inverted Index with different objects: a document index maps each word to document ids, a q-gram index maps each q-gram to word ids. The construction code from Lecture 1 carries over almost unchanged.
  • Store ids, not the strings themselves.
  • The merge takes time linear in the total length of the fetched lists, typically far less than computing (P)ED for every y∈Dy \in D (ES8: ∣D∣≈1.7|D| \approx 1.7 million Wikidata entities).
  • Padding must match the distance: left only for PED, both sides for ED (see Q-Gram > Padding). The lecture code pads both sides; ES8 (PED) pads the left side only.

Construction (lecture code, padding = "$" * (q - 1)):

def q_grams(self, x: str) -> list[str]:
    x = self.padding + x + self.padding        # ED setting; for PED drop the right padding
    return [x[i : i + self.q] for i in range(len(x) - self.q + 1)]

def build_from_file(self, file_name: str):
    with open(file_name, "r") as file:
        word_id = 0
        for line in file:
            word_id += 1
            word = line.split("\t", 2)[0].lower()
            for q_gram in self.q_grams(word):
                if q_gram not in self.inverted_lists:
                    self.inverted_lists[q_gram] = []
                self.inverted_lists[q_gram].append(word_id)

Example#

Building (exam WS 18/19, Task 3.1): words abba, bab, aba, q=2q = 2, one $ on the left: $abba (id 1), $bab (id 2), $aba (id 3).

2-gramInverted list
$a1, 3
$b2
ab1, 2, 3
ba1, 2, 3
bb1

Querying (lecture): x=breix = \text{brei}, q=2q = 2, δ=1\delta = 1, PED. Padded $brei has the 2-grams $b, br, re, ei (∣Q2(x)∣=4|Q_2(x)| = 4):

$b : bangalore, beijing, berlin, …
br : brisbane, brussels, gibraltar, …
re : bangalore, freiburg, singapore, …
ei : beijing, freiburg, marseille, …

The threshold is 4−2⋅1=24 - 2 \cdot 1 = 2. Merging, bangalore, beijing and freiburg occur at least twice; only they are verified: PED(brei,bangalore)=3\mathrm{PED}(\text{brei}, \text{bangalore}) = 3 ✗, PED(brei,beijing)=1\mathrm{PED}(\text{brei}, \text{beijing}) = 1 ✓, PED(brei,freiburg)=1\mathrm{PED}(\text{brei}, \text{freiburg}) = 1 ✓.

Sources#

Search

Type In
↑ ↓ move ↵ open ⇥ next section Ctrl↵ results page Prefix # to search text only