lambeq.rewrite

class lambeq.rewrite.CoordinationRewriteRule(words: Container[str] | None = None)[source]

Bases: RewriteRule

A rewrite rule for coordination.

This rule matches the word ‘and’ with codomain a.r @ a @ a.l for pregroup type a, and replaces the word, based on [Kar2016], with a layer of interleaving spiders.

__call__(box: Box) Diagrammable | None

Apply the rewrite rule to a box.

Parameters:
boxlambeq.backend.grammar.Box

The candidate box to be tested against this rewrite rule.

Returns:
lambeq.backend.grammar.Diagram, optional

The rewritten diagram, or None if rule does not apply.

Notes

The default implementation uses the matches() and rewrite() methods, but derived classes may choose to not use them, since the default Rewriter implementation does not call those methods directly, only this one.

__init__(words: Container[str] | None = None) None[source]

Instantiate a CoordinationRewriteRule.

Parameters:
wordscontainer of str, optional

A list of words to be rewritten by this rule. If a box does not have one of these words, it will not be rewritten, even if the codomain matches. If omitted, the rewrite applies only to the word “and”.

matches(box: Box) bool[source]

Check if the given box should be rewritten.

rewrite(box: Box) Diagrammable[source]

Rewrite the given box.

class lambeq.rewrite.CurryRewriteRule[source]

Bases: RewriteRule

A rewrite rule using map-state duality.

__call__(box: Box) Diagrammable | None

Apply the rewrite rule to a box.

Parameters:
boxlambeq.backend.grammar.Box

The candidate box to be tested against this rewrite rule.

Returns:
lambeq.backend.grammar.Diagram, optional

The rewritten diagram, or None if rule does not apply.

Notes

The default implementation uses the matches() and rewrite() methods, but derived classes may choose to not use them, since the default Rewriter implementation does not call those methods directly, only this one.

__init__() None[source]

Instantiate a CurryRewriteRule.

This rule uses the map-state duality by iteratively uncurrying on both sides of each box. When used in conjunction with lambeq.backend.grammar.Diagram.pregroup_normal_form(), this removes cups from the diagram in exchange for depth. Diagrams with fewer cups become circuits with fewer post-selection, which results in faster QML experiments.

matches(box: Box) bool[source]

Check if the given box should be rewritten.

rewrite(box: Box) Diagrammable[source]

Rewrite the given box.

class lambeq.rewrite.DiagramRewriter[source]

Bases: ABC

Base class for diagram level rewriters.

__call__(target: list[lambeq.backend.grammar.Diagram]) list[lambeq.backend.grammar.Diagram][source]
__call__(target: Diagram) Diagram

Rewrite the given diagram(s) if the rule applies.

Parameters:
diagramlambeq.backend.grammar.Diagram

or list of Diagram

The candidate diagram(s) to be rewritten.

Returns:
lambeq.backend.gramar.Diagram or list of Diagram

The rewritten diagram. If the rule does not apply, the original diagram is returned.

abstract matches(diagram: Diagram) bool[source]

Check if the given diagram should be rewritten.

abstract rewrite(diagram: Diagram) Diagram[source]

Rewrite the given diagram.

class lambeq.rewrite.RemoveCupsRewriter[source]

Bases: DiagramRewriter

Removes cups from a given diagram.

Diagrams with less cups become circuits with less post-selection, which results in faster QML experiments.

__call__(target: list[Diagram] | Diagram) list[Diagram] | Diagram

Rewrite the given diagram(s) if the rule applies.

Parameters:
diagramlambeq.backend.grammar.Diagram

or list of Diagram

The candidate diagram(s) to be rewritten.

Returns:
lambeq.backend.gramar.Diagram or list of Diagram

The rewritten diagram. If the rule does not apply, the original diagram is returned.

matches(diagram: Diagram) bool[source]

Check if the given diagram should be rewritten.

rewrite(diagram: Diagram) Diagram[source]

Rewrite the given diagram.

class lambeq.rewrite.RemoveSwapsRewriter[source]

Bases: DiagramRewriter

Produce a proper pregroup diagram by removing any swaps.

Direct conversion of a CCG derivation into a string diagram form may introduce swaps, caused by cross-composition rules and unary rules that may change types and the directionality of composition at any point of the derivation. This class removes swaps, producing a valid pregroup diagram (in J. Lambek’s sense) as follows:

  1. Eliminate swap morphisms by swapping the actual atomic types of the words.

  2. Scan the new diagram for any detached parts, and remove them by merging words together when possible.

