Tutorials › Pharmacometric Workflows and Reproducible Modeling › Comparing Model Code With Its Written Specification

Quality Control and Independent Review · Tutorial 328 of 399

Comparing Model Code With Its Written Specification

You will learn to compare a model’s written specification with its executable code using traceable component links rather than simple name matching.

Intermediate 10 min read

What You'll Learn

  • Set a clear scope for a specification-to-code comparison.
  • Inventory structural, covariate, and error-model components at a consistent level.
  • Link semantically corresponding items even when their names differ.
  • Identify declared components with no linked implementation.
  • Flag implemented terms with no linked specification support.
  • Record uncertainty and distinguish component mapping from deeper code validation.

Why Compare the Specification With the Code?

A written model specification describes what an analysis is intended to implement; model code expresses what the software is instructed to run. These records can diverge even when each looks plausible on its own. A covariate effect may be described but omitted from the executable code, or a term may remain in the code after it has been removed from the approved specification. Either discrepancy can affect interpretation, estimation, or reproducibility.

The task here is a component-level comparison. The reviewer identifies declared structural, covariate, and error-model components, locates their corresponding implementation in the relevant code, and flags components on either side that lack support on the other. This mapping does not by itself establish that a coded equation is mathematically correct; it establishes which code is intended to represent which specification item and where review attention is needed.

Definition: A declared component is a structural, covariate, or error-model element stated in the in-scope written specification. An implemented component is an element that affects the executable model on the run path being reviewed. A link is an evidence-supported claim that a particular implementation corresponds to a particular declared component.

The comparison depends on a defined review scope. The specification and code must be identified by version or other unambiguous references, and the code examined must be the code used for the run under review, including relevant generated or included files. The reviewer also needs a consistent inventory unit: for example, list a covariate effect as one component rather than listing it once as a general concept and again as several unrelated fragments. If the specification is ambiguous, or the active code path cannot be established, record that uncertainty rather than treating a guess as a confirmed link.

Build Two Inventories and a Link Record

Start by listing declared components and implemented components separately. For each item, record its category, a concise description, and where it is evidenced: a section or table in the specification, and a code location or generated-code location in the implementation. Then record the links between the inventories.

Names are not reliable component identities. A specification might say “body size effect on clearance,” while code uses the variable abbreviation “WT” and a parameterized expression. Different labels can refer to corresponding components; conversely, a matching label in a comment may not be active model code. Therefore, do not infer correspondence from literal string equality alone.

Definition: Let \(D\) be the inventory of declared components and \(I\) the inventory of implemented components. Let \(R\) be a reviewed correspondence relation, where \((d,i)\in R\) means that evidence supports linking declared component \(d\) to implemented component \(i\). The declared components with no linked implementation are \(\{d\in D:\text{there is no }i\in I\text{ such that }(d,i)\in R\}\). The implemented components with no linked specification support are \(\{i\in I:\text{there is no }d\in D\text{ such that }(d,i)\in R\}\).

These unmatched sets are defined by the recorded links, not by subtracting two lists of differently named items. A link may be one-to-one, or, where justified by the specification and code structure, may connect one declared component to multiple implementation locations or multiple declared components to a shared code construct. Such cases should be explained in the link record; they should not be forced into a one-to-one match just to simplify a table.

A useful status vocabulary is linked, unmatched, and unresolved. “Unmatched” means no supported link was found after the in-scope evidence was examined. “Unresolved” means correspondence cannot yet be decided, perhaps because a macro expansion is unavailable or wording is ambiguous. Do not count unresolved items as confirmed matches or quietly report them as omissions.

A Practical Comparison Workflow

1
Fix the review boundary.
Identify the exact specification, source files, generated files, and run or branch under review. Note any missing artifacts that could hide an active implementation.
2
Inventory declared components.
Extract each in-scope structural, covariate, and error-model item from the specification, retaining its wording and location. Split or combine entries consistently so that each is reviewable at a useful component level.
3
Inventory implemented components.
Inspect executable code and relevant expansions or includes. Record active model terms, not merely comments, inactive examples, or unused variables, and retain their code locations.
4
Evaluate candidate links.
For each proposed correspondence, compare its role and context, not only its label. Record the evidence for the link and mark doubtful cases unresolved pending clarification.
5
Report both directions.
List declared items with no linked implementation and implemented items with no linked specification support. Also identify partial links, unresolved items, and the evidence needed to close them.

