Mastery course · Software and Computational Perfumery

Diffing Formula Versions

Compare two versions of a formula line by line on stable ids, report weight and share changes separately, and keep a history that explains every change.

In short

To see what changed between two versions of a formula, compare them line by line on material id and report two things for each line: its own change in weight or dilution, and its change in share. The second matters because a line whose weight is untouched still changes its share when anything else changes. A diff is only half the record; the other half is the reason for each change.

What you will learn

  • Compute a diff of two formula versions keyed on material id, classifying lines as added, removed, changed or unchanged
  • Explain why an unchanged weight can still change its share, and report both
  • Keep version history with reasons, in the app and in plain files
  • Use text-based version control for formula records, and know its limits

Before this lesson: Fragrance Calculations in Python, Checked, Compare Two Versions Blind: Study Guide, Formula Design and Iteration Log

Before you start

You need the program from fragrance calculations in Python, the habits of comparing versions and the iteration log. This is an external exercise.

A diff in a few lines

def pure_by_material(lines):
    out = {}
    for material, weight, dilution in lines:
        out[material] = out.get(material, 0.0) + weight * dilution / 100
    return out

def diff(old, new):
    a, b = pure_by_material(old), pure_by_material(new)
    ta, tb = sum(a.values()), sum(b.values())
    rows = []
    for m in sorted(set(a) | set(b)):
        pa, pb = a.get(m, 0.0), b.get(m, 0.0)
        ra, rb = 100 * pa / ta, 100 * pb / tb
        kind = ("added" if m not in a else "removed" if m not in b
                else "changed" if abs(pa - pb) > 1e-9 else "same")
        rows.append((m, kind, round(pa, 4), round(pb, 4), round(rb - ra, 4)))
    return rows

Summing by material before comparing also merges two lines of one material, which removes the duplicate-id weakness of the earlier program.

Worked example

Version 1: bergamot FCF 30 g, Hedione 25 g, Iso E Super 20 g, Ambroxan 5 g at 10%. Version 2 lowers Iso E Super to 15 g and adds 2 g of Timberol at 10%. The diff (pure grams, then change in relative share, in points):

The diff of version 1 against version 2 (arithmetic example)
MaterialStatusPure v1 → v2 (g)Share change
Iso E Superchanged20 → 15−5.27
Timberoladded0 → 0.2+0.28
Bergamot FCFsame30 → 30+2.70
Hedionesame25 → 25+2.25
Ambroxansame0.5 → 0.5+0.05

A reader who saw only "Iso E Super reduced, Timberol added" would miss that bergamot rose by nearly three points. Whether that matters is for the nose, but the record should not hide it.

In the RUŌOD Lab app

The app keeps versions by duplication. Duplicate makes a new formula named after the original with a version number (Amber v2), and the list marks each formula with its version and how many copies exist; the original is never changed. It has no side-by-side comparison. To diff, export each version (one formula at a time is available on every plan; see pricing for bulk export) as CSV or JSON, and run a comparison like the one above. The versions and reports tutorial shows those steps.

Text-based version control

Formulas stored as CSV or JSON files can be kept in a version-control system such as Git: every change becomes a commit with a message, and the history shows who changed what and when. Two cautions. Line-based text diffs know nothing about formulas, so a reordered file looks heavily changed; diff on ids as above for meaning. And a repository holding confidential formulas is itself confidential: never push one to a public service.

Where it stops

  • A diff describes, it does not evaluate. A two-point share change can be invisible or decisive.
  • Stocks must be identified. If v2 uses a new 10% dilution of Timberol made on another day, the stock id should differ, so that a bad dilution is traceable.

Practical exercise: Diff five versions of one formula

About 120 minutes · You will have: a diff report for each consecutive pair among five versions of one formula, each change linked to its reason in your iteration log

  1. Take a formula you developed through at least five versions, from your log or from the app.
  2. Export or transcribe each version as rows of (material id, weight, dilution).
  3. Diff each consecutive pair. For every change, quote the reason from your log; for every share drift above one point, note whether you intended it.
  4. Write one paragraph per version on what the diff shows that your log did not record.

You have done this well if every diff is keyed on ids, both weight changes and share drift are reported, every deliberate change has a reason from the time it was made, and you identify at least one unintended share drift.

Common mistakes

  • Diffing by line position. A reorder is not a reformulation.
  • Reporting only weights. Shares carry the olfactory meaning.
  • Editing an old version to "fix" it. Make a new one and record why.

Key terms

Diff
A list of the differences between two versions of a record. For a formula, keyed on material id, with each line marked added, removed, changed or unchanged.
Share drift
The change in a line's percentage caused by changes elsewhere in the formula, with its own weight unchanged.
Commit message
In version control, the short statement saved with each change saying why it was made. For formulas, the equivalent of the reason column in an iteration log.

Knowledge check

1. Iso E Super drops from 20 g to 15 g and Timberol 10% is added at 2 g. Bergamot's weight is unchanged. Does its relative share change?
Show the answer

Yes: it rises by about 2.7 points because the total pure material fell. Relative share is pure over total pure; the total fell from 75.5 g to 70.7 g, so every unchanged line's share rose.

2. Why key a diff on material id rather than line position?
Show the answer

Reordering lines would otherwise look like many changes. A position-based diff reports a reorder as a rewrite; an id-based diff reports what actually changed.

3. Does the RUŌOD Lab app compare two formula versions side by side?
Show the answer

No; Duplicate keeps each version as its own formula, and comparison is done by exporting and diffing. The app versions by duplication and marks versions; it has no comparison view, so the diff is an external step.

Written and reviewed by the RUŌOD Lab team. This is general education, not legal, regulatory, medical or safety advice. Example dilutions and exercises are for learning, are not validated products, and have not been safety-assessed. Completing a lesson confers no qualification. How we check these lessons.