Parameters:
diagramlambeq.backend.grammar.Diagram

The input diagram.

Returns:
lambeq.backend.grammar.Diagram

A copy of the input diagram without swaps.

Raises:
ValueError

If the input diagram is not in “pregroup” form, i.e. when words do not strictly precede the morphisms.

Notes

The class trades off diagrammatic simplicity and conformance to a formal pregroup grammar for a larger vocabulary, since each word is associated with more types than before and new words (combined tokens) are added to the vocabulary. Depending on the size of your dataset, this might lead to data sparsity problems during training.

Examples

In the following example, “am” and “not” are combined at the CCG level using cross composition, which introduces the interwoven pattern of wires.

I       am            not        sleeping
─  ───────────  ───────────────  ────────
n  n.r·s·s.l·n  s.r·n.r.r·n.r·s   n.r·s
│   │  │  │  ╰─╮─╯    │    │  │    │  │
│   │  │  │  ╭─╰─╮    │    │  │    │  │
│   │  │  ╰╮─╯   ╰─╮──╯    │  │    │  │
│   │  │  ╭╰─╮   ╭─╰──╮    │  │    │  │
│   │  ╰──╯  ╰─╮─╯    ╰─╮──╯  │    │  │
│   │        ╭─╰─╮    ╭─╰──╮  │    │  │
│   ╰────────╯   ╰─╮──╯    ╰╮─╯    │  │
│                ╭─╰──╮    ╭╰─╮    │  │
╰────────────────╯    ╰─╮──╯  ╰────╯  │
                      ╭─╰──╮          │
                      │    ╰──────────╯

Rewriting with the RemoveSwapsRewriter class will return:

I     am not    sleeping
─  ───────────  ────────
n  n.r·s·s.l·n   n.r·s
╰───╯  │  │  ╰────╯  │
       │  ╰──────────╯

removing the swaps and combining “am” and “not” into one token.

__call__(target: list[Diagram] | Diagram) list[Diagram] | Diagram

Rewrite the given diagram(s) if the rule applies.

Parameters:
diagramlambeq.backend.grammar.Diagram

or list of Diagram

The candidate diagram(s) to be rewritten.

Returns:
lambeq.backend.gramar.Diagram or list of Diagram

The rewritten diagram. If the rule does not apply, the original diagram is returned.

matches(diagram: Diagram) bool[source]

Check if the given diagram should be rewritten.

rewrite(diagram: Diagram) Diagram[source]

Rewrite the given diagram.

class lambeq.rewrite.RewriteRule[source]

Bases: ABC

Base class for rewrite rules.

__call__(box: Box) Diagrammable | None[source]

Apply the rewrite rule to a box.

Parameters:
boxlambeq.backend.grammar.Box

The candidate box to be tested against this rewrite rule.

Returns:
lambeq.backend.grammar.Diagram, optional

The rewritten diagram, or None if rule does not apply.

Notes

The default implementation uses the matches() and rewrite() methods, but derived classes may choose to not use them, since the default Rewriter implementation does not call those methods directly, only this one.

abstract matches(box: Box) bool[source]

Check if the given box should be rewritten.

abstract rewrite(box: Box) Diagrammable[source]

Rewrite the given box.

class lambeq.rewrite.Rewriter(rules: Iterable[RewriteRule | str] | None = None)[source]

Bases: object

Class that rewrites diagrams.

Comes with a set of default rules.

__call__(diagram: Diagram) Diagram[source]

Apply the rewrite rules to the given diagram.

__init__(rules: Iterable[RewriteRule | str] | None = None) None[source]

Initialise a rewriter.

Parameters:
rulesiterable of str or RewriteRule, optional

A list of rewrite rules to use. RewriteRule instances are used directly, str objects are used as names of the default rules. See Rewriter.available_rules() for the list of rule names. If omitted, all the default rules are used.

add_rules(*rules: RewriteRule | str) None[source]

Add rules to this rewriter.

classmethod available_rules() list[str][source]

The list of default rule names.

class lambeq.rewrite.SimpleRewriteRule(cod: Ty, template: Diagrammable, words: Container[str] | None = None, case_sensitive: bool = False)[source]

Bases: RewriteRule

A simple rewrite rule.

This rule matches each box against a required codomain and, if provided, a set of words. If they match, the word box is rewritten into a set template.

__call__(box: Box) Diagrammable | None

Apply the rewrite rule to a box.

Parameters:
boxlambeq.backend.grammar.Box

The candidate box to be tested against this rewrite rule.

Returns:
lambeq.backend.grammar.Diagram, optional