This workflow is valid only to the extent that the reviewed inventories cover the stated scope and the code path is correctly identified. It is not enough to inspect a convenient source file if the run executes generated code, selects a conditional branch, or imports a model fragment from elsewhere. Likewise, a specification’s heading alone is not evidence that all its details have been inventoried.

Worked Example: Linking Structural Components Despite Different Names

Hypothetical review. A written specification lists three structural components: a two-compartment disposition structure, first-order transfer between the central and peripheral compartments, and first-order elimination from the central compartment. The executable model contains code sections labelled “COMPARTMENT SETUP,” “Q TRANSFER,” and “CL CLEARANCE.” For this example, assume the reviewer has verified that these sections are active in the run and has inspected enough surrounding code to identify their roles.

The declared inventory has three entries, \(D=\{d_1,d_2,d_3\}\), and the implementation inventory has three entries, \(I=\{i_1,i_2,i_3\}\). The label “two-compartment disposition structure” does not literally match “COMPARTMENT SETUP,” but the active code section establishes the compartment structure. Similarly, the transfer and clearance labels are supported by their active code context.

The reviewer records \(R=\{(d_1,i_1),(d_2,i_2),(d_3,i_3)\}\), with a code location and specification location for each pair. For \(d_1\), there is an \(i\in I\) such that \((d_1,i)\in R\), so \(d_1\) is not in the declared-unmatched set. The same check holds for \(d_2\) and \(d_3\). Each implementation entry is also linked to a declared item, so the implemented-unmatched set is empty.

The result is three supported component links and no unmatched items in this scoped inventory. It is not a conclusion that every structural equation is correctly translated: detailed comparison of equation form and parameterization requires a separate, deeper check.

What Counts as Support?

A convincing link is supported by more than a shared word. Useful evidence includes the specification’s description of a component, the code location that defines or uses it, and the execution context showing that the code is active for the reviewed run. A comment can help explain intent, but a comment without an active implementation does not establish that a component is implemented. Likewise, an active term with a familiar label is not supported by the specification unless its role corresponds to a declared item.

At this stage, ask whether the code construct represents the specified component and whether it is in scope. Avoid silently extending the task into a full re-derivation of the model. For example, a reviewer can link a declared “body size effect on clearance” to the active code term that uses WT in the clearance expression, while separately noting that this mapping does not yet confirm the precise functional form, scaling, or units.

Worked Example: Flagging an Implemented Covariate Without Specification Support

Hypothetical review. The specification declares a body-size effect on clearance and an age effect on volume. The active code contains a WT term in the clearance component and an AGE term in the volume component. It also contains an active indicator term for renal impairment in the clearance component. No in-scope specification section mentions renal impairment. Assume the reviewer has checked the active code path and searched the complete, applicable specification.

The declared inventory contains two items: body size on clearance and age on volume. The implementation inventory contains three: WT on clearance, AGE on volume, and renal-impairment indicator on clearance. The evidence supports links from body size on clearance to WT on clearance, and from age on volume to AGE on volume. Different names do not prevent these links because the component roles and code context agree.

The third implemented item has no linked declared item. Thus the implemented-unmatched set contains only the renal-impairment indicator on clearance. The declared-unmatched set is empty: both declared items have linked code. The appropriate finding is that the renal-impairment term is implemented but lacks specification support in the reviewed scope. It is not automatically proof that the term is erroneous; a missing or superseded specification could explain it. The finding should identify the code location and request clarification or an authoritative specification update.

Counting illustrates why both directions matter. There are two declared items and three implemented items, with two supported links. The difference in inventory sizes is one, but the review result is not obtained by relying on that arithmetic alone: the links identify precisely which item is unsupported. A different arrangement could have three declared items and three implemented items while still containing both an omission and an unsupported addition.

