Rapid equilibrium vs steady state
Every step in a mechanism is either rapid equilibrium (RE) or steady state (SS). That single flag drives parameter count: RE steps cost one parameter each, while SS steps cost two.
The flag in the DSL
In @enzyme_mechanism, ⇌ marks a step as rapid equilibrium and <--> marks it as steady state. The distinction is stored on each Step as the is_equilibrium field.
Parameter count per step
- An RE binding step contributes one parameter: a dissociation constant
Kd, rendered asK_<metabolite>_<form>(for example,K_S_E). - An RE isomerization step contributes one parameter: an isomerization constant
Kiso, rendered asKiso_<from>_to_<to>(for example,Kiso_ES_to_EP). - An SS binding step contributes two rate constants:
kon_<met>_<form>andkoff_<met>_<form>. - An SS isomerization step contributes two directed rate constants:
k_<from>_to_<to>andk_<to>_to_<from>.
A concrete comparison
A one-substrate reaction barely distinguishes the two assumptions — the rapid-equilibrium and steady-state rate laws differ only in how three or four constants are named. The difference becomes obvious for even the simplest mechanisms with more than one substrate or product. Take an ordered bi-uni reaction — A binds, then B, the complex isomerizes, and P leaves — first as a rapid-equilibrium mechanism with steady-state catalysis:
using EnzymeRates
re = @enzyme_mechanism begin
substrates: A, B
products: P
steps: begin
E + A ⇌ E(A)
E(A) + B ⇌ E(A, B)
E(A, B) <--> E(P)
E(P) ⇌ E + P
end
end
parameters(re)(:K_A_E, :K_B_EA, :K_P_E, :k_EAB_to_EP, :Keq, :E_total)Six parameters, and a compact rate law:
print(rate_equation_string(re))(; K_A_E, K_B_EA, K_P_E, k_EAB_to_EP, Keq, E_total) = params
(; A, B, P) = concs
# Haldane constraints:
k_EP_to_EAB = (1 / Keq) * (1 / K_A_E) * (1 / K_B_EA) * K_P_E * k_EAB_to_EP
v = E_total * (k_EAB_to_EP * A * B / (K_A_E * K_B_EA) - k_EP_to_EAB * P / K_P_E) / (1 + A / K_A_E + P / K_P_E + A * B / (K_A_E * K_B_EA))Now the same skeleton with every step made steady state:
ss = @enzyme_mechanism begin
substrates: A, B
products: P
steps: begin
E + A <--> E(A)
E(A) + B <--> E(A, B)
E(A, B) <--> E(P)
E(P) <--> E + P
end
end
parameters(ss)(:k_EAB_to_EP, :koff_A_E, :koff_B_EA, :koff_P_E, :kon_A_E, :kon_B_EA, :kon_P_E, :Keq, :E_total)Nine parameters — each binding step trades its single K for an independent kon/koff pair — and the rate law is far larger:
print(rate_equation_string(ss))(; k_EAB_to_EP, koff_A_E, koff_B_EA, koff_P_E, kon_A_E, kon_B_EA, kon_P_E, Keq, E_total) = params
(; A, B, P) = concs
# Haldane constraints:
k_EP_to_EAB = (1 / Keq) * k_EAB_to_EP * (1 / koff_A_E) * (1 / koff_B_EA) * koff_P_E * kon_A_E * kon_B_EA * (1 / kon_P_E)
v = E_total * (k_EAB_to_EP * koff_P_E * kon_A_E * kon_B_EA * A * B - k_EP_to_EAB * koff_A_E * koff_B_EA * kon_P_E * P) / (k_EAB_to_EP * koff_A_E * koff_P_E + k_EP_to_EAB * koff_A_E * koff_B_EA + koff_A_E * koff_B_EA * koff_P_E + k_EAB_to_EP * koff_P_E * kon_A_E * A + k_EP_to_EAB * koff_B_EA * kon_A_E * A + koff_B_EA * koff_P_E * kon_A_E * A + k_EAB_to_EP * koff_P_E * kon_B_EA * B + k_EAB_to_EP * koff_A_E * kon_P_E * P + k_EP_to_EAB * koff_A_E * kon_P_E * P + k_EP_to_EAB * koff_B_EA * kon_P_E * P + koff_A_E * koff_B_EA * kon_P_E * P + k_EAB_to_EP * kon_A_E * kon_B_EA * A * B + k_EP_to_EAB * kon_A_E * kon_B_EA * A * B + koff_P_E * kon_A_E * kon_B_EA * A * B + k_EAB_to_EP * kon_B_EA * kon_P_E * B * P + k_EP_to_EAB * kon_B_EA * kon_P_E * B * P)The contrast is structural, not cosmetic. The rapid-equilibrium denominator has one term per reachable enzyme form — 1, A, A·B, and P, four terms — because every binding step factors out as a pre-equilibrium segment. The steady-state denominator keeps those same four terms but adds new ones in B and B·P: nothing factors out, so the King–Altman treatment carries a term for every enzyme-form pattern, with products of on/off rates throughout. Those extra terms give the steady-state equation qualitatively different behaviour — not the same form with renamed constants — and after thermodynamic reduction it still keeps more independent parameters, because each binding step starts with two rate constants instead of one. Mechanisms with random-order binding diverge even more drastically: their steady-state rate equations can carry squared concentration terms, which users can confirm for themselves by building a random-order mechanism and printing its rate equation.
The RE assumption
Rapid equilibrium assumes the binding step relaxes to equilibrium on a time scale much faster than the catalytic step. When that assumption holds, the single Kd is sufficient. When it does not hold, the full on/off pair is needed.
The The Cha / King–Altman algorithm solves the full Cha steady state regardless of whether individual steps are RE or SS; RE steps simply factor out of the rate matrix as pre-equilibrium segments, giving the familiar K_met_form notation in the denominator.