The rewritten diagram, or None if rule does not apply.

Notes

The default implementation uses the matches() and rewrite() methods, but derived classes may choose to not use them, since the default Rewriter implementation does not call those methods directly, only this one.

__init__(cod: Ty, template: Diagrammable, words: Container[str] | None = None, case_sensitive: bool = False) None[source]

Instantiate a simple rewrite rule.

Parameters:
codlambeq.backend.grammar.Ty

The type that the codomain of each box is matched against.

templatelambeq.backend.grammar.Diagrammable

The diagram that a matching box is replaced with. A special placeholder box is replaced by the word in the matched box, and can be created using SimpleRewriteRule.placeholder().

wordscontainer of str, optional

If provided, this is a list of words that are rewritten by this rule. If a box does not have one of these words, it is not rewritten, even if the codomain matches. If omitted, all words are permitted.

case_sensitivebool, default: False

This indicates whether the list of words specified above are compared case-sensitively. The default is False.

matches(box: Box) bool[source]

Check if the given box should be rewritten.

classmethod placeholder(cod: Ty) Word[source]

Helper function to generate the placeholder for a template.

Parameters:
codlambeq.backend.grammar.Ty

The codomain of the placeholder, and hence the word in the resulting rewritten diagram.

Returns:
lambeq.backend.grammar.Word

A placeholder word with the given codomain.

rewrite(box: Box) Diagrammable[source]

Rewrite the given box.

class lambeq.rewrite.UnifyCodomainRewriter(output_type: Ty = Ty(s))[source]

Bases: DiagramRewriter

Unifies the codomain of diagrams to match a given type.

A rewriter that takes diagrams with d.cod != output_type and append a d.cod -> output_type box.

Attributes:
output_typelambeq.backend.grammar.Ty, default S

The output type of the appended box.

__call__(target: list[Diagram] | Diagram) list[Diagram] | Diagram

Rewrite the given diagram(s) if the rule applies.

Parameters:
diagramlambeq.backend.grammar.Diagram

or list of Diagram

The candidate diagram(s) to be rewritten.

Returns:
lambeq.backend.gramar.Diagram or list of Diagram

The rewritten diagram. If the rule does not apply, the original diagram is returned.

__init__(output_type: Ty = Ty(s)) None
matches(diagram: Diagram) bool[source]

Check if the given diagram should be rewritten.

output_type: Ty = Ty(s)
rewrite(diagram: Diagram) Diagram[source]

Rewrite the given diagram.

class lambeq.rewrite.UnknownWordsRewriteRule(vocabulary: Container[str | tuple[str, Ty]], unk_token: str = '<UNK>')[source]

Bases: RewriteRule

A rewrite rule for unknown words.

This rule matches any word not included in its vocabulary and, when passed a diagram, replaces all the boxes containing an unknown word with an UNK box corresponding to the same pregroup type.

__call__(box: Box) Diagrammable | None

Apply the rewrite rule to a box.

Parameters:
boxlambeq.backend.grammar.Box

The candidate box to be tested against this rewrite rule.

Returns:
lambeq.backend.grammar.Diagram, optional

The rewritten diagram, or None if rule does not apply.

Notes

The default implementation uses the matches() and rewrite() methods, but derived classes may choose to not use them, since the default Rewriter implementation does not call those methods directly, only this one.

__init__(vocabulary: Container[str | tuple[str, Ty]], unk_token: str = '<UNK>') None[source]

Instantiate an UnknownWordsRewriteRule.

Parameters:
vocabularycontainer of str or tuple of str and Ty

A list of words (or words with specific output types) to not be rewritten by this rule.

unk_tokenstr, default: ‘<UNK>’

The string to use for the UNK token.

classmethod from_diagrams(diagrams: Iterable[Diagram], min_freq: int = 1, unk_token: str = '<UNK>', ignore_types: bool = False) UnknownWordsRewriteRule[source]

Create the rewrite rule from a set of diagrams.

The vocabulary is the set of words that occur at least min_freq times throughout the set of diagrams.

Parameters:
diagramslist of Diagram

Diagrams from which the vocabulary is created.

min_freqint, default: 1

The minimum frequency required for a word to be included in the vocabulary.

unk_tokenstr, default: ‘<UNK>’

The string to use for the UNK token.

ignore_typesbool, default: False

Whether to just consider the word when determining frequency or to also consider the output type of the box (the default behaviour).

matches(box: Box) bool[source]

Check if the given box should be rewritten.

rewrite(box: Box) Box[source]

Rewrite the given box.