Reviewing Covariate and Error-Model Components

Use the same linking logic for each component class, while keeping the inventory entries specific enough to be useful. A covariate entry should identify the covariate and the model component it is declared to affect, rather than simply saying “covariates included.” An error-model entry should describe the declared error structure at the level stated in the specification. A broad statement such as “residual error is modeled” may not support a detailed code term unless the specification gives enough detail to establish their correspondence.

Worked Example: Comparing Error-Model Inventories

Hypothetical review. The written specification states that the observation model uses a proportional error component. The active code contains a proportional component and an additive component in its observation-error expression. The reviewer verifies that both terms are active, not disabled alternatives, and finds no specification statement supporting an additive component.

The declared inventory is \(D=\{d_1\}\), where \(d_1\) is the proportional error component. The implementation inventory is \(I=\{i_1,i_2\}\), where \(i_1\) is the proportional component and \(i_2\) is the additive component. Evidence supports the link \((d_1,i_1)\). There is no declared item linked to \(i_2\), so the implemented-unmatched set is \(\{i_2\}\); the declared-unmatched set is empty.

The review finding is narrowly stated: “The active code includes an additive error component with no support identified in the reviewed specification.” It should not claim that the entire observation model is wrong based solely on this mapping exercise. The next action is to establish whether the specification is incomplete, the code contains an unintended term, or the code path was misunderstood.

Common Failure Modes and Appropriate Checks

  • Taking set differences of raw labels. Names such as “body size” and “WT” can denote corresponding components. Define links between items first, or normalize both inventories to rigorously defined canonical identities; then determine unmatched items from the links.
  • Treating a code search as a complete audit. A text match may be in a comment, inactive branch, or unused definition. Establish that the term is part of the code path used in the run.
  • Using inconsistent granularity. If one inventory has a single “covariate model” item and the other lists each covariate effect separately, apparent unmatched items may reflect inventory design rather than a model discrepancy. Reconcile the component level before judging coverage.
  • Calling uncertainty an omission. If a generated file or specification appendix is unavailable, report the item as unresolved and state what evidence is missing.
  • Claiming equation correctness from a component link. A link shows correspondence at the chosen inventory level. It does not prove algebraic equivalence, units, parameterization, or run-time behavior.

A manual crosswalk is often the clearest approach for a small model or a small number of ambiguous components. A script can help enumerate labels, file locations, or inventory rows for a larger project, but automated string matching should produce candidate links, not final correspondence decisions. Regardless of tool, retain enough evidence for another reviewer to reproduce the link decisions.

Key takeaway: Compare two inventories through evidence-supported correspondence links. Report declared items with no linked implementation and implemented items with no linked specification support separately; different labels alone establish neither a match nor a mismatch.

Check Your Understanding

For each question, identify the appropriate comparison result. Solutions follow the questions.

  1. A specification declares “body size effect on clearance.” Active code implements a WT term on clearance. What should the reviewer do before classifying either item as unmatched?
  2. A specification lists three components and code lists three components. Does equal inventory size establish that every component is supported in both directions? Explain.
  3. The specification declares an age effect on volume. Code includes an active AGE-on-volume term and an active renal-function-on-clearance term, which has no specification support after the in-scope documents are checked. State both unmatched sets.
  4. A search finds a matching model term only in a commented-out code block. Is that sufficient evidence of implementation for the reviewed run? Why or why not?

Solutions. (1) Inspect the component roles and relevant active code context, then record an evidence-supported link if WT represents the specified body-size effect; the different names alone do not determine correspondence. (2) No. Equal counts do not establish pairwise correspondence; the reviewer must record supported links and identify any declared or implemented items without links. (3) The declared-unmatched set is empty because age on volume has a linked active term. The implemented-unmatched set contains renal function on clearance because no declared component links to it. (4) No. A commented-out term is not evidence that the component is implemented on the run path; check the active executable or generated code and record the item as unmatched or unresolved according to the available evidence.

Clinical Biostats