COPASI API  4.16.103
CSBMLunitInterface.h
Go to the documentation of this file.
1 // Copyright (C) 2013 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 // Copyright (C) 2008 - 2009 by Sven Sahle and University of Heidelberg
7 // All rights reserved.
8 
9 #ifndef CSBMLUNITINTERFACE
10 #define CSBMLUNITINTERFACE
11 
12 #include <vector>
13 #include <map>
14 #include <set>
15 #include "CSBMLunit.h"
16 
17 class Model;
18 class ASTNode;
19 
20 /**
21  * This class contains a copy of the unit information of an sbml model in the
22  * data structures the unit conversion algorithm can deal with.
23  * It contains lists of all objects/numbers that potentially can have units, and
24  * a list of all mathematical expressions in the sbml model that impose constraints
25  * on the units.
26  */
28 {
29 private:
30  // disable the assignment operator and the copy constructor
31  // because right now I am too lazy to implement it. R.G.
33 
35 
36 public:
37 
38  /**
39  * initialize the unit interface from an sbml model, extracting all
40  * the unit information from the model
41  */
42  CSBMLunitInterface(Model * model, bool unitsFromModel);
43 
44  /**
45  * Destructor.
46  */
48 
49  /**
50  * initialize the unit interface from an sbml model, without using
51  * any unit information from the model
52  */
53  //CSBMLunitInterface(Model * model, std::vector<CSBMLunit> setOfUnits);
54 
55  //void initializeSetOfUnits(std::vector<CSBMLunit> setOfUnits);
56 
57  void debugOutput() const;
58  void calculateStatistics();
59 
60  /**
61  * retrieve the SBML model
62  */
63  Model * getModel() {return mpModel;};
64  const Model * getModel() const {return mpModel;};
65 
67 
68  /**
69  * Tries to determine unknown units by considering the known units
70  * and all the contrains imposed by the mathmatical expressions.
71  */
72  void determineUnits();
73 
74  /**
75  * Writes the units information back to an sbml model (without any unit conversions).
76  * The most common use case for this will be to annotate the model with units of
77  * objects that did not have explicit units before, e.g. parameters.
78  */
79  void writeBackToModel();
80 
81  class Statistics
82  {
83  public:
84  std::vector<unsigned int> global, local, numbers, all;
85  };
86 
87  /**
88  * get statistics of the units of the model.
89  * In each of the vectors:
90  * 0: unknown
91  * 1: default
92  * 2: model wide provided units
93  * 3: provided units
94  * 4: derived units
95  * 5: conflict
96  */
97  const Statistics & getStatistics() const {return mStatistics;};
98 
99  static void outputStatistics(const Statistics & stat, bool flag);
100 
101  /**
102  * returns a list of sbml id corresponding to all global sbml objects that match
103  * the given unit status (as explained above)
104  */
105  std::vector<std::string> getListOfObjectsWithGivenUnitStatus(int status) const;
106 
107  /**
108  * returns a list of pairs of sbml IDs corresponding to all local parameters that match
109  * the given unit status (as explained above)
110  */
111  std::vector<std::pair<std::string, std::string> > getListOfLocalParametersWithGivenUnitStatus(int status) const;
112 
113  /**
114  * generates a message containing a list of the objects with unknown units.
115  * The message should be suitable for presentation in a user interface.
116  */
117  std::string getMessageAboutUnknownUnits() const;
118 
119  /**
120  * after determineUnits() was called this contains a set of terminal ASTNodes
121  * in which a conflict was detected.
122  * Note that is not necessarily where one would intuitively locate the conflict,
123  * i's just where it was detected.
124  */
125  const std::set<const ASTNode *> & getListOfConflictingNodes() const;
126 
127  /**
128  * This class contains the information about one mathematical expression
129  * from an sbml model and how it relates to units constraints.
130  */
132  {
133  public:
134  /// root node of an expression in the sbml model
135  const ASTNode* mpExpression;
136 
137  /// specifies whether the units of the result of the expression are some unit divided by time
138  bool mPerTime;
139 
140  /// if this is not "" then the root of the expression should have the units of the referenced object
141  std::string mRootObject;
142 
143  /// if mRootObject is "" then this member specifies the units of the root of the expression
145 
146  /// id of a reaction. If this is set the local parameters of the reaction are in scope for the expression
147  std::string mReactionId;
148 
149  /// error code after run
151 
152  /// this indicates the origin of the expression for display purposes, e.g. "kinetic law"
153  std::string mTypeDescription;
154 
155  /// display name of the object that either contains the expression or the the expression applies to.
156  std::string mObjectDisplayString;
157 
158  /// Default constructor
159  CExpressionInformation(unsigned int sbmlLevel, unsigned int sbmlVersion)
160  : mpExpression(NULL), mPerTime(false), mRootObject(), mRootUnit(CSBMLunitInformation(sbmlLevel, sbmlVersion)), mReactionId(), mErrorCode(0)
161  {};
162  };
163 
164  /**
165  * return the list of all mathematical expressions including additional information
166  */
167  const std::vector<CExpressionInformation> & getExpressions() const {return mSBMLExpressions;};
168 
169  /**
170  * describes the local environment for the recursive unit analysis.
171  * It can either be empty, in this case only the global objects are accessible.
172  * If a reaction is provided the local parameters of this reaction are accessible.
173  * If a stack of function variables is provided, the top level of this stack describes
174  * the accessible variables in the frame. Local parameters and function variables
175  * are never simultaneously accessible.
176  */
178  {
179  public:
181  CEnvironmentInformation(const std::string & ri): mReactionID(ri) {};
182 
183  ///tells if the current scope involves a reaction (local parameters)
184  bool isReactionScope() const
185  {return mReactionID != "" && mFrameStack.size() == 0;}
186 
187  ///drop the top level of the function variables frame stack
188  void drop()
189  {if (mFrameStack.size() > 0) mFrameStack.pop_back() ;};
190 
191  ///push a mapping for function variables onto the frame stack
192  void push(std::map<std::string, ASTNode*> & frame)
193  {mFrameStack.push_back(frame);};
194 
195  std::string mReactionID;
196  std::vector<std::map<std::string, ASTNode*> > mFrameStack;
197  };
198 
199  /**
200  * provided with an identifier from an object node, this method tries to find the
201  * mapped unit information. According to the provided environment, this could be
202  * a local parameter or a global object.
203  */
204  CSBMLunitInformation* getMappedUnitFromIdentifier(const std::string & node,
205  const CEnvironmentInformation & ei);
206  /**
207  * find the unit information corresponding to a number node
208  */
210 
211 private:
212 
213  /**
214  * initialize from sbml model. If unitsFromModel is true the unit information
215  * is extracted from the model. Otherwise the units are constructed from a
216  * set of base units that was provided by initializeSetOfUnits(). .
217  */
218  void initializeFromSBMLModel(bool unitsFromModel);
219 
220  ///initializes the base units with the defaults (moles, seconds, l, m, m^2)
221  void initializeDefaultUnits();
222 
223  ///the sbml model from which this interface was initialized
224  Model * mpModel;
225 
226  unsigned int mSBMLLevel;
227 
228  unsigned int mSBMLVersion;
229 
230  /**
231  * This maps the id of any sbml object that can be referenced by one id to a copy
232  * of its units information.
233  */
234  std::map<std::string, CSBMLunitInformation> mSBMLObjectsMap;
235 
236  /**
237  * This maps the id of a reaction and the id of a local parameter to a copy
238  * of its units information. (Local parameters are the only objects in sbml that
239  * need two ids for their identification)
240  */
241  std::map<std::string, std::map<std::string, CSBMLunitInformation> > mSBMLLocalParametersMap;
242 
243  /**
244  * This maps number nodes to units information
245  */
246  std::map<const ASTNode*, CSBMLunitInformation> mSBMLNumbersMap;
247 
248  /**
249  * a list of all mathematical expressions in the sbml model along with the
250  * units information for their root node.
251  */
252  std::vector<CExpressionInformation> mSBMLExpressions;
253 
254  /**
255  * indicated whether a number 1.0 and -1.0 is considered to be dimensionless
256  */
258 
259  /// try to find out as much as possible about the units from one expression
261 
262  CSBMLunitInformation recursion(const ASTNode* node, const CSBMLunitInformation & ui,
263  const CEnvironmentInformation & ei);
264 
265  /**
266  * This handles the units assignment/comparison/query for terminal node of the tree.
267  * ui is the unit information that is passed from above, pNodeUnit is the unit information
268  * that is already present in the terminal node, and the return value is the units of the node
269  * after the assignment/comparison/querying. mError is set to 1 if a conflict appears.
270  * The node is optional (it can be NULL), it is only used for reporting conflicts.
271  * If a new conflict appears the node pointer is added to the mConflictingNodes set.
272  */
273  CSBMLunitInformation handleTerminalNode(const CSBMLunitInformation & ui, CSBMLunitInformation *pNodeUnit, const ASTNode* node);
274 
275  /**
276  * handle the case of a node where the units are supposed to be equal.
277  * This includes plus, minus, choice, comparison operators
278  */
279  CSBMLunitInformation recursionEqual(const ASTNode* node, const CSBMLunitInformation & ui,
280  const CEnvironmentInformation & ei);
281 
282  /**
283  * handle a multiplication node. If one unit is unknown it can be calculated.
284  * If no unit is unknown a consistency check can be made. If more than one unit
285  * is unknown, nothing can be done.
286  */
287  CSBMLunitInformation recursionTimes(const ASTNode* node, const CSBMLunitInformation & ui,
288  const CEnvironmentInformation & ei);
289 
290  /**
291  * handle a division node. If one unit is unknown it can be calculated.
292  * If no unit is unknown a consistency check can be made. If more than one unit
293  * is unknown, nothing can be done.
294  */
295  CSBMLunitInformation recursionDivide(const ASTNode* node, const CSBMLunitInformation & ui,
296  const CEnvironmentInformation & ei);
297 
298  CSBMLunitInformation recursionPower(const ASTNode* node, const CSBMLunitInformation & ui,
299  const CEnvironmentInformation & ei);
300 
301  /**
302  * handle the case of a pieewise node
303  */
304  CSBMLunitInformation recursionPiecewise(const ASTNode* node, const CSBMLunitInformation & ui,
305  const CEnvironmentInformation & ei);
306 
308  {
309  public:
310  double result;
311  bool known;
312  };
313 
314  EvaluationResult evaluate(const ASTNode* node);
315 
316  /**
317  * provided with an identifier from an object node, this method checks if it
318  * corresponds to a function variable from the current environment.
319  * If it does, the ASTNode* is returned, else NULL.
320  */
321  ASTNode* resolveVariableName(const std::string & node,
322  const CEnvironmentInformation & ei);
323 
324  /**
325  * provided with an identifier from an object node, this method checks if it
326  * corresponds to a function definition in the current model.
327  * If it does, the FunctionDefinition* is returned, else NULL.
328  */
329  FunctionDefinition* resolveFunctionName(const std::string & node);
330 
331  //**** wrapper functions for node class *************************
332 
333  static bool isObject(const ASTNode* node);
334 
335  static bool isOperator(const ASTNode* node);
336 
337  ///determines if the node represents a number (integer, real, or rational)
338  static bool isNumber(const ASTNode* node);
339 
340  ///determines if the node contains a call to a function definition
341  static bool isFunctionCall(const ASTNode* node);
342 
343  ///determines if the node contains a call to a built in function
344  static bool isBuiltInFunctionCall(const ASTNode* node);
345 
346  ///return the value of a number node
347  static double getValueFromNumberNode(const ASTNode* node);
348 
349  static std::string getIdentifier(const ASTNode* node);
350 
351  //***********************************************
352 
358 
360 
361  int mError;
362 
363  ///contains the (terminal) nodes where a conflict appeared
364  std::set<const ASTNode *> mConflictingNodes;
365 
367 };
368 
369 #endif
static std::string getIdentifier(const ASTNode *node)
EvaluationResult evaluate(const ASTNode *node)
std::vector< unsigned int > local
void setAssumeDimensionlessOne(bool f)
const Statistics & getStatistics() const
const std::vector< CExpressionInformation > & getExpressions() const
std::string mRootObject
if this is not "" then the root of the expression should have the units of the referenced object ...
void handleOneExpression(CExpressionInformation &ei)
try to find out as much as possible about the units from one expression
CSBMLunitInformation * mpSBMLAreaUnit
CSBMLunitInformation * mpSBMLConflictUnit
CSBMLunitInformation recursionPiecewise(const ASTNode *node, const CSBMLunitInformation &ui, const CEnvironmentInformation &ei)
std::vector< CExpressionInformation > mSBMLExpressions
CSBMLunitInformation recursionTimes(const ASTNode *node, const CSBMLunitInformation &ui, const CEnvironmentInformation &ei)
Model * mpModel
the sbml model from which this interface was initialized
std::vector< unsigned int > global
std::string mObjectDisplayString
display name of the object that either contains the expression or the the expression applies to...
FunctionDefinition * resolveFunctionName(const std::string &node)
static bool isNumber(const ASTNode *node)
determines if the node represents a number (integer, real, or rational)
CSBMLunitInterface(const CSBMLunitInterface &src)
CSBMLunitInformation * mpSBMLLengthUnit
CSBMLunitInformation recursion(const ASTNode *node, const CSBMLunitInformation &ui, const CEnvironmentInformation &ei)
std::vector< std::map< std::string, ASTNode * > > mFrameStack
CSBMLunitInformation * getMappedUnitFromIdentifier(const std::string &node, const CEnvironmentInformation &ei)
bool isReactionScope() const
tells if the current scope involves a reaction (local parameters)
std::map< std::string, CSBMLunitInformation > mSBMLObjectsMap
std::vector< std::string > getListOfObjectsWithGivenUnitStatus(int status) const
CExpressionInformation(unsigned int sbmlLevel, unsigned int sbmlVersion)
Default constructor.
bool mPerTime
specifies whether the units of the result of the expression are some unit divided by time ...
CSBMLunitInformation handleTerminalNode(const CSBMLunitInformation &ui, CSBMLunitInformation *pNodeUnit, const ASTNode *node)
std::string mTypeDescription
this indicates the origin of the expression for display purposes, e.g. "kinetic law" ...
ASTNode * resolveVariableName(const std::string &node, const CEnvironmentInformation &ei)
CSBMLunitInformation mRootUnit
if mRootObject is "" then this member specifies the units of the root of the expression ...
CSBMLunitInformation * getMappedUnitFromNumberNode(const ASTNode *node)
void push(std::map< std::string, ASTNode * > &frame)
push a mapping for function variables onto the frame stack
CSBMLunitInformation * mpSBMLAmountUnit
void initializeDefaultUnits()
initializes the base units with the defaults (moles, seconds, l, m, m^2)
static bool isOperator(const ASTNode *node)
void initializeFromSBMLModel(bool unitsFromModel)
const ASTNode * mpExpression
root node of an expression in the sbml model
long int flag
Definition: f2c.h:52
CSBMLunitInformation * mpSBMLVolumeUnit
CSBMLunitInterface & operator=(const CSBMLunitInterface &src)
std::vector< unsigned int > numbers
std::string mReactionId
id of a reaction. If this is set the local parameters of the reaction are in scope for the expression...
std::map< std::string, std::map< std::string, CSBMLunitInformation > > mSBMLLocalParametersMap
static void outputStatistics(const Statistics &stat, bool flag)
static bool isObject(const ASTNode *node)
static bool isFunctionCall(const ASTNode *node)
determines if the node contains a call to a function definition
std::map< const ASTNode *, CSBMLunitInformation > mSBMLNumbersMap
std::vector< unsigned int > all
static double getValueFromNumberNode(const ASTNode *node)
return the value of a number node
static bool isBuiltInFunctionCall(const ASTNode *node)
determines if the node contains a call to a built in function
CSBMLunitInformation recursionDivide(const ASTNode *node, const CSBMLunitInformation &ui, const CEnvironmentInformation &ei)
void drop()
drop the top level of the function variables frame stack
std::set< const ASTNode * > mConflictingNodes
contains the (terminal) nodes where a conflict appeared
CSBMLunitInformation * mpSBMLTimeUnit
CSBMLunitInformation recursionPower(const ASTNode *node, const CSBMLunitInformation &ui, const CEnvironmentInformation &ei)
const std::set< const ASTNode * > & getListOfConflictingNodes() const
std::string getMessageAboutUnknownUnits() const
std::vector< std::pair< std::string, std::string > > getListOfLocalParametersWithGivenUnitStatus(int status) const
CSBMLunitInformation recursionEqual(const ASTNode *node, const CSBMLunitInformation &ui, const CEnvironmentInformation &ei)
const Model * getModel() const