Once the assertions have all been read and reduced to inferences, and all the creations have been made, we take stock; sometimes we spot inconsistencies, sometimes we make deductions, and we try to complete our picture of the model world.


§1. Stages II to IV. The process of using existing facts to infer new ones is vulnerable to timing bugs, so we organise the "making" process into five numbered stages, given the Roman numerals I to V. Much of the work is done by plugins, which can take a hand at any or all of the stages, using their contextual knowledge to fill in missing properties.

The following routine, then, carries out stages II, III and IV.

void World::complete(void) {
    Stages II and III of the completion process1.1;
    Stage IV of the completion process1.2;
}

§1.1. The model world is a broth with many cooks. On the one hand, we have the various different INFSs, with their different needs — a various-to-various relation, a global variable, and so on — and on the other hand we also have the plugins, each of which takes its own global view of the situation. We give everyone a turn.

Stages II and III of the completion process1.1 =

    inference_subject *infs;
    LOOP_OVER(infs, inference_subject) {
        InferenceSubjects::complete_model(infs);
        Properties::Appearance::reallocate(infs);
    }
    LOOP_OVER(infs, inference_subject)
        Assertions::Implications::consider_all(infs);
    Plugins::Call::complete_model(2);
    Plugins::Call::complete_model(3);

§1.2. Checking what we have, then. Once again each INFS is given an opportunity to check itself, and then the plugins have a turn.

Stage IV of the completion process1.2 =

    inference_subject *infs;
    LOOP_OVER(infs, inference_subject) {
        InferenceSubjects::check_model(infs);
        Check that properties are permitted1.2.1;
        Check that properties are not contradictory1.2.2;
    }
    Plugins::Call::complete_model(4);

§1.2.1. These two checks may seem a little odd. After all, we've been throwing out impossible inferences with problem messages all along, while reading the source text. Why not perform these checks then, too?

The answer is that both depend not only on the subject of the inferences made, but also on what that subject inherits from. Suppose we are told:

The cup is in the Yellow Cupboard. The Cupboard is lighted.

When we make the "lighted" inference, we know for certain what subject it's about — the Yellow Cupboard — but not where this lives in the inference-subject hierarchy, because that depends on the kind of the Cupboard. Is it a room, or a container? We don't yet know (and won't until Stage I of model-completion), so we aren't in a position to judge whether or not it's permitted to have the property "lighted". This is why the check is postponed until after Stage I, and it seems natural to perform it here in Stage IV, so that we also catch any accidents due to bugs in plugins which add inconsistent properties.

A nameless property added in Stages II and III does not need permission.

Check that properties are permitted1.2.1 =

    inference *inf;
    KNOWLEDGE_LOOP(inf, infs, PROPERTY_INF) {
        property *prn = World::Inferences::get_property(inf);
        if (Wordings::nonempty(prn->name))
            if (World::Permissions::find(infs, prn, TRUE) == NULL)
                Problems::Issue::inference_problem(_p_(PM_PropertyNotPermitted),
                    infs, inf, "is not allowed to exist",
                    "because you haven't said it is. What properties something can "
                    "have depends on what kind of thing it is: see the Index for "
                    "details.");
    }

§1.2.2. The following contradiction checks do not apply to properties added in Stages II and III, since those are often I6 hacks added for run-time convenience, and don't have to follow the I7 rules.

Check that properties are not contradictory1.2.2 =

    inference *narrow;
    KNOWLEDGE_LOOP(narrow, infs, PROPERTY_INF) {
        if (World::Inferences::added_in_construction(narrow) == FALSE) {
            property *prn = World::Inferences::get_property(narrow);
            int sign = 1;
            if (World::Inferences::get_certainty(narrow) < 0) sign = -1;
            Look for clashes concerning this property from wider inferences1.2.2.1;
            if ((Properties::is_either_or(prn)) && (Properties::EitherOr::get_negation(prn))) {
                prn = Properties::EitherOr::get_negation(prn);
                sign = -sign;
                Look for clashes concerning this property from wider inferences1.2.2.1;
            }
        }
    }

§1.2.2.1. Look for clashes concerning this property from wider inferences1.2.2.1 =

    inference_subject *boss = InferenceSubjects::narrowest_broader_subject(infs);
    while (boss) {
        inference *wide;
        KNOWLEDGE_LOOP(wide, boss, PROPERTY_INF)
            if (World::Inferences::added_in_construction(wide) == FALSE)
                if (prn == World::Inferences::get_property(wide))
                    Check that these differently scoped inferences do not clash1.2.2.1.1;
        boss = InferenceSubjects::narrowest_broader_subject(boss);
    }

§1.2.2.1.1. It's never a problem when a vague fact about something general is contradicted by a fact about something specific; the problem comes with something like this:

A door is always open. The Marble Portal is a closed door.

Here the "wide" property inference, for the "door" kind, is CERTAIN_CE rather than LIKELY_CE, and so we can't allow the "narrow" inference, about the Portal, to stand.

Check that these differently scoped inferences do not clash1.2.2.1.1 =

    int abcw = World::Inferences::get_certainty(wide); if (abcw < 0) abcw = -abcw;
    if (abcw == CERTAIN_CE) {
        int clash = FALSE;
        int wide_sign = 1; if (World::Inferences::get_certainty(wide) < 0) wide_sign = -1;
        if (Properties::is_either_or(prn) == FALSE) {
            parse_node *narrow_val = World::Inferences::get_property_value(narrow);
            parse_node *wide_val = World::Inferences::get_property_value(wide);
            if (Rvalues::compare_CONSTANT(narrow_val, wide_val) == FALSE) {
                LOG("Clash of $P and $P\n  $I\n  $I\n",
                    narrow_val, wide_val, narrow, wide);
                clash = TRUE;
            }
        }
        if (sign != wide_sign) clash = (clash)?FALSE:TRUE;
        if (clash) {
            int abcn = World::Inferences::get_certainty(narrow); if (abcn < 0) abcn = -abcn;
            if (abcn == CERTAIN_CE)
                 Issue a problem message for clash with wider inference1.2.2.1.1.1
            else
                World::Inferences::set_certainty(narrow, IMPOSSIBLE_CE);
        }
    }

§1.2.2.1.1.1. Issue a problem message for clash with wider inference1.2.2.1.1.1 =

    LOG("Checking infs $j compatible with infs $j for property $Y:\n  $I\n  $I\n",
        infs, boss, prn, narrow, wide);
    Problems::Issue::infs_contradiction_problem(_p_(PM_InstanceContradiction),
        World::Inferences::where_inferred(narrow), World::Inferences::where_inferred(wide), infs,
        "therefore has to have two contradictory states of the same property at once",
        "which is impossible. When a kind's definition says that something is 'always' "
        "true, there is no way to override that for particular things of the kind.");

§2. Stage V. See above. This is for the use of plugins only.

void World::complete_additions(void) {
    Plugins::Call::complete_model(5);
}