Skip to content

VCell does not properly handle -0.0 in the IEEE standard within Expressions, creating far-reaching problems #1646

@CodeByDrescher

Description

@CodeByDrescher

Background

Important Facts

Throughout VCell's existence, the VCell team has made efforts to convert the IEEE double precision float. value of "-0.0" into "0.0".

After SBML support was introduced, a series of trigonometric functions were introduced; most relevant are: tan(x), cot(x), atan(x), acot(x), atan2(y,x).

Java as a language accepts that 1.0/0.0 != NaN, instead: 1.0/0.0 = infinity; likewise, -1.0/0.0 = -infinity. Other languages do not necessarily make the same conclusion.

Problem

While converting -0.0 to +0.0 seems to be completely innocuous, this is not the case when interacting with the trigonometric functions.

The example that alerted us to this problem is the following test:
Are the two expressions functionally equivalent?
(1) atan(1/(0.10831 * species_concentration * 0.0)); <the domain of species_concentration is (-∞, 0)>
(2) 1.5708 (π/2)

Historically the answer in VCell is "yes!", but outside of VCell, that isn't necessarily the case.

In computational numerics, acot(0.10831 * species_concentration * 0.0) for species_concentration < 0 is not π/2, but rather -π/2 (see bottom for calculation). Even when multiplied by zero, the sign is preserved as "-0.0", and it directly affects the computation of acot among other trig functions.

The net result is that there when someone exports a model from VCell to another tool, the results could be incorrect. In continuous models, this could only be at a very specific point in time, but in more logically controlled models, this could have a much larger impact.

But as a very important feature, VCell has used boolean logic to guard expressions for 25-30 years. Flatting models directly depends on anything multiplied with 0.0 flattened to +0.0.

The solution to this problem is not an easy pick as well. Here are the different scenarios and implications.

Solution 1: Preserve VCell's status quo that -0.0 must always be treated as 0.0.

Pros:

  • Backward compatibility is kept 100% intact.
  • No results should have any changes.
  • A majority of models need no action.
    Cons:
  • VCell models present and future may have mathematically incorrect results if they use any of the affected trigonometric equations. A warning should be announced, and then put into VCell's documentation. VCell published models should be checked if they contain the trigonometries vulnerable to the problem, and if any models produce numerically incorrect results, inform the authors and/or publications.
  • We can not guarantee any model that contains the trigonometries will produce the same results when given to other tools.

Solution 2: Preserve VCell's status quo , but Isolate VCell's use of the affected trigonometries.

Pros:

  • VCell's internal expression flattening is left unaffected.
  • No models require action
    Cons:
  • VCell must block export to other formats if the model contains the affected trigonometries, or otherwise encode VCell specific behavior; the algorithms will be complicated. This also applies to PyVCell.
  • Imported models in VCell will not necessarily be able to be supported / reproducable, if their models contain the affected trigonometries.

Solution 3a Change VCell's status quo; make functional equivalence testing more lenient through flattening

By permitting functional equivalence to be determined by flattened equations rather than original equations, we can still declare the equations functionally equivalent even to the new status quo
Pros:

  • Results are always computationally sound.
  • Problem with trigonometries is solved.
  • If any models contained previously incorrect results, new results would fix that.
  • Expression flattening left unchanged
    Cons:
  • Using boolean guards with multiplication would have to be syntactically different, and thus break backwards compatibility.
  • Round trip validation would become less strict; greater chance round tripping could quietly fail and make it through to production.

Solution 3b Change VCell's status quo; modify expression flattening

Pros:

  • Results are always computationally sound.
  • Problem with trigonometries is solved.
  • If any models contained previously incorrect results, new results would fix that.
    Cons:
  • Backwards compatibility is severed for all affected models:
  • backwards compatibility for VCell expression flattening is changed.

  • Using boolean guards with multiplication would have to be syntactically different.

How acot(0.10831 * species_concentration * 0.0) could equal -π/2

First, understand that 3 different calculations are made:
eq_1 = 0.10831 * species_concentration * 0.0
eq_2 = 1.0/eq_1
eq_3 = atan(eq_2)

I will compare VCell with "general computing" (GC) for the math below:

EQ 1

VCell automatically detects that 0.0 is in the first calculation, and sets the results to 0.0.
But if actually multiplied out, the signs suggest the number should be negative. So computationally the answer should be -0.0.

So while VCell says: 0.0, GC says: -0.0.

EQ 2

Java says that 1.0/0.0 is infinity, so VCell says .

But since we have -0.0 from GC, and a positive numerator over a negative denominator is a negative number, java also says 1.0/-0.0 = -∞

EQ 3

taking atan of an infinity effectively means "what's the value of x that makes tan(x) go to the desired infinity?"
Well it's π/2 for ... and -π/2 for -∞ (and the multiples of each there-of)
So...we get different answers depending on whether it's VCell or standard IEEE double-precision computation!

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

Status

Active

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions