Skip to content

Same results as GECKO for subsets, subsystems, uniprot cells, FSEOF and pFBA; scipy solver support - #72

Merged
edkerk merged 17 commits into
developfrom
fix/parity-round-3
Oct 30, 2026
Merged

edkerk merged 17 commits into
developfrom
fix/parity-round-3

Conversation

@edkerk

@edkerk edkerk commented Oct 30, 2026

Copy link
Copy Markdown
Collaborator

geckopy gives the same results as GECKO on the cases the comparison in CompMetEng/raven-gecko-parity#141 turned up, and works on the scipy (HiGHS) solver. Needs CompMetEng/raven-toolbox#185 (fseof(..., equality=True), the pFBA top level and the YAML readers); the minimum raven-toolbox version is raised once a release contains it.

Solver status.

  • flexibilize_enz_concs and sensitivity_tuning decide an infeasible start from the solver status, so Gurobi, GLPK and scipy behave alike. flexibilize_enz_concs warns and returns an empty result, as flexibilizeEnzConcs does. sensitivity_tuning still raises ValueError at the start and warns and stops inside the loop.

scipy. optlang's scipy interface keeps a dense matrix that it copies on every edit, renumbers columns wrongly after a variable removal, removes several constraints at once incorrectly, ignores model.tolerance and returns no duals. The new geckopy.solver_support module works around this:

  • A sparse problem class replaces the dense one. EcModel.solver repairs a stale index map when it is read. load_conventional_gem and load_ec_model build on GLPK and convert at the end, and get_subset_ec_model and apply_kcat_constraints (for 100 or more ec reactions) edit on GLPK and convert back.
  • Shadow prices come from HiGHS row marginals after a primal and dual optimality check. get_enzyme_bottlenecks, Enzyme.shadow_price and relax_proteomics_greedy use them. relax_proteomics_greedy takes one price vector per iteration and breaks ties by lowest ID.
  • model.tolerance reaches HiGHS, and a solve that ends with numerical difficulties is repeated at the default tolerance. An infeasible solve returns a solution with its status.
  • Light Human-GEM now builds in about 7 minutes on scipy (it took 2 h 17 min) and get_subset_ec_model finishes in about 5 minutes (it took 65 min). ecYeastGEM loads in 25 to 36 s. ec_fva on ecYeastGEM takes 52 to 81 minutes on scipy, against 9 minutes on Gurobi, and its bounds differ from Gurobi's by up to 0.15 percent because HiGHS is less accurate on these LPs.

Same results as GECKO.

  • get_subset_ec_model removes genes as removeGenes does, keeps the ec rows of a light ecModel (the 001_ prefix) and drops the metabolites and genes no reaction uses. It raised ValueError: <gene> not found on the light Human-GEM ecModel.
  • assign_standard_kcat compares subsystem names without regard to letter case, and a reaction without a subsystem gets the model-wide standard kcat.
  • load_uniprot_tsv and get_uniprot_ids_from_table read the cells like textscan with %q: quotes are removed and tabs inside quotes belong to the cell. A quoted EC cell such as "1.1.1.25; 2.5.1.19" kept its quotes and changed the BRENDA matches of 44 reactions in the Yarrowia build.
  • load_ec_model reads a file with an empty enzymes: !!omap and with unescaped quotes in a value, as loadEcModel does. This stays in geckopy until the minimum raven-toolbox version contains the same repair.
  • pfba_enzymes holds the objective at 0.999999 of its optimum, as getPfbaEnzymes does. Pass fraction_of_optimum=1.0 for the previous behaviour.
  • ec_fseof fixes the target flux at each level by equality, as ecFSEOF does. The targets table lists reaction targets before transport targets, each group in score order, and has a new boolean column transport. This changes the row order for callers that take the top N rows.

edkerk added 16 commits October 29, 2026 00:36
…uals from HiGHS, build large models sparsely

optlang's scipy interface renumbers variable columns wrongly after a removal and keeps a dense matrix that it copies on every edit. An EcModel now moves its scipy problem to a sparse class with correct renumbering whenever model.solver is read, Enzyme.shadow_price, get_enzyme_bottlenecks and relax_proteomics_greedy read HiGHS row marginals on scipy, and load_conventional_gem and make_ec_model build on glpk and convert to scipy at the end.
… keep the ec rows of a light model

A reaction that survives the removal of a gene of its rule lost the gene from model.genes but not from its rule, so removing it later raised that the gene was not found. The ec rows of a gecko-light model carry a 001_ prefix and were all dropped.
getSubsetEcModel's removeGenes and removeReactions calls drop every
metabolite and gene without a reaction. get_subset_ec_model left the
pseudo-gene standard and six unused metabolites in the HT29-GEM subset of the
light Human-GEM ecModel.
…lone

load_ec_model reads the file on glpk and converts the ecModel when scipy is
cobra's default solver, and setting EcModel.solver to scipy builds the sparse
problem of switch_to_scipy. Loading ecYeastGEM on scipy did not finish in 25
minutes before.
optlang restores a pickled or copied scipy model by adding every variable and
constraint to a dense problem, which took tens of minutes per ec_fva worker on
ecYeastGEM.
optlang's scipy interface ignores every tolerance, so a model set to 1e-9 was
solved at the HiGHS default of 1e-7.
…nstraints, and populate the sparse problem in one pass

optlang's scipy interface removes constraints through a loop that calls the generic
removal once per constraint with the whole list, so removing two or more constraints
raised LookupError; the sparse model removes them correctly. Removals, and the
coefficient rewrites of apply_kcat_constraints, run on glpk and the model is converted
back with switch_to_scipy, which now creates each constraint with its whole expression.
@edkerk
edkerk merged commit c07b5ce into develop Oct 30, 2026
5 of 10 checks passed
@edkerk
edkerk deleted the fix/parity-round-3 branch October 30, 2026 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant