All Downloads are FREE. Search and download functionalities are using the official Maven repository.

models.examples.toys.numbering.als Maven / Gradle / Ivy

module examples/toys/numbering

/*
 * Alloy model of paragraph numbering
 *
 * This model addresses some issues that arose in the design of a text tagging tool. The
 * tool receives as input a text stream in which paragraphs are tagged with style names,
 * along with a style sheet that indicates how paragraphs of a given style are to be numbered.
 * In practice, the style sheet includes such details as what symbols to use for numbering (eg,
 * roman numericals, letters of the alphabet, etc), but these details are uninteresting.
 *
 * In the simplest case, the styles are organized into chains. For example, there may be a
 * single chain, chapter-section-subsection, so that chapters are numbered 1, 2, 3, etc,
 * sections are numbered 1.1, 1.2, 1.3, etc, and subsections are numbered 1.1.1, 1.1.2,
 * etc, each paragraph being numbered according to a number associated with its own
 * style, and a number for each ancestor.
 *
 * Some styles, however, should be numbered independently of one another, but still
 * according to the same ancestors. For example, we might also have a figure style
 * that is numbered, like section, according to its chapter, with figures and sections in
 * some arbitrary interleaving, the numbering of one not affecting the other.
 *
 * So in our style hierarchy, a style can have more than one "child". A more tricky complication
 * allows multiple parents. We might want to have an appendix style, for example, with a
 * different numbering from the chapter style, but would want section and subsection to work
 * within appendix exactly as they would work within chapter. So the first section in an
 * appendix numbered A might be numbered A.1, but if placed in a chapter numbered 1,
 * it would be numbered 1.1 instead.
 *
 * To account for this, styles are organized into replacement classes. Chapter and appendix,
 * for example, are replacements of one another. When a chapter style is encountered, it
 * is as if the style hierarchy contains only chapter, with children section, figure and so on;
 * when appendix is encountered subsequently, chapter is replaced, and figure and section
 * become children of appendix. We'll call the set of styles active in the tree at a given time
 * the "context".
 *
 * The first part focuses on the replacement mechanism. It characterizes a well-formed
 * style sheet (with the fact StyleSheet), and a well-formed state (with the fact Forest). An
 * operation addStyleToContext describes how the context is altered, and includes a
 * precondition requiring that, for example, a child is not encountered before its parents
 * (a document can't start with subsection, eg). The assertion PreservesForest checks that the
 * operation preserves the well-formedness of the state; it was analyzing this that helped
 * determine an appropriate precondition and the appropriate constraints in the invariant.
 *
 * The second part adds the numbering of styles. Note the idiom of declaring a subsignature
 * and then equating it to the supersignature, thus essentially retrofitting the new fields to the
 * old signature. A second operation describes how numbers are assigned; the conjunction of the
 * two operations is what happens when a style is encountered. The assertion AddNeverReduces
 * checks that when a style is encountered the number associated with each style in the context is
 * not decreased. The first assertion is valid; the second isn't.
 *
 * author: Daniel Jackson, 11/15/01
 */

open util/relation as rel

sig Style {
    replaces, parents: set Style
    }

fact StyleSheet {
    equivalence [replaces, Style]
    acyclic [parents, Style]
    all x: Style {
        x.replaces.parents.replaces = x.parents
        all y,z: x.parents | y in z.replaces
        }
    }

sig State {
    context: set Style,
    ancestors: Style -> Style
    }

fact DefineAncestors {
    all s: State, x: Style | s.ancestors [x] = x.*parents & s.context
    }

pred Forest [s: State] {
    all x: s.context |
        some root: s.ancestors[x] {
            no root.parents
            all y: s.ancestors[x] - root | one y.parents & s.context
            }
    all x: Style | lone x.replaces & s.context
    }

pred AddStyleToContext [s, s': State, style: Style] {
    all x: style.^parents | some x.replaces & s.context
    s'.context = s.context - style.replaces + style
    }

assert PreserveForest {
    all s,s': State, z: Style |
        Forest[s] && AddStyleToContext [s,s',z] => Forest[s']
    }

check PreserveForest for 4 expect 0

sig Value {next: Value}
sig NumberedStyle extends Style {
    initial: Value
    }
sig NumberedState extends State {
    value: Style -> one Value
    }
fact {Style = NumberedStyle}
fact {State = NumberedState}

pred AddStyleToNumbering [s, s': State, style: Style] {
    s'.value[style] = (style in s.context => s.value[style].next else style.initial)
    s'.context = s.context - style.replaces + style
    all x: Style - style |
        s'.value[x] = (style in x.^parents => x.initial else s.value[x])
    }

pred AddStyle [s, s': State, style: Style] {
    AddStyleToContext [s,s',style]
    AddStyleToNumbering [s,s',style]
    }

assert AddNeverReduces {
    all s,s': State, z: Style |
        Forest[s] && AddStyle [s,s',z] =>
            (all y: s'.context | s'.value[y] in s.value[y].*next)
    }

check AddNeverReduces for 5 expect 1





© 2015 - 2025 Weber Informatics LLC | Privacy Policy