simgi 0.2 → 0.3
raw patch · 71 files changed
+2675/−1578 lines, 71 filesdep ~base
Dependency ranges changed: base
Files
- AUTHORS +2/−0
- ChangeLog +22/−0
- INSTALL +7/−5
- Makefile +6/−4
- Models/brusselator.sgl +6/−6
- Models/irreversible_bimol.sgl +21/−0
- Models/irreversible_trimol.sgl +38/−0
- Models/oregonator.sgl +6/−6
- Models/reversible_bimol.sgl +29/−0
- Models/reversible_trimol.sgl +39/−0
- Models/volterra.sgl +6/−6
- README +3/−2
- doc/Makefile +6/−26
- doc/simgi.html +687/−600
- doc/simgi.mdml +425/−0
- doc/simgi.pdf binary
- doc/simgi.rst +0/−324
- simgi.cabal +3/−3
- src/CommandLine.hs +3/−1
- src/Engine.hs +28/−33
- src/ExtraFunctions.hs +38/−3
- src/GenericModel.hs +27/−9
- src/IO.hs +76/−0
- src/InputCheck.hs +83/−14
- src/InputParser.hs +168/−97
- src/Messages.hs +7/−4
- src/PrettyPrint.hs +4/−1
- src/RpnCalc.hs +39/−6
- src/RpnData.hs +4/−4
- src/RpnParser.hs +1/−1
- src/TokenParser.hs +10/−4
- src/simgi.hs +4/−8
- test/Makefile +19/−9
- test/check_event_parser/EventParserTest.hs +25/−22
- test/check_event_parser/Makefile +2/−2
- test/check_irreversible/Makefile +0/−19
- test/check_irreversible/irreversible.1.sgl +0/−22
- test/check_irreversible/irreversible.2.sgl +0/−22
- test/check_irreversible/run_test.1.sh +0/−60
- test/check_irreversible/run_test.2.sh +0/−60
- test/check_irreversible_bimol/Makefile +17/−0
- test/check_irreversible_bimol/irreversible_bimol.1.sgl +21/−0
- test/check_irreversible_bimol/irreversible_bimol.2.sgl +21/−0
- test/check_irreversible_bimol/run_test.1.sh +63/−0
- test/check_irreversible_bimol/run_test.2.sh +63/−0
- test/check_irreversible_trimol/Makefile +17/−0
- test/check_irreversible_trimol/irreversible_trimol.1.sgl +38/−0
- test/check_irreversible_trimol/irreversible_trimol.2.sgl +38/−0
- test/check_irreversible_trimol/run_test.1.sh +67/−0
- test/check_irreversible_trimol/run_test.2.sh +67/−0
- test/check_reaction_parser/Makefile +2/−2
- test/check_reaction_parser/ReactionParserTest.hs +7/−3
- test/check_reversible/Makefile +0/−19
- test/check_reversible/average.hs +0/−38
- test/check_reversible/check_deviation.hs +0/−46
- test/check_reversible/reversible.sgl +0/−29
- test/check_reversible/run_test.sh +0/−53
- test/check_reversible_bimol/Makefile +16/−0
- test/check_reversible_bimol/reversible_bimol.sgl +29/−0
- test/check_reversible_bimol/run_test.sh +53/−0
- test/check_reversible_trimol/Makefile +19/−0
- test/check_reversible_trimol/reversible_trimol.1.sgl +39/−0
- test/check_reversible_trimol/reversible_trimol.2.sgl +39/−0
- test/check_reversible_trimol/run_test.1.sh +53/−0
- test/check_reversible_trimol/run_test.2.sh +53/−0
- test/check_rpnstack/Makefile +2/−2
- test/check_rpnstack/RpnStackTest.hs +5/−2
- test/test_helpers/Makefile +16/−0
- test/test_helpers/TestHelpers.hs +2/−1
- test/test_helpers/average.hs +38/−0
- test/test_helpers/check_deviation.hs +46/−0
AUTHORS view
@@ -1,1 +1,3 @@ Markus Dittrich <haskelladdict@users.sourceforge.net>+National Resource for Biomedical Supercomputing &+Carnegie Mellon University
ChangeLog view
@@ -1,3 +1,25 @@+2010-02-10 Markus Dittrich <haskelladdict@users.sourceforge.net>++ * 0.3 released+ * many bugfixes (an important one relates to 3 way and+ higher order reactions which we computed incorrectly+ in version 0.2).+ * another significant overhaul of SGL language specs which+ are now much more streamlined. Main changes++ - dropped "def" keyword from input block to simplify parser+ - all SGL identifier that expect a Double/Integer literal+ now accept either parse-time or run-time statement blocks.+ - the event definition block syntax is now much more+ consistent with the rest of the SGL+ - the "outputFile" keyword has been moved to the output+ block+ + * simgi will now try to evaluate statement blocks while+ parsing in order to minimize the run-time overhead.+ * added many more tests to the test suite.++ 2009-12-01 Markus Dittrich <haskelladdict@users.sourceforge.net> * 0.2 released.
INSTALL view
@@ -2,13 +2,15 @@ ----------- Compilaton of simgi requires -- >=ghc-6.10-- >=gmp-4.3+* >=ghc-6.10 (http://haskell.org/ghc/)+* >=gmp-4.3 (http://gmplib.org/)+* >=mersenne-random-pure64 (http://hackage.haskell.org/package/mersenne-random-pure64)+* bc (http://www.gnu.org/software/bc/bc.html) (for the test suite only) -To compile the documentation (not required), you will also need+The optional document generation requires -- >=docutils-0.5 -- latex, e.g., tetex or texlive+* >=pandoc-1.4 (http://johnmacfarlane.net/pandoc)+* latex (e.g. texlive) Building of simgi can be done either via
Makefile view
@@ -1,23 +1,24 @@ # Copyright 2009 Markus Dittrich <haskelladdict@users.sourceforge.net> # Distributed under the terms of the GNU General Public License v3 -VERSION=0.2+VERSION=0.3 DESTDIR= prefix=/usr mandir=$(DESTDIR)$(prefix)/share/man/man1 docdir=$(DESTDIR)$(prefix)/share/doc/simgi-$(VERSION)+exampledir=$(DESTDIR)$(prefix)/share/simgi/examples htmldir=$(docdir)/html bindir=$(DESTDIR)$(prefix)/bin GHC_FLAGS_DEVEL = -O -Wall -fwarn-simple-patterns -fwarn-tabs -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction -fwarn-implicit-prelude -fno-warn-orphans-GHC_FLAGS_RELEASE = -O2+GHC_FLAGS_RELEASE = -O2 OBJECTS = src/simgi.hs src/CommandLine.hs src/Engine.hs \ src/GenericModel.hs src/InputCheck.hs src/InputParser.hs \ src/PrettyPrint.hs src/RpnParser.hs src/RpnCalc.hs \ src/RpnData.hs src/TokenParser.hs -all: simgi +all: simgi simgi: $(OBJECTS) ghc -i./Models -i./src $(GHC_FLAGS_RELEASE) --make src/simgi.hs@@ -37,10 +38,12 @@ install -d $(docdir) install -d $(bindir) install -d $(htmldir)+ install -d $(exampledir) install -m 0755 src/simgi $(bindir)/ install -m 0644 ChangeLog COPYING AUTHORS $(docdir)/ install -m 0644 doc/*.pdf $(docdir)/ install -m 0644 doc/*.html $(htmldir)/+ install -m 0644 Models/*.sgl $(exampledir)/ .PHONY: clean doc@@ -51,4 +54,3 @@ clean: rm -f src/*.o src/*.hi src/simgi make -C test clean - make -C doc clean
Models/brusselator.sgl view
@@ -5,26 +5,26 @@ ------------------------------------------------------} -def parameters+parameters time = 50.0 outputBuffer = 50000 outputFreq = 200 systemVol = nil -- interpret rates as propensities- outputFile = "brusselator_output.dat" end -def molecules+molecules x = 1000 y = 2000 end -def reactions+reactions nil -> x | 5000 | x -> y | 50.0 | 2x + y -> 3x | 0.00005 | x -> nil | 5.0 | end -def output- [x,y]+output+ outputFile = "brusselator_output.dat"+ [TIME,x,y] end
+ Models/irreversible_bimol.sgl view
@@ -0,0 +1,21 @@+parameters+ time = 1.0+ systemVol = 1.25e-19 + outputBuffer = 50000 + outputFreq = 100+end++molecules+ a = 1000+ b = 1000+ c = 0+end++reactions+ a + b -> c | 1e6 |+end ++output+ outputFile = "irreversible_bimol.1.dat"+ [TIME, ITERATION, a, b, c]+end
+ Models/irreversible_trimol.sgl view
@@ -0,0 +1,38 @@+{-----------------------------------------------------++ this is the input deck for a simple 3 way reaction+ (C) 2010 Markus Dittrich++------------------------------------------------------}++variables+ Na = 6.022e23+ myConc = 50e-6+ cubeVol_um = 0.05+ cubeVol = { cubeVol_um * 1e-15 }+ myMol = { myConc * cubeVol } + myRelease = { myMol * Na }+end++parameters+ time = 100000.0+ outputBuffer = 1 + outputFreq = 1+ systemVol = { cubeVol }+end++molecules+ A = { myRelease }+ B = { myRelease }+ C = { myRelease }+ D = 0+end++reactions+ A + B + C -> D | 1e11 |+end++output+ outputFile = "irreversible_trimol.1.dat"+ [A,B,C,D]+end
Models/oregonator.sgl view
@@ -5,21 +5,20 @@ ------------------------------------------------------} -def parameters+parameters time = 50.0 outputBuffer = 50000 outputFreq = 500 systemVol = nil -- interpret rates as propensities- outputFile = "oregonator_output.dat" end -def molecules+molecules x = 500 y = 1000 z = 2000 end -def reactions+reactions y -> x | 2.0 | x + y -> nil | 0.1 | x -> 2x + z | 104.0 |@@ -27,6 +26,7 @@ z -> y | 26.0 | end -def output- [x,y,z]+output+ outputFile = "oregonator_output.dat"+ [TIME,x,y,z] end
+ Models/reversible_bimol.sgl view
@@ -0,0 +1,29 @@+{-----------------------------------------------------++ this is the input deck for the oregonator model + (C) 2009 Markus Dittrich++------------------------------------------------------}++parameters+ time = 1.0e-4+ systemVol = 1.25e-19+ outputBuffer = 50000+ outputFreq = 10+end++molecules+ a = 1000+ b = 1000+ c = 0+end++reactions+ a + b -> c | {1e6*10} |+ c -> a + b | 1e5 |+end++output+ [ITERATION, TIME, a, b, c]+ outputFile = "reversible_bimol.dat"+end
+ Models/reversible_trimol.sgl view
@@ -0,0 +1,39 @@+{-----------------------------------------------------++ this is the input deck for a simple 3 way reaction+ (C) 2010 Markus Dittrich++------------------------------------------------------}++variables+ Na = 6.022e23+ myConc = 50e-6+ cubeVol_um = 0.05+ cubeVol = { cubeVol_um * 1e-15 }+ myMol = { myConc * cubeVol } + myRelease = { myMol * Na }+end++parameters+ time = 0.004+ outputBuffer = 50+ outputFreq = 1+ systemVol = { cubeVol }+end++molecules+ A = { myRelease }+ B = { myRelease }+ C = { myRelease }+ D = 0+end++reactions+ A + B + C -> D | 1e12|+ D -> A + B + C | 1e3 |+end++output+ outputFile = "reversible_trimol.1.dat"+ [{D/cubeVol/Na}]+end
Models/volterra.sgl view
@@ -5,25 +5,25 @@ ------------------------------------------------------} -def parameters+parameters time = 50.0 outputBuffer = 50000 outputFreq = 200 systemVol = nil -- interpret rates as propensities- outputFile = "volterra_output.dat" end -def molecules+molecules x = 1000 y = 2000 end -def reactions+reactions x -> 2x | 10.0 | x + y -> 2y | 0.01 | y -> nil | 10.0 | end -def output- [x,y]+output+ outputFile = "volterra_output.dat"+ [TIME,x,y] end
README view
@@ -1,11 +1,12 @@ DESCRIPTION: ------------ - simgi is a stochastic simulator using the Gillespie algorithm [1,2]. simgi is released under the GPL v3. -(C) 2009 Markus Dittrich+(C) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University See doc/simgi.html for more information.
doc/Makefile view
@@ -1,32 +1,12 @@ -RST_FILES = simgi.rst--default: doc---doc: clean_old build_html build_pdf---build_html: $(RST_FILES)- rst2html.py $< > $(<:.rst=.html)--build_pdf: $(RST_FILES)- rst2latex.py $< > $(<:.rst=.tex)+MARKDOWN_FILES = simgi.mdml - # fix indentation- sed -i "17 s:^\(.*\):\\\setlength{\\\parindent}{0in}\n\1:" \- $(<:.rst=.tex)- pdflatex $(<:.rst=.tex)- rm -f *.aux *.log *.out *.tex+doc: build_html build_pdf -clean_old:- rm -f *.html *.pdf -+build_html: $(MARKDOWN_FILES)+ pandoc -s $< > $(<:.mdml=.html) -.PHONY: clean+build_pdf: $(MARKDOWN_FILES)+ markdown2pdf $< -clean:- rm -f *.aux *.log *.html *.pdf *.tex *.out- -
doc/simgi.html view
@@ -1,600 +1,687 @@-<?xml version="1.0" encoding="utf-8" ?>-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">-<head>-<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />-<meta name="generator" content="Docutils 0.6: http://docutils.sourceforge.net/" />-<title>simgi - A Stochastic Gillespie Simulator for Molecular Systems</title>-<meta name="author" content="Markus Dittrich" />-<style type="text/css">--/*-:Author: David Goodger (goodger@python.org)-:Id: $Id: html4css1.css 5951 2009-05-18 18:03:10Z milde $-:Copyright: This stylesheet has been placed in the public domain.--Default cascading style sheet for the HTML output of Docutils.--See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to-customize this style sheet.-*/--/* used to remove borders from tables and images */-.borderless, table.borderless td, table.borderless th {- border: 0 }--table.borderless td, table.borderless th {- /* Override padding for "table.docutils td" with "! important".- The right padding separates the table cells. */- padding: 0 0.5em 0 0 ! important }--.first {- /* Override more specific margin styles with "! important". */- margin-top: 0 ! important }--.last, .with-subtitle {- margin-bottom: 0 ! important }--.hidden {- display: none }--a.toc-backref {- text-decoration: none ;- color: black }--blockquote.epigraph {- margin: 2em 5em ; }--dl.docutils dd {- margin-bottom: 0.5em }--/* Uncomment (and remove this text!) to get bold-faced definition list terms-dl.docutils dt {- font-weight: bold }-*/--div.abstract {- margin: 2em 5em }--div.abstract p.topic-title {- font-weight: bold ;- text-align: center }--div.admonition, div.attention, div.caution, div.danger, div.error,-div.hint, div.important, div.note, div.tip, div.warning {- margin: 2em ;- border: medium outset ;- padding: 1em }--div.admonition p.admonition-title, div.hint p.admonition-title,-div.important p.admonition-title, div.note p.admonition-title,-div.tip p.admonition-title {- font-weight: bold ;- font-family: sans-serif }--div.attention p.admonition-title, div.caution p.admonition-title,-div.danger p.admonition-title, div.error p.admonition-title,-div.warning p.admonition-title {- color: red ;- font-weight: bold ;- font-family: sans-serif }--/* Uncomment (and remove this text!) to get reduced vertical space in- compound paragraphs.-div.compound .compound-first, div.compound .compound-middle {- margin-bottom: 0.5em }--div.compound .compound-last, div.compound .compound-middle {- margin-top: 0.5em }-*/--div.dedication {- margin: 2em 5em ;- text-align: center ;- font-style: italic }--div.dedication p.topic-title {- font-weight: bold ;- font-style: normal }--div.figure {- margin-left: 2em ;- margin-right: 2em }--div.footer, div.header {- clear: both;- font-size: smaller }--div.line-block {- display: block ;- margin-top: 1em ;- margin-bottom: 1em }--div.line-block div.line-block {- margin-top: 0 ;- margin-bottom: 0 ;- margin-left: 1.5em }--div.sidebar {- margin: 0 0 0.5em 1em ;- border: medium outset ;- padding: 1em ;- background-color: #ffffee ;- width: 40% ;- float: right ;- clear: right }--div.sidebar p.rubric {- font-family: sans-serif ;- font-size: medium }--div.system-messages {- margin: 5em }--div.system-messages h1 {- color: red }--div.system-message {- border: medium outset ;- padding: 1em }--div.system-message p.system-message-title {- color: red ;- font-weight: bold }--div.topic {- margin: 2em }--h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,-h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {- margin-top: 0.4em }--h1.title {- text-align: center }--h2.subtitle {- text-align: center }--hr.docutils {- width: 75% }--img.align-left, .figure.align-left{- clear: left ;- float: left ;- margin-right: 1em }--img.align-right, .figure.align-right {- clear: right ;- float: right ;- margin-left: 1em }--.align-left {- text-align: left }--.align-center {- clear: both ;- text-align: center }--.align-right {- text-align: right }--/* reset inner alignment in figures */-div.align-right {- text-align: left }--/* div.align-center * { */-/* text-align: left } */--ol.simple, ul.simple {- margin-bottom: 1em }--ol.arabic {- list-style: decimal }--ol.loweralpha {- list-style: lower-alpha }--ol.upperalpha {- list-style: upper-alpha }--ol.lowerroman {- list-style: lower-roman }--ol.upperroman {- list-style: upper-roman }--p.attribution {- text-align: right ;- margin-left: 50% }--p.caption {- font-style: italic }--p.credits {- font-style: italic ;- font-size: smaller }--p.label {- white-space: nowrap }--p.rubric {- font-weight: bold ;- font-size: larger ;- color: maroon ;- text-align: center }--p.sidebar-title {- font-family: sans-serif ;- font-weight: bold ;- font-size: larger }--p.sidebar-subtitle {- font-family: sans-serif ;- font-weight: bold }--p.topic-title {- font-weight: bold }--pre.address {- margin-bottom: 0 ;- margin-top: 0 ;- font: inherit }--pre.literal-block, pre.doctest-block {- margin-left: 2em ;- margin-right: 2em }--span.classifier {- font-family: sans-serif ;- font-style: oblique }--span.classifier-delimiter {- font-family: sans-serif ;- font-weight: bold }--span.interpreted {- font-family: sans-serif }--span.option {- white-space: nowrap }--span.pre {- white-space: pre }--span.problematic {- color: red }--span.section-subtitle {- /* font-size relative to parent (h1..h6 element) */- font-size: 80% }--table.citation {- border-left: solid 1px gray;- margin-left: 1px }--table.docinfo {- margin: 2em 4em }--table.docutils {- margin-top: 0.5em ;- margin-bottom: 0.5em }--table.footnote {- border-left: solid 1px black;- margin-left: 1px }--table.docutils td, table.docutils th,-table.docinfo td, table.docinfo th {- padding-left: 0.5em ;- padding-right: 0.5em ;- vertical-align: top }--table.docutils th.field-name, table.docinfo th.docinfo-name {- font-weight: bold ;- text-align: left ;- white-space: nowrap ;- padding-left: 0 }--h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,-h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {- font-size: 100% }--ul.auto-toc {- list-style-type: none }--</style>-</head>-<body>-<div class="document" id="simgi-a-stochastic-gillespie-simulator-for-molecular-systems">-<h1 class="title">simgi - A Stochastic Gillespie Simulator for Molecular Systems</h1>-<table class="docinfo" frame="void" rules="none">-<col class="docinfo-name" />-<col class="docinfo-content" />-<tbody valign="top">-<tr><th class="docinfo-name">Author:</th>-<td>Markus Dittrich</td></tr>-<tr class="field"><th class="docinfo-name">email:</th><td class="field-body">haskelladdict at users dot sourceforge dot net</td>-</tr>-<tr><th class="docinfo-name">Version:</th>-<td>0.2 (12/01/2009)</td></tr>-</tbody>-</table>-<div class="section" id="contents">-<h1>Contents</h1>-<ol class="arabic simple">-<li><a class="reference internal" href="#introduction">Introduction</a></li>-<li><a class="reference internal" href="#status">Status</a></li>-<li><a class="reference internal" href="#download">Download</a></li>-<li><a class="reference internal" href="#compilation">Compilation</a></li>-<li><a class="reference internal" href="#simgi-model-generation-language-sgl">Simgi Model Generation Language (SGL)</a></li>-<li><a class="reference internal" href="#example-input-files">Example Input Files</a></li>-<li><a class="reference internal" href="#bugs">Bugs</a></li>-</ol>-</div>-<div class="section" id="introduction">-<h1>Introduction</h1>-<p><strong>simgi</strong> is a fairly simple and straightforward stochastic simulator-based on Gillespie's <a class="footnote-reference" href="#id4" id="id1">[1]</a> direct method. <strong>simgi</strong> is implemented in-pure Haskell, command line driven and comes with a flexible simulation-description language called <a class="reference internal" href="#simgi-model-generation-language-sgl">Simgi Model Generation Language (SGL)</a>.-<strong>simgi</strong> uses a fast 64 bit implementation of the Mersenne Twister-algorithm as random number source.</p>-</div>-<div class="section" id="status">-<h1>Status</h1>-<p>The 0.2 release of <strong>simgi</strong> provides a fully functional simulator-which has been tested on several model systems some of which were-fairly large.</p>-</div>-<div class="section" id="download">-<h1>Download</h1>-<p>The current release of simgi can be downloaded <a class="reference external" href="http://sourceforge.net/project/platformdownload.php?group_id=260550">here</a>.</p>-</div>-<div class="section" id="compilation">-<h1>Compilation</h1>-<p>Compilaton of <strong>simgi</strong> requires</p>-<ul class="simple">-<li><a class="reference external" href="http://haskell.org/ghc/">>=ghc-6.10</a></li>-<li><a class="reference external" href="http://gmplib.org/">>=gmp-4.3</a></li>-<li><a class="reference external" href="http://hackage.haskell.org/package/mersenne-random-pure64">>=mersenne-random-pure64</a></li>-</ul>-<p>To compile the documentation (not required), you will also need</p>-<ul class="simple">-<li><a class="reference external" href="http://docutils.sourceforge.net/">>=docutils-0.5</a></li>-<li>latex, e.g., tetex or texlive</li>-</ul>-<p>Building of <strong>simgi</strong> can be done either via</p>-<ul class="simple">-<li>the standard <tt class="docutils literal">make, make check, make install</tt></li>-<li>or via cabal</li>-</ul>-</div>-<div class="section" id="simgi-model-generation-language-sgl">-<h1>Simgi Model Generation Language (SGL)</h1>-<p><strong>simgi</strong> simulations are described via <a class="reference internal" href="#simgi-model-generation-language-sgl">Simgi Model Generation Language-(SGL)</a>. The corresponding simulation input files typically have an <em>.sgl</em>-extension, but this is not enforced by the <strong>simgi</strong> simulation-engine.</p>-<p>A SGL file consists of zero or more descriptor blocks of the form</p>-<pre class="literal-block">-def <block name>-- <block content>--end-</pre>-<p>The formatting of the input files is very flexible. In-particular, neither newlines <a class="footnote-reference" href="#id5" id="id2">[2]</a> nor extraneous whitespace matter.-Hence, the above SGL block could have also been written on a single line.-However, it is strongly recommended to stick to a consistent and-"visually simple" layout to aid in "comprehending" the underlying-model. Also, it is important to point out that <strong>simgi</strong>'s parser is-case sensitive.</p>-<p><strong>Comments</strong> can be added to the SGL file and are parsed according to-the Haskell language specs</p>-<ul class="simple">-<li>simple line comments begin with a <tt class="docutils literal"><span class="pre">--</span></tt> token and treat everything-until the next newline as a comment, including valid SGL commands.-Hence, SGL blocks containing line comments need to be separated by-newlines in order to be parsed correctly.</li>-<li>block comments begin with a <tt class="docutils literal">{-</tt> token and end with a <tt class="docutils literal"><span class="pre">-}</span></tt>-token. Everything within a comment block is ignored by the parser-and block comments can be nested.</li>-</ul>-<p><strong>Expression Statements</strong> are an important and useful part of SGL.-<tt class="docutils literal">Expression statements</tt> are enclosed in curly braces and can contain-any mathematical expression involving doubles, the simulation time-(via the keyword <tt class="docutils literal">TIME</tt>), as well as the values of any variable or-molecule count. The values of time, molecule counts and variables-are evaluated at run time and represent the instantaneous values at the-time at which the expression is evaluated.-<tt class="docutils literal">Expressions statements</tt> can contain any-arithmetic expression involving the standard operators "+", "-", "*", "/", "^"-(exponentiation), and the mathematical functions <tt class="docutils literal">sqrt, exp, log, log2, log10, sin,-cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, acosh, atanh,-erf, erfc, abs</tt>.</p>-<p>Internally, <tt class="docutils literal">expression statements</tt> are converted into a compute stack-in RPN format which is evaluated at run-time. Even though this-procedure is fairly efficient, there is some numerical overhead-incurred at each iteration and the use of complicated rate-expressions should therefore be avoided if possible.</p>-<p>Below is a list of all SGL blocks available for describing simulations.-Presently, the order of blocks matters and should be exactly the same-in which they are described below. Several SGL blocks are-optional and are marked as such below.</p>-<p>Currently, the SGL specs define the following block types with their-respective block commands and block content:</p>-<p><strong>parameter block:</strong> <tt class="docutils literal"><block name></tt> = <em>parameters</em></p>-<blockquote>-<p>The purpose of the parameter block is to describe the global-simulation parameters. The following parameters are currently-supported:</p>-<dl class="docutils">-<dt><em>time</em> = <tt class="docutils literal">Double</tt></dt>-<dd>Maximum simulation time in seconds. Default is 0.0 s.</dd>-<dt><em>outputBuffer</em> = <tt class="docutils literal">Integer</tt></dt>-<dd><p class="first">Output will be kept in memory and written to the output file and-stdout every <em>outputBuffer</em> iterations. Larger values should-result in faster simulations but require more system memory.-Default is to write output every 10000 iterations.</p>-<p class="last">Note: <em>outputBuffer</em> only affects how often output is written to-the output file, not how much output is actually generated during a-simulation (see outputFreq parameter).</p>-</dd>-<dt><em>outputFreq</em> = <tt class="docutils literal">Integer</tt></dt>-<dd>Iteration frequency with which output is generated. Default is every 1000-iterations. Please note that output is written to the output file in batches of-<em>outputBuffer</em>.</dd>-<dt><em>systemVol</em> = <tt class="docutils literal">Double</tt></dt>-<dd>Volume of the simulation system in liters. This is needed to-properly compute the reaction rates in molar units. If rates-should rather be interpreted as reaction propensities (like-in <a class="footnote-reference" href="#id4" id="id3">[1]</a>) please set <em>systemVol = nil</em>. Default is a system-volume of 1.0 liter.</dd>-<dt><em>outputFile</em> = <tt class="docutils literal">Quoted String</tt></dt>-<dd>Name of the output file. This is the only required parameter-in the parameter section. If not given, the simulation will-terminate.</dd>-</dl>-</blockquote>-<p><strong>variable block:</strong> <tt class="docutils literal"><block name></tt> = <em>variables</em></p>-<blockquote>-<p>This block consist of a list of pairs of the form</p>-<pre class="literal-block">-String = <variable expression>-</pre>-<p>where <tt class="docutils literal">String</tt> is the variable name, and <tt class="docutils literal"><variable expression></tt>-is either a <tt class="docutils literal">Double</tt> or an <tt class="docutils literal">expression statement</tt> as defined above.-Variables can be used in any other <tt class="docutils literal">expression statement</tt> in the-SGL file including reaction rate definitions. Please make sure to-not define a variable in terms of itself to avoid infinite recursion.</p>-</blockquote>-<p><strong>molecule block:</strong> <tt class="docutils literal"><block name></tt> = <em>molecules</em></p>-<blockquote>-<p>This block consist of a list of pairs of the form</p>-<pre class="literal-block">-String = Integer-</pre>-<p>giving the name of each molecule and the number of molecules-present initially. For example, the following molecule definition-block defines molecules <tt class="docutils literal">A</tt> and <tt class="docutils literal">B</tt> with initial numbers of-100 and 200, respectively</p>-<pre class="literal-block">-def molecules- A = 100- B = 200-end-</pre>-<p><strong>NOTE</strong>: Please do not use any of the predefined mathematical-functions or defined variables (including <tt class="docutils literal">TIME</tt>) as-molecule names since this will lead to undefined behavior.</p>-</blockquote>-<p><strong>reaction block</strong>: <tt class="docutils literal"><block name></tt> = <em>reactions</em></p>-<blockquote>-<p>This block describes the reactions between molecules defined in-the molecule block. Reactions are specified via</p>-<pre class="literal-block">-<reactants> -> <products> | <rate expression> |-</pre>-<p>Here, <tt class="docutils literal"><reactants></tt> and <tt class="docutils literal"><products></tt> are of the form</p>-<pre class="literal-block">-Integer String + Integer String + .....-</pre>-<p>In this expression, <tt class="docutils literal">String</tt> is a molecule name-as defined in the molecule block and <tt class="docutils literal">Integer</tt> an optional-integer specifying the stoichiometry. If <tt class="docutils literal">Integer</tt> is not-explicitly given, it is assumed to be 1.</p>-<p>The <tt class="docutils literal"><rate expression></tt> can either be a fixed value of type-<tt class="docutils literal">Double</tt> or an <tt class="docutils literal">expression statement</tt> as defined above.</p>-<p>Below is an example reaction block for the two molecules <tt class="docutils literal">A</tt> and-<tt class="docutils literal">B</tt> defined above:</p>-<pre class="literal-block">-define reactions- 2A + B -> A | 10.0e-5 |- B -> A | {2.0e-5 * A * exp(-0.5*TIME)} |-end-</pre>-<p>In the first reaction, 2 <tt class="docutils literal">A</tt> molecules react with one <tt class="docutils literal">B</tt> to-yield another <tt class="docutils literal">A</tt> at a rate of 10.0e-5. The second-reaction describes a decay of <tt class="docutils literal">B</tt> back to <tt class="docutils literal">A</tt> at a rate-that is computed based on the instantaneous number of <tt class="docutils literal">A</tt>-molecules present and which decays exponentially with simulation-time.</p>-</blockquote>-<p><strong>event block</strong>: <tt class="docutils literal"><block name></tt> = <em>events</em></p>-<blockquote>-<p>An event block allows one to specify events which will occur during-the simulation. Each event consists of a <tt class="docutils literal"><trigger expression></tt> and-an associated set of <tt class="docutils literal"><action expressions></tt>.-Events are specified via</p>-<pre class="literal-block">-{ <trigger expression> } => { <action expression> }-</pre>-<p>Here, <tt class="docutils literal">trigger expression</tt> is of the form</p>-<pre class="literal-block">-<trigger primitive> [ <boolean operator> <trigger primitive>]-</pre>-<p>with <tt class="docutils literal"><trigger primitive></tt> defined by</p>-<pre class="literal-block">-<expression statement> relational operator <expression statement>-</pre>-<p>Each <tt class="docutils literal"><trigger primitive></tt> contains two <tt class="docutils literal">expression statements</tt>-as defined above and a <tt class="docutils literal">relational operator</tt> which can be-any of <tt class="docutils literal">>=</tt>, <tt class="docutils literal"><=</tt>, <tt class="docutils literal">==</tt>, <tt class="docutils literal">></tt>, and <tt class="docutils literal"><</tt>. Hence, each-<tt class="docutils literal"><trigger primitive></tt> evaluates to either <tt class="docutils literal">true</tt> or <tt class="docutils literal">false</tt>.</p>-<p>Several <tt class="docutils literal"><trigger primitives></tt> can be chained together via the-<tt class="docutils literal"><boolean operators></tt> <tt class="docutils literal">&&</tt> and <tt class="docutils literal">||</tt> to yield a final boolean-value of <tt class="docutils literal">true</tt> or <tt class="docutils literal">false</tt>.</p>-<p>If the <tt class="docutils literal"><trigger expression></tt> evaluates to true during an-iteration, the associated <tt class="docutils literal"><action expressions></tt> is executed-during the same timestep.</p>-<p><tt class="docutils literal"><action expression></tt> consists of a semi-colon separated list of-assignments</p>-<pre class="literal-block">-String = <assignment expression> [; String = <assignment expression>]-</pre>-<p>where <tt class="docutils literal">String</tt> is a molecule or variable name and-<tt class="docutils literal"><expression></tt> either a <tt class="docutils literal">Double</tt> or an <tt class="docutils literal">expression statement</tt>.</p>-<p><strong>NOTE</strong>: Since molecule counts are integer values assignments-to molecule counts in <tt class="docutils literal"><action expression></tt> will be converted-to an integer value via <tt class="docutils literal">floor</tt>.</p>-</blockquote>-<p><strong>output block</strong>: <tt class="docutils literal"><block name></tt> = <em>output</em></p>-<blockquote>-<p>This block consists of a simple list of variable and molecule-names that will be streamed to the output file in the same order:</p>-<pre class="literal-block">-[ name1, name2, name3, .... ]-</pre>-</blockquote>-</div>-<div class="section" id="example-input-files">-<h1>Example Input Files</h1>-<p>Below are several example input files detailing the use of SGL:</p>-<ul class="simple">-<li><a class="reference external" href="model_files/volterra.sgl">Lotka-Volterra Model</a></li>-<li><a class="reference external" href="model_files/brusselator.sgl">Brusselator Model</a></li>-<li><a class="reference external" href="model_files/oregonator.sgl">Oregonator Model</a></li>-</ul>-<p>These are also available in the <em>Models/</em> sub-directory in the source tree.</p>-</div>-<div class="section" id="bugs">-<h1>Bugs</h1>-<p>Please report all bugs and feature requests to-<haskelladdict at users dot sourceforge dot net>.</p>-<table class="docutils footnote" frame="void" id="id4" rules="none">-<colgroup><col class="label" /><col /></colgroup>-<tbody valign="top">-<tr><td class="label">[1]</td><td><em>(<a class="fn-backref" href="#id1">1</a>, <a class="fn-backref" href="#id3">2</a>)</em> Daniel T. Gillespie (1977). "Exact Stochastic Simulation of Coupled Chemical Reactions". The Journal of Physical Chemistry 81 (25): 2340-2361</td></tr>-</tbody>-</table>-<table class="docutils footnote" frame="void" id="id5" rules="none">-<colgroup><col class="label" /><col /></colgroup>-<tbody valign="top">-<tr><td class="label"><a class="fn-backref" href="#id2">[2]</a></td><td>An exception to this rule are line comments starting with <tt class="docutils literal"><span class="pre">--</span></tt> which ingnore everything until the next newline.</td></tr>-</tbody>-</table>-</div>-</div>-</body>-</html>+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">+<html xmlns="http://www.w3.org/1999/xhtml">+<head>+ <title>Simgi - A Stochastic Gillespie Simulator</title>+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />+ <meta name="generator" content="pandoc" />+ <meta name="author" content="Markus Dittrich" />+ <meta name="date" content="02/10/2010" />+</head>+<body>+<h1 class="title">Simgi - A Stochastic Gillespie Simulator</h1>+<hr+ /><p+>This manual covers simgi v0.3 (released 02/10/2010).</p+><br /><div id="contents"+><h2+ >Contents</h2+ ><ol style="list-style-type: decimal;"+ ><li+ ><a href="#introduction"+ >Introduction</a+ ></li+ ><li+ ><a href="#download"+ >Download</a+ ></li+ ><li+ ><a href="#installation-and-compilation"+ >Installation and Compilation</a+ ></li+ ><li+ ><a href="#simgi-model-generation-language-syntax"+ >Simgi Model Description Language Syntax</a+ ></li+ ><li+ ><a href="#input-samples"+ >Input Samples</a+ ></li+ ><li+ ><a href="#contact-and-bugs"+ >Contact and Bugs</a+ ></li+ ><li+ ><a href="#copyright-and-license"+ >Copyright and License</a+ ></li+ ><li+ ><a href="#references"+ >References</a+ ></li+ ></ol+ ><br /> <br /></div+><div id="introduction"+><h2+ >Introduction</h2+ ><p+ >simgi is a small but efficient stochastic simulator based on <a href="#ref_1"+ >Gillespie's</a+ > direct method and uses a 64 bit implementation of the Mersenne Twister algorithm as pseudo random number source. simgi is command line driven and features a powerful and flexible model generation language.</p+ ></div+><div id="download"+><h2+ >Download</h2+ ><p+ >The current release of simgi (version 0.3) can be obtained <a href="http://sourceforge.net/project/platformdownload.php?group_id=260550"+ >here</a+ > in both source and binary formats.</p+ ></div+><div id="installation-and-compilation"+><h2+ >Installation and Compilation</h2+ ><p+ >The simgi binary packages for 32 bit and 64 bit Linux should run on any recent distribution with <em+ >libgmp</em+ > installed.</p+ ><p+ >simgi is written in pure Haskell and compilation requires a working ghc Haskell compiler as well as the following additional packages:</p+ ><ul+ ><li+ ><a href="http://haskell.org/ghc/"+ >>=ghc-6.10</a+ ></li+ ><li+ ><a href="http://gmplib.org/"+ >>=gmp-4.3</a+ ></li+ ><li+ ><a href="http://hackage.haskell.org/package/mersenne-random-pure64"+ >>=mersenne-random-pure64</a+ ></li+ ><li+ ><a href="http://www.gnu.org/software/bc/bc.html"+ >bc</a+ > (for the test suite only)</li+ ></ul+ ><p+ >The optional document generation requires</p+ ><ul+ ><li+ ><a href="http://johnmacfarlane.net/pandoc"+ >>=pandoc-1.4</a+ ></li+ ><li+ >latex (e.g. texlive)</li+ ></ul+ ><p+ >simgi can be build in one of two ways</p+ ><ol style="list-style-type: decimal;"+ ><li+ >the standard <em+ >make, make check, make install</em+ ></li+ ><li+ >via cabal</li+ ></ol+ ><br /></div+><div id="simgi-model-generation-language-syntax"+><h2+ >Simgi Model Generation Language Syntax</h2+ ><div id="general-syntax"+ ><h3+ >General Syntax</h3+ ><p+ >simgi simulation models are described via <em+ >Simgi Model Generation Language (SGL)</em+ > inside a plain text ASCII file. Syntactically, each <em+ >SGL</em+ > file consists of a number of blocks each describing a certain aspect of the simulation such as variables, parameters, molecules, or reactions. Each block has the following structure</p+ ><pre+ ><code+ > <block name>++ <block content>++ end+</code+ ></pre+ ><p+ >Please note that there is no need to put block name and content description on separate lines even though it is highly recommended to do so for ease of reading.</p+ ><p+ >Even though syntactically <em+ >SGL</em+ > does not require blocks to be arranged in any specific order, semantically, each identifier used in a given block has to be defined when first used. Hence, the molecule definition block has to be placed before the reaction definition block.</p+ ></div+ ><div id="comment-on-syntax-notation"+ ><h3+ >Comment on Syntax Notation</h3+ ><p+ >In the syntax specification below, the following notation is used</p+ ><ul+ ><li+ ><p+ >If a syntactic expression can contain either one of a number of options A, B, C, ... this is specified as <code+ >( A <|> B <|> C <|> ..)</code+ >.</p+ ></li+ ><li+ ><p+ >If a syntactic element A is optional, it is enclosed in brackets <code+ >[ A ]</code+ >.</p+ ></li+ ><li+ ><p+ >If a syntactic element B can repeat zero or more times it is enclosed in curly braces <code+ >{ A }</code+ >.</p+ ></li+ ><li+ ><p+ >Literal braces, parenthesis, etc. are always enclosed in single quotes, e.g, '(' or '}'.</p+ ></li+ ></ul+ ><p+ >Please note that this notation does not apply in the examples given, which are always meant to be literal code examples.</p+ ></div+ ><div id="comments"+ ><h3+ >Comments</h3+ ><p+ >Comments inside SGL follow the standard Haskell convention. Multiline comments can be wrapped inside <em+ >{-- --}</em+ >. Single line comments start with <em+ >--</em+ > and ignore everything until the next newline. For example,</p+ ><pre+ ><code+ > {-- this is+ a multiline+ comment+ --}++ foo = bar -- this is a single line comment+</code+ ></pre+ ></div+ ><div id="identifiers"+ ><h3+ >Identifiers</h3+ ><p+ >SGL identifiers have to start with a lower or uppercase letter followed by any number of lower or uppercase letters, digits, or underscores. Please note that identifiers can not be any of the keywords or mathematical functions available in simgi.</p+ ></div+ ><div id="numerical-identifiers-and-statement-blocks"+ ><h3+ >Numerical Identifiers and Statement Blocks</h3+ ><p+ >Inside SGL, some identifiers are assigned numerical values. Examples are variables, initial molecule numbers, reaction rates, or event definitions. A numerical value can either be a literal <em+ >Double</em+ > value or a <em+ >statement block</em+ >. The latter is a mathematical expression enclosed in curly braces that evaluates to a <em+ >Double</em+ > literal either at parse-time or at run-time. Whether a <em+ >statement block</em+ > is evaluated at parse or run-time depends on the definition block in which it occurs as detailed in the description for each block below.</p+ ><p+ ><em+ >statement blocks</em+ > which are evaluated at parse-time may contain only mathematical expression involving <em+ >Double</em+ > literals and variable values. <em+ >statement blocks</em+ > which are evaluated at run-time can in addition contain the instantaneous counts of molecules as well as the current simulation time accessible via the keyword <em+ >TIME</em+ >. These two types of <em+ >statement blocks</em+ > are referred to as <em+ >parse-time statement blocks</em+ > and <em+ >run-time statement blocks</em+ >, respectively.</p+ ><p+ >Assuming that <em+ >foo</em+ > and <em+ >bar</em+ > are variables, the following are valid statement blocks</p+ ><p+ ><strong+ >Example:</strong+ ></p+ ><pre+ ><code+ > { 3.0*foo + bar^2 } -- parse-time statement block++ { 3.0*exp(-foo/TIME) + bar*TIME } -- run-time statement block+</code+ ></pre+ ><p+ >Inside <em+ >statment blocks</em+ > simgi supports the use of the following mathematical functions:</p+ ><blockquote+ ><p+ >sqrt, exp, log, log2, log10, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, acosh, atanh, erf, erfc, abs.</p+ ></blockquote+ ><p+ ><strong+ >Note 1:</strong+ > Depending on their numerical complexity, <em+ >run-time statement blocks</em+ > incur a computational overhead and should therefore be avoided if possible.</p+ ><p+ ><strong+ >Note 2:</strong+ > SGL statements which expect an <em+ >Integer</em+ > value instead of a <em+ >Double</em+ > will use <code+ >floor()</code+ > to for rounding.</p+ ></div+ ><div id="variable-definition-block"+ ><h3+ >Variable Definition Block</h3+ ><p+ ><strong+ ><block name> = variables</strong+ ></p+ ><p+ >This block allows the definition of variables which can then be used inside any <em+ >statement block</em+ > in the remainder of the SGL file. Variable assignments are of the form</p+ ><blockquote+ ><p+ ><variable name> = (<em+ >Double</em+ > <|> <em+ >parse-time statement block</em+ >)</p+ ></blockquote+ ><p+ >Since the variable block will be evaluated only after it has been fully parsed, variables which depend on other variables via <em+ >parse-time statement blocks</em+ > do not have to be defined in order.</p+ ><p+ ><strong+ >Note:</strong+ > Users have to ensure that variable definitions do not contain circular references since this may lead to infinite evaluation loops.</p+ ></div+ ><div id="parameter-definition-block"+ ><h3+ >Parameter Definition Block</h3+ ><p+ ><strong+ ><block name> = parameters</strong+ ></p+ ><p+ >The parameter block defines the main simulation control parameters. It can be left out and all parameters will then assume their default values. Available parameter options are</p+ ><ul+ ><li+ ><p+ ><strong+ >time</strong+ > = (<em+ >Double</em+ > <|> <em+ >parse-time statement block</em+ >)</p+ ><p+ >Maximum simulation time in seconds. Default is 0.0 s.</p+ ></li+ ><li+ ><p+ ><strong+ >outputBuffer</strong+ > = (<em+ >Integer</em+ > <|> <em+ >parse-time statement block</em+ >)</p+ ><p+ >Output will be kept in memory and written to the output file and stdout every <em+ >outputBuffer</em+ > iterations. Larger values should result in faster simulations due to reduced I/O but will require more system memory. Default is to write output every 10000 iterations.</p+ ><p+ >Note: The value of <em+ >outputBuffer</em+ > only affects the chunk size in which output is written to the output file, not how much output is actually generated during a simulation (see outputFreq parameter).</p+ ></li+ ><li+ ><p+ ><strong+ >outputFreq</strong+ > = (<em+ >Integer</em+ > <|> <em+ >parse-time statement block</em+ >)</p+ ><p+ >Iteration frequency with which output is generated. Default is to generate output every 1000 iterations.</p+ ></li+ ><li+ ><p+ ><strong+ >systemVol</strong+ > = (<em+ >Double</em+ > <|> <em+ >parse-time statement block</em+ > <|> <em+ >nil</em+ >)</p+ ><p+ >Volume of the simulation system in dm<sup+ >3</sup+ > nor <em+ >nil</em+ >. Unless <em+ >nil</em+ > is specified, reaction rates are interpreted in molar units. If <em+ >nil</em+ > is given instead, rates are interpreted as reaction propensities (see <a href="#ref_1"+ >1</a+ >). The default is a system volume of 1.0 dm<sup+ >3</sup+ >.</p+ ></li+ ></ul+ ></div+ ><div id="molecule-definition-block"+ ><h3+ >Molecule Definition Block</h3+ ><p+ ><strong+ ><block name> = molecules</strong+ ></p+ ><p+ >The molecule definition block is used to declare all molecular species present in the simulation and assign initial molecule counts to each species. Molecule assignments are of the form</p+ ><blockquote+ ><p+ ><molecule name> = (<em+ >Integer</em+ > <|> <em+ >parse-time statement block</em+ >)</p+ ></blockquote+ ><p+ ><strong+ >Note:</strong+ > In contrast to many ODE simulation packages, simgi requires the specification of molecule numbers not concentrations.</p+ ><p+ ><strong+ >Example:</strong+ ></p+ ><pre+ ><code+ > molecules+ A = 100+ B = { 10 * someVar }+ end+</code+ ></pre+ ></div+ ><div id="reaction-definition-block"+ ><h3+ >Reaction Definition Block</h3+ ><p+ ><strong+ ><block name> = reactions</strong+ ></p+ ><p+ >The reaction definition block is the heart of the simgi model and describes the dynamics of the underlying chemical system. Rate expressions are of the general form</p+ ><blockquote+ ><p+ >a<sub+ >1</sub+ > R<sub+ >1</sub+ > + ... + a<sub+ >N</sub+ > R<sub+ >N</sub+ > -> b<sub+ >1</sub+ > P<sub+ >1</sub+ > + ... + b<sub+ >M</sub+ > P<sub+ >M</sub+ > | <rate> |</p+ ></blockquote+ ><p+ >where</p+ ><blockquote+ ><p+ ><rate> = (<em+ >Double</em+ > <|> <em+ >run-time statement block</em+ >)</p+ ></blockquote+ ><p+ >and a<sub+ >i</sub+ >, R<sub+ >i</sub+ >, b<sub+ >j</sub+ >, P<sub+ >j</sub+ > are the stoichiometric coefficients and names of reactants and products, respectively. If any of the stoichiometric coefficients is omitted it is assumed to be equal to 1.</p+ ><p+ ><strong+ >Example:</strong+ ></p+ ><pre+ ><code+ > reactions+ 2A + 3B -> C | 1e-4 |+ 10B + 4C -> D | { 2.0 * exp(-A/TIME) } | + end+</code+ ></pre+ ><p+ >Here, the rate for the second reaction is given by a <em+ >run-time statement block</em+ > and exponentially decays as a function of the instantaneous concentration of species A and simulation time.</p+ ></div+ ><div id="event-definition-block"+ ><h3+ >Event Definition Block</h3+ ><p+ ><strong+ ><block name> = events</strong+ ></p+ ><p+ >Events allow users to interact with a simulation at run-time. The event block consists of a list of event statements of the form</p+ ><blockquote+ ><p+ >[ '(' ] <em+ >trigger expression</em+ > [ ')' ] => '[' <em+ >action expression list</em+ > ']'</p+ ></blockquote+ ><p+ >Here, <em+ >trigger expression</em+ > defines when an event takes place and <em+ >action expression</em+ > specifies the action triggered by the event. During each iteration of the simulation each <em+ >trigger expression</em+ > will be evaluated and if <em+ >True</em+ > all actions in the associated <em+ >action expression list</em+ > will be executed.</p+ ><p+ >A trigger expression consists of one or more trigger primitives combined via the boolean operators <code+ >&&</code+ > (<em+ >AND</em+ >) and <code+ >||</code+ > (<em+ >OR</em+ >)</p+ ><blockquote+ ><p+ ><em+ >trigger expression</em+ > = <em+ >trigger primitive</em+ > { (&& <|> ||) <em+ >trigger primitive</em+ > }</p+ ></blockquote+ ><p+ >Trigger primitives each consist of two <em+ >run-time statement blocks</em+ > or <em+ >Double</em+ > literals combined via a relational operation</p+ ><blockquote+ ><p+ ><em+ >trigger primitive</em+ > = [ '(' ] (<em+ >run-time statement block</em+ > <|> <em+ >Double</em+ >) ( == <|> < <|> > <|> <= <|> => ) (<em+ >run-time statement block</em+ > <|> <em+ >Double</em+ >) [ ')' ]</p+ ></blockquote+ ><p+ >An <em+ >action expression</em+ > consists of a comma separated list of <em+ >action primitives</em+ ></p+ ><blockquote+ ><p+ ><em+ >action expression</em+ > = <em+ >action primitive</em+ > { , <em+ >action primitive</em+ > }</p+ ></blockquote+ ><p+ >where each <em+ >action primitive</em+ > is an assignment statement of the form</p+ ><blockquote+ ><p+ >(<em+ >variable</em+ > <|> <em+ >molecule name</em+ >) = (<em+ >Double</em+ > <|> <em+ >run-time statement block</em+ >)</p+ ></blockquote+ ><p+ ><strong+ >Example:</strong+ ></p+ ><pre+ ><code+ > events+ A == 100 => [ A = {A/100} ]+ (A == 100 && B == 0) => [A = 10, B = {A/10}]+ A == 10 || C == 50 => [C = 10, A = {A+C*TIME}]+ end+</code+ ></pre+ ></div+ ><div id="output-definition-block"+ ><h3+ >Output Definition Block</h3+ ><p+ ><strong+ ><block name> = output</strong+ ></p+ ><p+ >This block defines the name of the output file and the type of simulation output that will be produced and written to it. Presently, simgi will only generate a single output file and produce a separate column for each output item requested. Available options are</p+ ><ul+ ><li+ ><p+ ><strong+ >outputFile</strong+ > = <em+ >String</em+ ></p+ ><p+ >Name of the output file. If this option is not given no output is produced.</p+ ></li+ ><li+ ><p+ >'[' <em+ >String</em+ > <|> <em+ >run-time statement block</em+ > { , <em+ >String</em+ > <|> <em+ >run-time statment block</em+ > } ']'</p+ ><p+ >List of variables to be output. Users can either provide the name of a variable or molecule, or any <em+ >run-time statement block</em+ >. In addition, the simulation time and iteration number can be output via the special keywords TIMES and ITERATIONS. The order in which items are punched to the output file is the same as the one in which they are listed.</p+ ></li+ ></ul+ ><p+ ><strong+ >Note:</strong+ > Data is produced only every <em+ >outputFreq</em+ > iterations as defined in the <em+ >Parameter Definition Block</em+ >.</p+ ><p+ ><strong+ >Example:</strong+ ></p+ ><pre+ ><code+ > output+ outputFile = "someFile.dat"+ [ TIMES, A, B, {A*B/10}, ITERATIONS]+ end+</code+ ></pre+ ></div+ ></div+><div id="input-samples"+><h2+ >Input Samples</h2+ ><p+ >Both the binary and source distributions for simgi contain a <em+ >Models/</em+ > directory with several example SGL input files for a variety of systems.</p+ ></div+><div id="contact-and-bugs"+><h2+ >Contact and Bugs</h2+ ><p+ >Please report bugs to Markus Dittrich <haskelladdict.at.users.sourceforge.net>. The author would also like to encourage users to email comments, suggestions, and questions.</p+ ></div+><div id="copyright-and-license"+><h2+ >Copyright and License</h2+ ><p+ >simgi was developed and is currently maintained by Markus Dittrich <haskelladdict.at.users.sourceforge.net>. simgi is free software and released under the GPL version 3.</p+ ><p+ >Copyright 2009-2010 Markus Dittrich, National Resource for Biomedical Supercomputing & Carnegie Mellon University.</p+ ></div+><div id="references"+><h2+ >References</h2+ ><p id="ref_1">[1] Daniel T. Gillespie (1977). "Exact Stochastic Simulation of Coupled Chemical Reactions". The Journal of Physical Chemistry 81 (25): 2340-2361</p>++</div+>+</body>+</html>+
+ doc/simgi.mdml view
@@ -0,0 +1,425 @@+% Simgi - A Stochastic Gillespie Simulator+% Markus Dittrich+% 02/10/2010 ++***+This manual covers simgi v0.3 (released 02/10/2010).++<br />+++## Contents++1) [Introduction](#introduction)+2) [Download](#download)+3) [Installation and Compilation](#installation-and-compilation)+4) [Simgi Model Description Language Syntax](#simgi-model-generation-language-syntax)+5) [Input Samples](#input-samples)+6) [Contact and Bugs](#contact-and-bugs)+7) [Copyright and License](#copyright-and-license)+8) [References](#references)+++<br />+<br />+++## Introduction++simgi is a small but efficient stochastic simulator based on +[Gillespie's](#ref_1) direct method and uses a 64 bit implementation +of the Mersenne Twister algorithm as pseudo random number source. +simgi is command line driven and features a powerful +and flexible model generation language. +++## Download++The current release of simgi (version 0.3) can be obtained +[here](<http://sourceforge.net/project/platformdownload.php?group_id=260550>)+in both source and binary formats.+++## Installation and Compilation++The simgi binary packages for 32 bit and 64 bit Linux should run on +any recent distribution with *libgmp* installed.++simgi is written in pure Haskell and compilation requires a working+ghc Haskell compiler as well as the following additional packages:++* [>=ghc-6.10](<http://haskell.org/ghc/>)+* [>=gmp-4.3](<http://gmplib.org/>)+* [>=mersenne-random-pure64](<http://hackage.haskell.org/package/mersenne-random-pure64>)+* [bc](http://www.gnu.org/software/bc/bc.html) (for the test suite only)++The optional document generation requires++* [>=pandoc-1.4](http://johnmacfarlane.net/pandoc)+* latex (e.g. texlive)++simgi can be build in one of two ways++1) the standard *make, make check, make install*+2) via cabal++<br />++## Simgi Model Generation Language Syntax++### General Syntax+simgi simulation models are described via *Simgi Model+Generation Language (SGL)* inside a plain text ASCII file.+Syntactically, each *SGL* file consists of a number of +blocks each describing a certain aspect of the +simulation such as variables, parameters, molecules,+or reactions. Each block has the following structure++~~~~+ <block name>++ <block content>++ end+~~~~++Please note that there is no need to put block name and content+description on separate lines even though it is highly recommended +to do so for ease of reading. ++Even though syntactically *SGL* does not require blocks to be arranged+in any specific order, semantically, each identifier used in a given+block has to be defined when first used. Hence, the molecule+definition block has to be placed before the reaction definition block.++++### Comment on Syntax Notation ++In the syntax specification below, the following notation is used++* If a syntactic expression can contain either one of a number of+options A, B, C, ... this is specified as `( A <|> B <|> C <|> ..)`.++* If a syntactic element A is optional, it is enclosed in brackets+`[ A ]`.++* If a syntactic element B can repeat zero or more times it is +enclosed in curly braces `{ A }`.++* Literal braces, parenthesis, etc. are always enclosed in single quotes,+e.g, '(' or '}'.++Please note that this notation does not apply in the examples+given, which are always meant to be literal code examples.+++### Comments++Comments inside SGL follow the standard Haskell convention. Multiline+comments can be wrapped inside *{-- --}*. Single line comments+start with *--* and ignore everything until the next newline. For example,++~~~~~+ {-- this is+ a multiline+ comment+ --}++ foo = bar -- this is a single line comment+~~~~~++### Identifiers++SGL identifiers have to start with a lower or uppercase letter +followed by any number of lower or uppercase letters, digits, or +underscores. Please note that identifiers can not be any of the keywords+or mathematical functions available in simgi.++++### Numerical Identifiers and Statement Blocks++Inside SGL, some identifiers are assigned numerical values. Examples+are variables, initial molecule numbers, reaction rates,+or event definitions. A numerical value can either be a literal *Double*+value or a *statement block*. The latter is a mathematical expression+enclosed in curly braces that evaluates to a *Double* literal+either at parse-time or at run-time. Whether a *statement block* is+evaluated at parse or run-time depends on the definition block in+which it occurs as detailed in the description for each block below.++*statement blocks* which are evaluated at parse-time may contain only+mathematical expression involving *Double* literals and variable values.+*statement blocks* which are evaluated at run-time can in +addition contain the instantaneous counts of molecules as well as the +current simulation time accessible via the keyword *TIME*.+These two types of *statement blocks* are referred to as *parse-time +statement blocks* and *run-time statement blocks*, respectively.++Assuming that *foo* and *bar* are variables, the following are+valid statement blocks++__Example:__++~~~~~~+ { 3.0*foo + bar^2 } -- parse-time statement block++ { 3.0*exp(-foo/TIME) + bar*TIME } -- run-time statement block+~~~~~~++Inside *statment blocks* simgi supports the use of the following +mathematical functions: ++> sqrt, exp, log, log2, log10, sin, cos, tan, asin, acos, atan, +> sinh, cosh, tanh, asinh, acosh, atanh, acosh, atanh, +> erf, erfc, abs.++__Note 1:__ Depending on their numerical complexity, *run-time +statement blocks* incur a computational overhead +and should therefore be avoided if possible.++__Note 2:__ SGL statements which expect an *Integer* value instead+of a *Double* will use `floor()` to for rounding. +++++### Variable Definition Block++__\<block name\> = variables__++This block allows the definition of variables which can then be+used inside any *statement block* in the remainder of the SGL file.+Variable assignments are of the form++> \<variable name\> = (*Double* <|> *parse-time statement block*)++Since the variable block will be evaluated only after it has been +fully parsed, variables which depend on other variables +via *parse-time statement blocks* do not have to be defined in order. ++__Note:__ Users have to ensure that variable definitions do not+contain circular references since this may lead to infinite +evaluation loops.++++ +### Parameter Definition Block++__\<block name\> = parameters__++The parameter block defines the main simulation control parameters. +It can be left out and all parameters will then assume their default+values. Available parameter options are++* __time__ = (*Double* <|> *parse-time statement block*)++ Maximum simulation time in seconds. Default is 0.0 s.++* __outputBuffer__ = (*Integer* <|> *parse-time statement block*)++ Output will be kept in memory and written to the output file and+ stdout every *outputBuffer* iterations. Larger values should+ result in faster simulations due to reduced I/O but will+ require more system memory.+ Default is to write output every 10000 iterations.++ Note: The value of *outputBuffer* only affects the chunk size in which + output is written to the output file, not how much output is actually + generated during a simulation (see outputFreq parameter).++* __outputFreq__ = (*Integer* <|> *parse-time statement block*)++ Iteration frequency with which output is generated. Default is to + generate output every 1000 iterations. ++* __systemVol__ = (*Double* <|> *parse-time statement block* <|> *nil*)++ Volume of the simulation system in dm^3^ nor *nil*. Unless *nil* is+ specified, reaction rates are interpreted in molar units. If *nil*+ is given instead, rates are interpreted as reaction propensities + (see [1](#ref_1)). The default is a system volume of 1.0 dm^3^.+++++### Molecule Definition Block++__\<block name\> = molecules__++The molecule definition block is used to declare all molecular species +present in the simulation and assign initial molecule counts to each +species. Molecule assignments are of the form++> \<molecule name\> = (*Integer* <|> *parse-time statement block*)++__Note:__ In contrast to many ODE simulation packages, simgi requires+the specification of molecule numbers not concentrations.++__Example:__++~~~~~~+ molecules+ A = 100+ B = { 10 * someVar }+ end+~~~~~~++++### Reaction Definition Block++__\<block name\> = reactions__++The reaction definition block is the heart of the simgi model and+describes the dynamics of the underlying chemical system. Rate+expressions are of the general form++> a~1~ R~1~ + ... + a~N~ R~N~ -> b~1~ P~1~ + ... + b~M~ P~M~ | \<rate> |++where++> \<rate\> = (*Double* <|> *run-time statement block*)++and a~i~, R~i~, b~j~, P~j~ are the stoichiometric+coefficients and names of reactants and products, respectively. If+any of the stoichiometric coefficients is omitted it is assumed+to be equal to 1.+++__Example:__++~~~~~~+ reactions+ 2A + 3B -> C | 1e-4 |+ 10B + 4C -> D | { 2.0 * exp(-A/TIME) } | + end+~~~~~~++Here, the rate for the second reaction is given by a *run-time+statement block* and exponentially decays as a function of the +instantaneous concentration of species A and simulation time.++++### Event Definition Block++__\<block name\> = events__++Events allow users to interact with a simulation at run-time. +The event block consists of a list of event statements of the+form++> [ '(' ] *trigger expression* [ ')' ] => '[' *action expression list* ']'++Here, *trigger expression* defines when an event takes+place and *action expression* specifies the action triggered+by the event. During each iteration of the simulation+each *trigger expression* will be evaluated and +if *True* all actions in the associated *action expression list*+will be executed. ++A trigger expression consists of one or more trigger primitives+combined via the boolean operators `&&` (*AND*) and `||` (*OR*)++> *trigger expression* = *trigger primitive* { (&& <|> ||) +> *trigger primitive* }++Trigger primitives each consist of two *run-time statement blocks* or +*Double* literals combined via a relational operation++> *trigger primitive* = [ '(' ] (*run-time statement block* <|> *Double*) +> ( == <|> < <|> > <|> <= <|> => ) +> (*run-time statement block* <|> *Double*) [ ')' ]++An *action expression* consists of a comma separated list of +*action primitives*++> *action expression* = *action primitive* { , *action primitive* }++where each *action primitive* is an assignment statement of the form++> (*variable* <|> *molecule name*) = (*Double* <|> *run-time statement block*)++__Example:__++~~~~~~+ events+ A == 100 => [ A = {A/100} ]+ (A == 100 && B == 0) => [A = 10, B = {A/10}]+ A == 10 || C == 50 => [C = 10, A = {A+C*TIME}]+ end+~~~~~~++++### Output Definition Block++__\<block name\> = output__++This block defines the name of the output file and the type of simulation+output that will be produced and written to it. Presently, simgi will only +generate a single output file and produce a separate column for each output +item requested. Available options are++* __outputFile__ = *String*++ Name of the output file. If this option is not given no output is+ produced.++* '[' *String* <|> *run-time statement block* { , *String* <|> *run-time statment+block* } ']'++ List of variables to be output. Users can either provide the name of a+ variable or molecule, or any *run-time statement block*. In addition,+ the simulation time and iteration number can be output via the special+ keywords TIMES and ITERATIONS. The order in which items are punched+ to the output file is the same as the one in which they are listed.+ ++__Note:__ Data is produced only every *outputFreq* iterations as defined+in the *Parameter Definition Block*.++__Example:__++~~~~~~+ output+ outputFile = "someFile.dat"+ [ TIMES, A, B, {A*B/10}, ITERATIONS]+ end+~~~~~~~++++## Input Samples++Both the binary and source distributions for simgi contain a *Models/*+directory with several example SGL input files for a variety of +systems.+++## Contact and Bugs++Please report bugs to Markus Dittrich <haskelladdict.at.users.sourceforge.net>. +The author would also like to encourage users to email comments, suggestions,+and questions.+++## Copyright and License++simgi was developed and is currently maintained by +Markus Dittrich <haskelladdict.at.users.sourceforge.net>. simgi+is free software and released under the GPL version 3.++Copyright 2009-2010 Markus Dittrich, National Resource for Biomedical +Supercomputing & Carnegie Mellon University.++++## References++<p id="ref_1">+[1] Daniel T. Gillespie (1977). "Exact Stochastic Simulation of Coupled Chemical Reactions". The Journal of Physical Chemistry 81 (25): 2340-2361+</p>
doc/simgi.pdf view
binary file changed (245560 → 174168 bytes)
− doc/simgi.rst
@@ -1,324 +0,0 @@-================================================================-simgi - A Stochastic Gillespie Simulator for Molecular Systems-================================================================--:Author: Markus Dittrich--:email: haskelladdict at users dot sourceforge dot net--:Version: 0.2 (12/01/2009)---Contents------------1) Introduction_-2) Status_-3) Download_-4) Compilation_ -5) `Simgi Model Generation Language (SGL)`_-6) `Example Input Files`_-7) Bugs_---Introduction---------------**simgi** is a fairly simple and straightforward stochastic simulator -based on Gillespie's [1]_ direct method. **simgi** is implemented in -pure Haskell, command line driven and comes with a flexible simulation-description language called `Simgi Model Generation Language (SGL)`_.-**simgi** uses a fast 64 bit implementation of the Mersenne Twister-algorithm as random number source.---Status ---------The 0.2 release of **simgi** provides a fully functional simulator -which has been tested on several model systems some of which were-fairly large. ---Download-----------The current release of simgi can be downloaded `here <http://sourceforge.net/project/platformdownload.php?group_id=260550>`_.---Compilation--------------Compilaton of **simgi** requires --- `>=ghc-6.10 <http://haskell.org/ghc/>`_-- `>=gmp-4.3 <http://gmplib.org/>`_ -- `>=mersenne-random-pure64 <http://hackage.haskell.org/package/mersenne-random-pure64>`_--To compile the documentation (not required), you will also need--- `>=docutils-0.5 <http://docutils.sourceforge.net/>`_-- latex, e.g., tetex or texlive---Building of **simgi** can be done either via --- the standard ``make, make check, make install``-- or via cabal----Simgi Model Generation Language (SGL)----------------------------------------**simgi** simulations are described via `Simgi Model Generation Language -(SGL)`_. The corresponding simulation input files typically have an *.sgl* -extension, but this is not enforced by the **simgi** simulation -engine. --A SGL file consists of zero or more descriptor blocks of the form--::-- def <block name>-- <block content>-- end--The formatting of the input files is very flexible. In-particular, neither newlines [2]_ nor extraneous whitespace matter. -Hence, the above SGL block could have also been written on a single line. -However, it is strongly recommended to stick to a consistent and -"visually simple" layout to aid in "comprehending" the underlying-model. Also, it is important to point out that **simgi**'s parser is -case sensitive.--**Comments** can be added to the SGL file and are parsed according to -the Haskell language specs--- simple line comments begin with a ``--`` token and treat everything - until the next newline as a comment, including valid SGL commands. - Hence, SGL blocks containing line comments need to be separated by - newlines in order to be parsed correctly.-- block comments begin with a ``{-`` token and end with a ``-}`` - token. Everything within a comment block is ignored by the parser - and block comments can be nested.--**Expression Statements** are an important and useful part of SGL.-``Expression statements`` are enclosed in curly braces and can contain-any mathematical expression involving doubles, the simulation time -(via the keyword ``TIME``), as well as the values of any variable or -molecule count. The values of time, molecule counts and variables-are evaluated at run time and represent the instantaneous values at the-time at which the expression is evaluated.-``Expressions statements`` can contain any -arithmetic expression involving the standard operators "+", "-", "*", "/", "^" -(exponentiation), and the mathematical functions ``sqrt, exp, log, log2, log10, sin, -cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, acosh, atanh, -erf, erfc, abs``.--Internally, ``expression statements`` are converted into a compute stack-in RPN format which is evaluated at run-time. Even though this-procedure is fairly efficient, there is some numerical overhead-incurred at each iteration and the use of complicated rate -expressions should therefore be avoided if possible.---Below is a list of all SGL blocks available for describing simulations.-Presently, the order of blocks matters and should be exactly the same-in which they are described below. Several SGL blocks are -optional and are marked as such below. --Currently, the SGL specs define the following block types with their -respective block commands and block content:---**parameter block:** ``<block name>`` = *parameters* -- The purpose of the parameter block is to describe the global - simulation parameters. The following parameters are currently- supported:-- *time* = ``Double``- Maximum simulation time in seconds. Default is 0.0 s.-- *outputBuffer* = ``Integer``- Output will be kept in memory and written to the output file and - stdout every *outputBuffer* iterations. Larger values should - result in faster simulations but require more system memory. - Default is to write output every 10000 iterations.-- Note: *outputBuffer* only affects how often output is written to - the output file, not how much output is actually generated during a - simulation (see outputFreq parameter).-- *outputFreq* = ``Integer``- Iteration frequency with which output is generated. Default is every 1000- iterations. Please note that output is written to the output file in batches of- *outputBuffer*.-- *systemVol* = ``Double``- Volume of the simulation system in liters. This is needed to - properly compute the reaction rates in molar units. If rates - should rather be interpreted as reaction propensities (like - in [1]_) please set *systemVol = nil*. Default is a system- volume of 1.0 liter.-- *outputFile* = ``Quoted String``- Name of the output file. This is the only required parameter - in the parameter section. If not given, the simulation will - terminate.-----**variable block:** ``<block name>`` = *variables*-- This block consist of a list of pairs of the form ::-- String = <variable expression>-- where ``String`` is the variable name, and ``<variable expression>``- is either a ``Double`` or an ``expression statement`` as defined above.- Variables can be used in any other ``expression statement`` in the- SGL file including reaction rate definitions. Please make sure to- not define a variable in terms of itself to avoid infinite recursion.---**molecule block:** ``<block name>`` = *molecules*-- This block consist of a list of pairs of the form ::-- String = Integer-- giving the name of each molecule and the number of molecules- present initially. For example, the following molecule definition - block defines molecules ``A`` and ``B`` with initial numbers of - 100 and 200, respectively ::-- def molecules- A = 100- B = 200- end-- **NOTE**: Please do not use any of the predefined mathematical- functions or defined variables (including ``TIME``) as - molecule names since this will lead to undefined behavior.-----**reaction block**: ``<block name>`` = *reactions*-- This block describes the reactions between molecules defined in - the molecule block. Reactions are specified via ::-- <reactants> -> <products> | <rate expression> |-- Here, ``<reactants>`` and ``<products>`` are of the form ::-- Integer String + Integer String + .....-- In this expression, ``String`` is a molecule name - as defined in the molecule block and ``Integer`` an optional - integer specifying the stoichiometry. If ``Integer`` is not - explicitly given, it is assumed to be 1.-- The ``<rate expression>`` can either be a fixed value of type - ``Double`` or an ``expression statement`` as defined above.- - Below is an example reaction block for the two molecules ``A`` and - ``B`` defined above::-- define reactions- 2A + B -> A | 10.0e-5 |- B -> A | {2.0e-5 * A * exp(-0.5*TIME)} |- end- - In the first reaction, 2 ``A`` molecules react with one ``B`` to - yield another ``A`` at a rate of 10.0e-5. The second - reaction describes a decay of ``B`` back to ``A`` at a rate - that is computed based on the instantaneous number of ``A`` - molecules present and which decays exponentially with simulation- time.--- -**event block**: ``<block name>`` = *events*-- An event block allows one to specify events which will occur during - the simulation. Each event consists of a ``<trigger expression>`` and - an associated set of ``<action expressions>``. - Events are specified via ::-- { <trigger expression> } => { <action expression> }-- Here, ``trigger expression`` is of the form ::-- <trigger primitive> [ <boolean operator> <trigger primitive>]-- with ``<trigger primitive>`` defined by ::-- <expression statement> relational operator <expression statement>-- Each ``<trigger primitive>`` contains two ``expression statements``- as defined above and a ``relational operator`` which can be- any of ``>=``, ``<=``, ``==``, ``>``, and ``<``. Hence, each- ``<trigger primitive>`` evaluates to either ``true`` or ``false``.-- Several ``<trigger primitives>`` can be chained together via the - ``<boolean operators>`` ``&&`` and ``||`` to yield a final boolean- value of ``true`` or ``false``.-- If the ``<trigger expression>`` evaluates to true during an- iteration, the associated ``<action expressions>`` is executed - during the same timestep.-- ``<action expression>`` consists of a semi-colon separated list of - assignments ::-- String = <assignment expression> [; String = <assignment expression>]-- - where ``String`` is a molecule or variable name and - ``<expression>`` either a ``Double`` or an ``expression statement``.-- **NOTE**: Since molecule counts are integer values assignments- to molecule counts in ``<action expression>`` will be converted- to an integer value via ``floor``.---**output block**: ``<block name>`` = *output*-- This block consists of a simple list of variable and molecule- names that will be streamed to the output file in the same order::-- [ name1, name2, name3, .... ]----Example Input Files----------------------Below are several example input files detailing the use of SGL:--- `Lotka-Volterra Model <model_files/volterra.sgl>`_-- `Brusselator Model <model_files/brusselator.sgl>`_-- `Oregonator Model <model_files/oregonator.sgl>`_--These are also available in the *Models/* sub-directory in the source tree.---Bugs-------Please report all bugs and feature requests to -<haskelladdict at users dot sourceforge dot net>. ---.. [1] Daniel T. Gillespie (1977). "Exact Stochastic Simulation of Coupled Chemical Reactions". The Journal of Physical Chemistry 81 (25): 2340-2361--.. [2] An exception to this rule are line comments starting with ``--`` which ingnore everything until the next newline.--
simgi.cabal view
@@ -1,8 +1,8 @@ Name: simgi-Version: 0.2+Version: 0.3 License: GPL license-file: COPYING-copyright: (C) 2009 Markus Dittrich+copyright: (C) 2009-2010 Markus Dittrich, NRBSC & CMU category: Scientific Simulation Synopsis: stochastic simulation engine Description: simgi is a stochastic simulation engine to model@@ -16,7 +16,7 @@ extra-source-files: README Executable simgi- Build-Depends: base >= 2 && <= 4, containers >= 0.1.0.0,+ Build-Depends: base >= 2 && < 5, containers >= 0.1.0.0, parsec == 2.1.*, mtl >= 1.1.0.2, haskell98, random >= 1.0.0.1, mersenne-random-pure64 >= 0.2 ghc-options: -O2
src/CommandLine.hs view
@@ -1,6 +1,8 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
src/Engine.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -35,12 +38,12 @@ import Text.Printf import System.Random(randomR) import qualified System.Random.Mersenne.Pure64 as MT-import System.IO -- local imports import ExtraFunctions import GenericModel+import IO import RpnCalc @@ -49,7 +52,7 @@ -- 1) the number of iterations is exhausted -- 2) the current time is > t_max, if t_max is set to -- zero t_max is treated as being infinity -gillespie_driver :: Handle -> Double -> Integer -> ModelState -> IO ()+gillespie_driver :: FileHandle -> Double -> Integer -> ModelState -> IO () gillespie_driver handle simTime dmpIter state = let (output, outState) = runState run_gillespie $ state @@ -58,7 +61,7 @@ in -- write output to console and the output file (write_info $ head reversedOutput)- >> (write_data handle reversedOutput)+ >> (write_to_handle handle reversedOutput) -- next iteration if we're not at the end >> if curTime < simTime@@ -216,12 +219,6 @@ adjust_count aName newCount where- -- NOTE: presently, converting double -> int is done- -- via floor. Is this a good policy (once documented- -- properly)?- to_int :: Double -> Int- to_int = floor - -- adjust either a molecule count or the value of a -- variable adjust_count key val = case M.member key (molSymbols symbols) of@@ -236,13 +233,13 @@ -- | generate a new Output data structure based on the current -- molecule counts generate_output :: Integer -> Integer -> Double -> SymbolTable- -> [String] -> [Output] -> [Output]-generate_output afreq it t symTable outVars outlist + -> [OutputItem] -> [Output] -> [Output]+generate_output afreq it t symTable outItems outlist | mod it afreq /= 0 = outlist | otherwise = new_out:outlist where- currentOutputList = grab_output_data outVars t symTable+ currentOutputList = grab_output_data outItems t it symTable new_out = Output { iteration = it , time = t@@ -254,9 +251,23 @@ -- | given a list of variable or molecule names, goes through the -- symbol table, grabs the current values associated with the variables, -- and returns them as a list-grab_output_data :: [String] -> Double -> SymbolTable -> [Double]-grab_output_data vars aTime symbols = - foldr (\x acc -> (get_val_from_symbolTable x aTime symbols):acc) [] vars+grab_output_data :: [OutputItem] -> Double -> Integer -> SymbolTable + -> [Double]+grab_output_data items aTime iter symbols = + foldr (\x acc -> (get_val x aTime iter symbols):acc) [] items++ where+ get_val x t it syms = + case x of+ Name n -> get_string_value n t it syms+ Expression e -> rpn_compute syms t e+++ get_string_value s t it syms = + case s of+ "TIME" -> t+ "ITERATION" -> fromInteger it+ _ -> get_val_from_symbolTable s t syms @@ -325,7 +336,7 @@ where symbols = SymbolTable initialMols initialVars- initialOutput = grab_output_data outVars 0.0 symbols+ initialOutput = grab_output_data outVars 0.0 0 symbols @@ -349,19 +360,3 @@ --- | basic routine writing the simulation output to the --- file handle corresponding to the output file-write_data :: Handle -> [Output] -> IO ()-write_data _ [] = return ()-write_data handle ((Output {iteration = it, time = t, outputData = out}):xs) = -- let - header = (printf "%-10d %18.15g " it t) :: String- counts = create_count_string out- in- hPutStrLn handle (header ++ counts)- >> write_data handle xs-- where- create_count_string :: [Double] -> String- create_count_string = foldr (\x a -> (printf "%18.15f " x) ++ a) ""
src/ExtraFunctions.hs view
@@ -1,8 +1,11 @@ {-# LANGUAGE ForeignFunctionInterface #-} {----------------------------------------------------------------- - (c) 2008-2009 Markus Dittrich + (c) 2008-2009 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -20,7 +23,7 @@ --------------------------------------------------------------------} -- | definition of additional math and helper functions-module ExtraFunctions ( avogadroNum+module ExtraFunctions ( convert_rate , erf , erfc , fact @@ -29,6 +32,7 @@ , maybe_to_int , maybe_to_positive_int , real_exp + , to_int ) where @@ -38,12 +42,17 @@ import Prelude +-- local imports+import GenericModel (MathExpr(..))+import RpnData (RpnStack(..), RpnItem(..))++--import Debug.Trace+ -- | a few constants avogadroNum :: Double avogadroNum = 6.0221415e23 - -- | use glibc DBL_EPSILON dbl_epsilon :: Double dbl_epsilon = 2.2204460492503131e-16@@ -160,3 +169,29 @@ then d_new else erfc_h n2 num_new d2 denom_new (i+0.5) +++-- | convert reaction propensities into rates if requested+-- by the user. For constants we simply multiply, for+-- rate functions we push the neccessary conversion onto+-- the stack+convert_rate :: MathExpr -> Int -> Double -> MathExpr+convert_rate theConst@(Constant c) order volume =+ case order of+ 1 -> theConst+ _ -> Constant $ c/(avogadroNum * volume)^(order-1)++convert_rate theFunc@(Function stack) order volume =+ case order of+ 1 -> theFunc+ _ -> let mult = 1.0/(avogadroNum * volume)^(order-1) in+ Function . RpnStack $ (toList stack) + ++ [Number mult,BinFunc (*)]+++-- | convert a double to int+-- NOTE: presently, converting double -> int is done+-- via floor. Is this a good policy (once documented+-- properly)?+to_int :: (RealFrac a, Integral b) => a -> b+to_int = floor
src/GenericModel.hs view
@@ -1,6 +1,9 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -30,6 +33,7 @@ , ModelState(..) , MoleculeMap , Output(..)+ , OutputItem(..) , Rate , RateList , Reaction(..)@@ -60,6 +64,12 @@ type MoleculeMap = M.Map String Int +-- | an OutputItem equals one output item and can be+-- an arbitrary function of molecule counts, variables, and+-- simulation time+data OutputItem = Name String | Expression RpnStack++ -- | A VariableMap holds all definied variables and their -- current value. -- NOTE: variables may change their each iteration since@@ -67,6 +77,7 @@ type VariableMap = M.Map String MathExpr + -- | SymbolTable holds all names we know about such as molecule -- names, variable names ... data SymbolTable = SymbolTable { molSymbols :: MoleculeMap@@ -74,11 +85,14 @@ } + -- | generic data type for a mathematical expression. This could -- either be a constant or an expression inside an RpnStack data MathExpr = Constant Double | Function RpnStack+ deriving(Show) + -- | make MathExpr an instance of Eq -- We allow only comparison of constants with each other -- and RPN stacks with each other@@ -89,16 +103,19 @@ _ == _ = False + -- | data type for variable values which are of type MathExpr -- i.e. they can either be a number or a function involving, e.g., -- TIME or molecule counts type VariableValue = Double + -- | data type for reaction rates which are of type MathExpr type Rate = MathExpr + -- | List of reactions and corresponding rates type RateList = [Double] @@ -121,7 +138,6 @@ -- actors: a list of Actors -- react : a list of tuples (i,j) describing that the reaction -- changes the count of molecule i by j --- data Reaction = Reaction { rate :: Rate , actors :: [Actor] , reaction :: [(String,Int)]@@ -200,6 +216,7 @@ data EventTriggerCombinator = AndCombinator | OrCombinator + -- | data type keeping track of possible events occuring during -- the simulation. Each event consist of a --@@ -214,9 +231,10 @@ -- -- changing the value of mol/var by <numerical expression> ---data Event = Event { evtTrigger :: ([EventTriggerPrimitive], [EventTriggerCombinator])- , evtActions :: [EventAction]- }+data Event = + Event { evtTrigger :: ([EventTriggerPrimitive], [EventTriggerCombinator])+ , evtActions :: [EventAction]+ } @@ -234,7 +252,7 @@ , maxTime :: Double , outputBufferSize :: Integer , outputFreq :: Integer- , outputRequest :: [String]+ , outputRequest :: [OutputItem] , outputCache :: [Output] , outfileName :: String , variables :: VariableMap@@ -245,9 +263,9 @@ -- | data structure for keeping track of our output-data Output = Output { iteration :: Integer- , time :: Double- , outputData :: [Double]+data Output = Output { iteration :: Integer+ , time :: Double+ , outputData :: [Double] } deriving(Show)
+ src/IO.hs view
@@ -0,0 +1,76 @@+{-----------------------------------------------------------------+ + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University+ + + This program is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License Version 3 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License Version 3 for more details.+ + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA.++--------------------------------------------------------------------}++-- | IO routines+module IO ( close_handle+ , get_handle+ , write_to_handle+ , FileHandle(..)+ ) where++-- imports+import Prelude+import System.IO+import Text.Printf+++-- local imports+import GenericModel+++-- | our custom Handle type; contains a "real" file handle+-- if the user requested output and otherwise None to indicate+-- that no output is supposed to be generated+data FileHandle = None | RealHandle Handle ++++-- | close file handle if it is real+close_handle :: FileHandle -> IO ()+close_handle h = case h of+ None -> return ()+ RealHandle handle -> hClose handle++++-- | get a file handle if a file name is defined+get_handle :: String -> IO FileHandle+get_handle name = if name /= ""+ then (openFile name WriteMode+ >>= \handle -> return (RealHandle handle) )+ else return None++++-- | basic routine writing the simulation output to the +-- file handle corresponding to the output file+write_to_handle :: FileHandle -> [Output] -> IO ()+write_to_handle _ [] = return ()+write_to_handle None _ = return ()+write_to_handle (RealHandle handle) ((Output {outputData = out}):xs) = ++ let + counts = foldr (\x a -> (printf "%18.15f " x) ++ a) "" out+ in+ hPutStrLn handle counts+ >> write_to_handle (RealHandle handle) xs
src/InputCheck.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -19,7 +22,10 @@ --------------------------------------------------------------------} -- | module responsible for doing some basic input checking-module InputCheck ( check_input ) where+module InputCheck ( check_input + , check_variables_for_cycles+ , check_variables_for_undefs+ ) where -- imports import Control.Monad.Error()@@ -41,20 +47,19 @@ , reactions = theReactions , outputBufferSize = iterCount , outputFreq = outFreq- , outfileName = fileName , variables = theVars , events = theEvents+ , outputRequest = theOutput }) = check_molecules (M.keys theMols) (react_mols theReactions) >> check_positive_outfreq outFreq >> check_positive_itercount iterCount- >> check_filename fileName- >> check_variable_names defined_names- (extract_variable_names (M.elems theVars)) "variables" >> check_variable_names defined_names (extract_variable_names_from_rates theReactions) "reactions" >> check_variable_names defined_names (extract_variable_names_from_events theEvents) "events"+ >> check_variable_names defined_names+ (extract_variable_names_from_output theOutput) "output" where -- | extract all reaction participants@@ -64,8 +69,36 @@ -- | extract all definied names (molecules, variables, ...) defined_names = (M.keys theMols) ++ (M.keys theVars) + +-- | extract all variable and molecule names from the output+-- specs. The way we deal with RpnStacks is a bit clunky+-- (i.e. rewrapping it as a MathExpr) but that way we can+-- re-use extract_variable_names.+-- NOTE: the treatment of the TIME keyword is also a bit inconsistent+-- with the rest of the input format since we presently allow+-- TIME/ITERATION to appear without a expression statements which+-- is not possible when defining variables, rates, ... . Hence,+-- we require a separate String treatment.+extract_variable_names_from_output :: [OutputItem] -> [String]+extract_variable_names_from_output = foldr grab_items [] + where+ grab_items x acc = + case x of+ Name string -> if is_keyword string + then acc+ else (string:acc)++ where+ is_keyword w = case w of+ "TIME" -> True+ "ITERATION" -> True+ _ -> False+ + Expression stack -> (extract_variable_names [Function stack]) ++ acc ++ -- | extract all molecules/variables appearing in reaction rate -- functions extract_variable_names_from_rates :: [Reaction] -> [String]@@ -113,14 +146,6 @@ --- | make sure the user specified an output file name-check_filename :: String -> Either String Bool-check_filename name - | name == "" = Left "Error: Please specify an output file name!"- | otherwise = Right True--- -- | make sure all molecules in reactions are defined check_molecules :: [String] -> [String] -> Either String Bool check_molecules defMols reactMols = @@ -164,3 +189,47 @@ ++ checkType ++ " block do not exist:\n --> " ++ (L.concat $ L.intersperse ", " noMol)++++-- | check a variable map for obvious problems such as circular+-- references and others+check_variables_for_cycles :: VariableMap -> Maybe String+check_variables_for_cycles vmap = + if null cyclicVariables + then Nothing+ else Just $ "Error: circular references for variables \+ \found:" ++ (stringify cyclicVariables)++ where+ stringify = foldr (\x a -> a ++ " " ++ x) ""++ cyclicVariables = foldr check_item [] . M.toList $ vmap++ check_item (_,(Constant _)) acc = acc+ check_item (s,(Function stack)) acc = cycles ++ acc++ where+ cycles = foldr contains [] $ toList stack+ contains x a = case x of+ Variable v -> if v == s+ then (s:a) + else a+ _ -> a+++-- | check if all elements in our variable list are defined +-- we can re-use check_variable_names with only a bit of+-- re-packaging+check_variables_for_undefs :: VariableMap -> Maybe String+check_variables_for_undefs vmap = + case check_variable_names (M.keys vmap) + (extract_variable_names (M.elems vmap)) "variables" of+ Left s -> Just s+ Right _ -> Nothing++++++
src/InputParser.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -34,7 +37,8 @@ -- local imports import ExtraFunctions import GenericModel-import RpnData+import InputCheck(check_variables_for_cycles, check_variables_for_undefs)+import RpnCalc (try_evaluate_expression) import RpnParser -- import Debug.Trace@@ -43,34 +47,53 @@ -- | main parser entry point input_parser :: CharParser ModelState ModelState input_parser = whiteSpace -{- *> many ( choice [ try parse_parameter_def- , try parse_molecule_def- , try parse_reaction_def- , try parse_event_def- ])-}- *> parse_parameter_def- *> optional (try parse_variable_def)- *> parse_molecule_def- *> parse_reaction_def- *> optional (try parse_event_def)- *> optional parse_output_def + *> (many block_parsers) *> eof >> getState <?> "main parser" +-- | parse each of the possible input blocks+block_parsers :: CharParser ModelState ()+block_parsers = parse_variable_def+ <|> parse_parameter_def+ <|> parse_molecule_def+ <|> parse_reaction_def+ <|> parse_event_def+ <|> parse_output_def ++ -- | parser for variable definitions parse_variable_def :: CharParser ModelState ()-parse_variable_def = join ( updateState <$> insert_variables <$>- parse_def_block "variables" (many parse_variable) ) +parse_variable_def = join ( updateState <$> + insert_variables <$>+ parse_def_block "variables" (many parse_variable) )+ *> check_all_vars <?> "variable definition block" where insert_variables :: [(String, MathExpr)] -> ModelState -> ModelState insert_variables theVars state = state { variables = M.fromList theVars } + -- | here we check that all variables can be evaluated (i.e. there are+ -- no self references, all elements are defined and such). + -- NOTE: We have to check our variables at parse time since we evaluate+ -- them during later parsing stages which will fail if they are ill + -- defined.+ check_all_vars :: CharParser ModelState () + check_all_vars = getState >>= \(ModelState {variables = vars}) -> + case check_variables_for_cycles vars of+ Just cycMsg -> fail cycMsg+ Nothing -> ++ case check_variables_for_undefs vars of+ Just undefMsg -> fail undefMsg+ Nothing -> pure ()+++ -- | parser for a single variable definition parse_variable :: CharParser ModelState (String, MathExpr) parse_variable = tuple_it <$> ((try parse_variable_name) )@@ -81,36 +104,78 @@ tuple_it one two = (one, two) + -- | parser for variable name parse_variable_name :: CharParser ModelState String parse_variable_name = identifier <?> "variable name" + -- | parse the definition for a variable+-- NOTE: we can not use parse_function_expression since this+-- will try to simplyfy in terms of the yet to be defined Variables parse_variable_definition :: CharParser ModelState MathExpr parse_variable_definition = (try parse_constant_expression)- <|> (braces parse_function_expression)+ <|> Function <$> (braces parse_infix_to_rpn) <?> "variable value" --- | parser for output definitions++-- | parser for the output block parse_output_def :: CharParser ModelState ()-parse_output_def = join ( updateState <$> insert_output_request <$>- parse_def_block "output" (parse_output_list) ) - <?> "event definitions" +parse_output_def = parse_def_block "output" (many parse_output_specs) + *> pure ()+ <?> "output block" - where- insert_output_request :: [String] -> ModelState -> ModelState- insert_output_request outDataList state = state { outputRequest = outDataList } +-- | parser for the individual output block specifications+parse_output_specs :: CharParser ModelState ()+parse_output_specs = parse_output_list + <|> parse_output_file+ <?> "output specifications"+++ -- | parse the list with variables or molecules to be punched to the -- output file-parse_output_list :: CharParser ModelState [String]-parse_output_list = brackets (commaSep parse_variable_name)+parse_output_list :: CharParser ModelState ()+parse_output_list = join (updateState <$> insert_output_list+-- <$> (brackets (commaSep parse_variable_name)))+ <$> (brackets (commaSep parse_output_item)))+ <?> "output list" + where+ insert_output_list :: [OutputItem] -> ModelState -> ModelState+ insert_output_list outDataList state = state { outputRequest = outDataList } +++-- | parse a single item in a output specifier list+parse_output_item :: CharParser ModelState OutputItem+parse_output_item = (Name <$> parse_variable_name)+ <|> (Expression <$> (braces parse_infix_to_rpn))+ <?> "output list item"++++-- | parse the name of the output file +-- accepts paths but will NOT create any of the parents+parse_output_file :: CharParser ModelState ()+parse_output_file = join (updateState <$> insert_filename+ <$> (reserved "outputFile" *> reservedOp "="+ *> parse_filename ))++ where+ insert_filename aName state = state { outfileName = aName }++++-- | parse a filename+parse_filename :: CharParser ModelState String+parse_filename = stringLiteral+ -- | parser for event definitions parse_event_def :: CharParser ModelState () parse_event_def = join ( updateState <$> insert_events <$>@@ -123,6 +188,7 @@ + -- | parser for individual events parse_events :: CharParser ModelState Event parse_events = Event <$> (parse_trigger) <*> (reservedOp "=>" *> parse_actions)@@ -133,16 +199,19 @@ -- | parser for an event trigger parse_trigger :: CharParser ModelState ([EventTriggerPrimitive], [EventTriggerCombinator])-parse_trigger = braces parse_trigger_expressions+parse_trigger = (try parse_trigger_expressions)+ <|> (parens parse_trigger_expressions) <?> "event trigger block" + -- | parse a list of trigger expressions parse_trigger_expressions :: CharParser ModelState ([EventTriggerPrimitive], [EventTriggerCombinator])-parse_trigger_expressions = combine_it <$> parse_single_trigger_expression - <*> (many parse_boolean_trigger_expression)+parse_trigger_expressions = combine_it + <$> parse_opt_parenthesized_trigger_expression + <*> (many parse_boolean_trigger_expression) <?> "event trigger" where@@ -150,31 +219,40 @@ --- | parse a single trigger expression-parse_single_trigger_expression :: CharParser ModelState EventTriggerPrimitive-parse_single_trigger_expression = - EventTriggerPrimitive <$> parse_infix_to_rpn <*> parse_relational- <*> parse_infix_to_rpn- <?> "single event trigger expression"--- -- | parse a single trigger expression prefixed with a && or || parse_boolean_trigger_expression :: CharParser ModelState (EventTriggerPrimitive, EventTriggerCombinator) parse_boolean_trigger_expression = - tuple_it <$> parse_boolean_combinator <*> parse_single_trigger_expression- <?> "boolean trigger expression"+ tuple_it <$> parse_boolean_combinator + <*> parse_opt_parenthesized_trigger_expression+ <?> "boolean trigger expression" where tuple_it a b = (b,a) +-- | parse a single trigger expression that is either parenthesized or not+parse_opt_parenthesized_trigger_expression :: CharParser ModelState+ EventTriggerPrimitive+parse_opt_parenthesized_trigger_expression = + (try parse_single_trigger_expression) + <|> (parens parse_single_trigger_expression)+ <?> "optionally parenthesized trigger expression"++++-- | parse a single trigger expression+parse_single_trigger_expression :: CharParser ModelState EventTriggerPrimitive+parse_single_trigger_expression = + EventTriggerPrimitive <$> parse_infix_to_rpn <*> parse_relational+ <*> parse_infix_to_rpn+ <?> "single event trigger expression" -- | parse a boolean combinator (&& or ||) parse_boolean_combinator :: CharParser ModelState EventTriggerCombinator parse_boolean_combinator = try parse_AND <|> parse_OR <?> "boolean combinator"+ @@ -185,6 +263,7 @@ + -- | parse an || combinator parse_OR :: CharParser ModelState EventTriggerCombinator parse_OR = symbol "||" *> (pure OrCombinator)@@ -192,6 +271,7 @@ + -- | parse a relational expression and return its associated -- binary function parse_relational :: CharParser ModelState (Double -> Double -> Bool)@@ -206,7 +286,7 @@ -- | parser for an event action parse_actions :: CharParser ModelState [EventAction]-parse_actions = braces parse_action_expressions+parse_actions = brackets parse_action_expressions <?> "event action block" @@ -214,14 +294,16 @@ -- | parser for a list of action expressions parse_action_expressions :: CharParser ModelState [EventAction] parse_action_expressions = - parse_single_action_expression `sepEndBy` semi + parse_single_action_expression `sepEndBy` comma <?> "event action expression" + -- | parser for a single event action expression parse_single_action_expression :: CharParser ModelState EventAction parse_single_action_expression = EventAction <$> - (molname) <*> (reservedOp "=" *> parse_function_expression)+ (molname) <*> (reservedOp "=" *> ((try parse_constant_expression)+ <|> (braces parse_function_expression))) <?> "single event action expression" @@ -236,24 +318,24 @@ -- | parse the individual parameters parse_parameters :: CharParser ModelState ()-parse_parameters = parse_time- <|> parse_outputFile+parse_parameters = parse_time <|> parse_outputBuffer <|> parse_outputFreq <|> parse_systemVol- <?> "time, outputBuffer, systemVol, outputFreq,\- \outputFile"+ <?> "time, outputBuffer, systemVol, outputFreq"+ -- | parse the simulation time specs parse_time :: CharParser ModelState () parse_time = join (updateState <$> insert_time - <$> (reserved "time" *> reservedOp "=" - *> parse_number))+ <$> (reserved "time" *> reservedOp "=" + *> parse_and_simplify_to_constant_expression )) where insert_time t state = state { maxTime = t }+ @@ -261,8 +343,8 @@ parse_systemVol :: CharParser ModelState () parse_systemVol = join (updateState <$> insert_volume <$> (reserved "systemVol" *> reservedOp "="- *> (parse_positive_number- <|> parse_systemVol_nil )))+ *> ( parse_and_simplify_to_constant_expression+ <|> parse_systemVol_nil ))) <?> "system volume" where@@ -274,33 +356,14 @@ --- | parse the name of the output file --- accepts paths but will NOT create any of the parents-parse_outputFile :: CharParser ModelState ()-parse_outputFile = join (updateState <$> insert_filename- <$> (reserved "outputFile" *> reservedOp "="- *> parse_filename ))-- where- insert_filename aName state = state { outfileName = aName }------ | parse a filename-parse_filename :: CharParser ModelState String-parse_filename = stringLiteral---- -- | parse the output iteration specification if present parse_outputBuffer :: CharParser ModelState () parse_outputBuffer = join (updateState <$> insert_outputBuffer <$> (reserved "outputBuffer" *> reservedOp "="- *> integer ))+ *> parse_and_simplify_to_constant_expression )) where- insert_outputBuffer i state = state { outputBufferSize = i }+ insert_outputBuffer i state = state { outputBufferSize = to_int i } @@ -308,10 +371,10 @@ parse_outputFreq :: CharParser ModelState () parse_outputFreq = join (updateState <$> insert_outputFreq <$> (reserved "outputFreq" *> reservedOp "="- *> integer ))+ *> parse_and_simplify_to_constant_expression )) where- insert_outputFreq i state = state { outputFreq = i }+ insert_outputFreq i state = state { outputFreq = to_int i } @@ -330,10 +393,11 @@ -- | parse a molecule name and the number of molecules of this type parse_molecules :: CharParser ModelState (String,Int)-parse_molecules = make_molecule <$> (try molname) <*> (symbol "=" *> integer)+parse_molecules = make_molecule <$> (try molname) + <*> (symbol "=" *> parse_and_simplify_to_constant_expression) <?> "molecule expression" where- make_molecule mol aCount = (mol,fromInteger aCount)+ make_molecule mol aCount = (mol, to_int aCount) -- | parser for a molecule name @@ -384,24 +448,7 @@ } - -- | convert reaction propensities into rates if requested- -- by the user. For constants we simply multiply, for- -- rate functions we push the neccessary conversion onto- -- the stack- convert_rate theConst@(Constant c) order volume =- case order of- 1 -> theConst- _ -> Constant $ c/(avogadroNum * volume^(order-1)) - convert_rate theFunc@(Function stack) order volume =- case order of- 1 -> theFunc- _ -> let mult = 1.0/(avogadroNum * volume^(order-1)) in- Function . RpnStack $ (toList stack) - ++ [Number mult,BinFunc (*)]--- -- | create the list holding the molecule number changes for -- this reactioni. If the net change in molecule number is -- zero ( a nop) we remove the action.@@ -484,7 +531,7 @@ -> CharParser ModelState a parse_def_block blockName parser = - between (reserved "def" *> reserved blockName )+ between (reserved blockName ) (reserved "end") (parser) <?> "parameter definitions"@@ -501,8 +548,6 @@ <|> (lineToken (braces parse_function_expression)) <?> "constant or function expression" - where- lineToken = between (symbol "|") (symbol "|") -- | parser for a simple rate constant expression@@ -512,9 +557,35 @@ --- | parser for a rate function+-- | parser for function expressions+-- NOTE: We are trying to simplify expressions based on defined+-- variables parse_function_expression :: CharParser ModelState MathExpr-parse_function_expression = Function <$> parse_infix_to_rpn+parse_function_expression = optimize_if_possible <$> parse_infix_to_rpn + <*> (getState + >>= \(ModelState { variables = vars })+ -> pure vars ) <?> "rate function" + + where+ optimize_if_possible x vars = case try_evaluate_expression x vars of + Right val -> Constant val+ Left func -> Function func+ +-- | parser for either a constant or an expression statement that can be+-- simplified to constant. After parsing we simplify any expression statement +-- to a constant (this should be that case for all variables.+parse_and_simplify_to_constant_expression :: CharParser ModelState Double+parse_and_simplify_to_constant_expression =+ join ( try_convert <$> ( parse_constant_expression + <|> (braces parse_function_expression) ))+ <?> "evaluate math expression"++ where+ try_convert x = + case x of + Constant c -> return c+ _ -> fail "Error: unknown variable, \+ \expression could not be evaluated."
src/Messages.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -18,7 +21,7 @@ --------------------------------------------------------------------} --- | main gsim driver+-- | message routines used in simgi module Messages ( show_version , startup_message , usage@@ -35,7 +38,7 @@ -- | show version info show_version :: IO ()-show_version = putStrLn "This is simgi v0.2 (C) 2009 Markus Dittrich"+show_version = putStrLn "This is simgi v0.3 (c) 2009-2010 Markus Dittrich" @@ -65,7 +68,7 @@ -- for nil volumes we want to display nil not -1.0 finalSimVol = if (simVol < 0) then "nil"- else (show simVol) ++ " m^3"+ else (show simVol) ++ " dm^3" -- | provide brief usage info
src/PrettyPrint.hs view
@@ -1,6 +1,9 @@ {----------------------------------------------------------------- - (c) 2008-2009 Markus Dittrich + (c) 2008-2009 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
src/RpnCalc.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -21,8 +24,9 @@ -- | RpnCalc defines the data structures and a calculator engine -- for computing mathematical expressions that have been parsed -- into reverse polish notations-module RpnCalc ( rpn_compute- , get_val_from_symbolTable +module RpnCalc ( get_val_from_symbolTable + , rpn_compute+ , try_evaluate_expression ) where @@ -34,7 +38,6 @@ import GenericModel import RpnData --- import Debug.Trace -- | computes an expressions based on an rpn stack -- molecule names are looked up in a MoleculeMap@@ -56,11 +59,12 @@ evaluate ((Number x):(Number y):ys) (BinFunc f) = (Number $ f y x):ys - -- extrace current time+ -- extract current time evaluate ys (Time) = (Number theTime):ys -- extract molecule variable- evaluate ys (Variable x) = (Number $ get_val_from_symbolTable x theTime symbols):ys + evaluate ys (Variable x) = + (Number $ get_val_from_symbolTable x theTime symbols):ys evaluate ys item = item:ys @@ -75,3 +79,32 @@ Nothing -> case (M.!) (varSymbols symbols) var of Constant c -> c Function s -> rpn_compute symbols aTime s++++-- | try to evaluate an RPN stack and return the result as a Double+-- if we can evaluate it during parse-time (i.e. if it doesn't contain+-- things like time and molecule count)+-- NOTE: We do _not_ want to substitute any molecule counts even+-- if we should now them; molecule counts are inherently dynamic+-- and need to be evaluated at run-time+try_evaluate_expression :: RpnStack -> VariableMap -> Either RpnStack Double+try_evaluate_expression stack varMap = ++ if can_evaluate stack + then+ Right $ rpn_compute (SymbolTable M.empty varMap) 0.0 stack + else+ Left stack++ where++ can_evaluate = null . filter unknown_element . toList + where+ unknown_element x = case x of+ Time -> True+ Variable v -> if v `elem` M.keys varMap+ then False+ else True+ _ -> False+
src/RpnData.hs view
@@ -1,6 +1,6 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -42,7 +42,7 @@ -- | RpnStack describes a computation stored in a stack of -- RpnItems newtype RpnStack = RpnStack { toList :: [RpnItem] }-+ deriving(Show) -- | make RpnStack an instance of Eq. -- We compare two RpnStacks by computing them and replacing@@ -81,8 +81,8 @@ -- extrace current time evaluate ys (Time) = (Number defaultVar):ys - -- extract molecule variable- evaluate ys (Variable x) = (Number defaultVar):ys+ -- extract variable name+ evaluate ys (Variable _) = (Number defaultVar):ys evaluate ys item = item:ys
src/RpnParser.hs view
@@ -1,6 +1,6 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
src/TokenParser.hs view
@@ -31,6 +31,7 @@ , float , identifier , integer+ , lineToken , parens , keywords , lexer@@ -106,10 +107,9 @@ -- | all other keywords that are not regular functions keywords :: [String]-keywords = [ "def", "molecules", "reactions", "time", "outputIter"- , "nil", "outputFreq", "outputFile", "systemVol", "seed"- , "end", "variables", "time"- ]+keywords = [ "end", "events", "molecules", "output", "outputBuffer"+ , "outputFile", "outputFreq", "parameters", "molecules", "reactions"+ , "systemVol", "time", "variables"] operators :: [String] operators = ["+", "->", "::", "=", "{", "}", ">=", "==", "<="@@ -126,6 +126,12 @@ ++ map fst builtinFunctions } ) +++-- | parser for parser sandwitched between line+-- symbols '|'+lineToken :: CharParser st a -> CharParser st a+lineToken = between (symbol "|") (symbol "|") -- | token parser for parenthesis
src/simgi.hs view
@@ -1,6 +1,6 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -23,8 +23,6 @@ -- imports import Prelude-import System.IO---import System.Random import System.Environment -- local imports@@ -32,6 +30,7 @@ import Engine import InputCheck import InputParser+import IO import Messages import TokenParser @@ -74,8 +73,7 @@ outFile = outfileName parsedState in - -- open output file- openFile outFile WriteMode + get_handle outFile >>= \handle -> -- print initial startup info@@ -85,6 +83,4 @@ >> gillespie_driver handle totalTime dataDumpIter initialState - -- close output file- >> hClose handle-+ >> close_handle handle
test/Makefile view
@@ -3,37 +3,47 @@ default: check -.PHONY: check check_event_parser check_rpnstack check_reversible \- check_reaction_parser check_irreversible clean +.PHONY: check check_event_parser check_rpnstack check_reversible_bimol \+ check_reversible_trimol check_irreversible_trimol \+ check_reaction_parser check_irreversible_bimol clean check_rpnstack: make -C $@ +check_reversible_bimol: helpers+ make -C $@ -check_reversible:+check_reversible_trimol: helpers make -C $@ -check_irreversible:+check_irreversible_bimol: make -C $@ +check_irreversible_trimol:+ make -C $@ + check_event_parser: make -C $@ - check_reaction_parser: make -C $@ check: check_rpnstack check_event_parser check_reaction_parser \- check_reversible check_irreversible -+ check_reversible_bimol check_irreversible_bimol \+ check_reversible_trimol check_irreversible_trimol +helpers:+ make -C test_helpers clean: make -C check_rpnstack clean- make -C check_reversible clean- make -C check_irreversible clean+ make -C check_reversible_bimol clean+ make -C check_reversible_trimol clean+ make -C check_irreversible_bimol clean+ make -C check_irreversible_trimol clean make -C check_event_parser clean make -C check_reaction_parser clean+ make -C test_helpers clean
test/check_event_parser/EventParserTest.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -31,7 +34,7 @@ -- local imports import Engine-import GenericModel+import GenericModel() import PrettyPrint import InputParser import TestHelpers@@ -63,61 +66,61 @@ --- NOTE: for now we simply test if parsing succeeds simpleEventParseTests :: [TestCase] simpleEventParseTests = - [ ("{ z == 100 } => { x = x }", + [ ("z == 100 => [ x = {x} ]", (True, M.fromList [("x",1000),("y",2000),("z",100)])) - , ("{ z== 100} => { x = x+y; y = y+1 }", + , ("( z== 100) => [ x = {x+y}, y = {y+1} ]", (True, M.fromList [("x",3000),("y",2001),("z",100)])) - , ("{z==121 } => { y=10 }", + , ("(z==121 ) => [ y=10 ]", (False, M.fromList [("x",1000),("y",10),("z",100)])) - , ("{z==101} => { x = x/2.0 }", + , ("(z==101) => [ x = {x/2.0} ]}", (False, M.fromList [("x",500),("y",2000),("z",100)])) - , ("{ z == 100}=>{ z= 121; x = 500; y=2000;}", + , ("z == 100=>[ z= 121, x = 500, y=2000,]", (True, M.fromList [("x",500),("y",2000),("z",121)])) - , ("{ y >= 121 }=>{z=1050}", + , ("( y >= 121 )=>[z=1050]", (True, M.fromList [("x",1000),("y",2000),("z",1050)])) - , ("{ z <= 100} => { x= sqrt(4)*100; y = x^2/10}", + , ("( z <= 100) => [ x= {sqrt(4)*100}, y = {x^2/10}]", (True, M.fromList [("x",200),("y",4000),("z",100)])) - , ("{ x >= 100} => { z= z; z = 2*z; z = 3*z;}", + , ("x >= 100 => [ z= {z}, z = {2*z}, z = {3*z },]", (True, M.fromList [("x",1000),("y",2000),("z",600)])) - , ("{ z < 100} => { x= 10; y = z}", + , ("z < 100 => [ x= 10, y = {z}]", (False, M.fromList [("x",10),("y",100),("z",100)])) - , ("{ x > 100} => { y= x+z}", + , ("(( x > 100)) => [ y= {x+z}]", (True, M.fromList [("x",1000),("y",1100),("z",100)])) - , ("{ y == 2000 } => { x=1001 }", + , ("y == 2000 => [ x=1001 ]", (True, M.fromList [("x",1001),("y",2000),("z",100)])) - , ("{ z <= 302 } => { x = 10; y = 10; z= 200; z=10 }", + , ("z <= 302 => [ x = 10, y = 10, z= 200, z=10 ]", (True, M.fromList [("x",10),("y",10),("z",10)])) - , ("{ y == 100 } => { x = 10; y = 20; }", + , ("( y == 100 ) => [ x = 10, y = 20, ]", (False, M.fromList [("x",10),("y",20),("z",100)])) - , ("{ z == 100 } => { x = 10; y = 20 }", + , ("( z == 100 )=> [ x = 10, y = 20 ]", (True, M.fromList [("x",10),("y",20),("z",100)])) - , ("{ z == 100 } => { x = 10; y = 20 + z }", + , ("((z == 100 ) )=> [ x = 10, y = {20 + z }]", (True, M.fromList [("x",10),("y",120),("z",100)])) - , ("{ x > 100 } => { x = 10*x+y; y = 20+z^2 }", + , ("x > 100 => [ x = {10*x+y}, y = {20+z^2} ]", (True, M.fromList [("x",12000),("y",10020),("z",100)])) - , ("{ z == 100 } => { x = 1e6*exp(-TIME); y = x; }",+ , ("z == 100 => [ x = {1e6*exp(-TIME)}, y = {x}, ]", (True, M.fromList [("x",4),("y",4),("z",100)])) - , ("{ y == 100 } => { x = 2; x = y^x; y = x*exp(-TIME) }", + , ("( y == 100 ) => [ x = 2, x = {y^x}, y ={ x*exp(-TIME)} ]", (False, M.fromList [("x",4000000),("y",17),("z",100)])) - , ("{ z == 100 } => { x = 10+z; y = sqrt(log((x^2))); }",+ , ("( z == 100 ) => [ x = {10+z}, y = {sqrt(log((x^2)))}, ]", (True, M.fromList [("x",110),("y",3),("z",100)])) ] @@ -147,7 +150,7 @@ -- | main test driver main :: IO ()-main = putStrLn "\n\n\nTesting Input Parser"+main = putStrLn "\n****** Testing Input Parser ******" -- check event parser >> (putStr $ color_string Cyan "\nEvent parse tests:\n")
test/check_event_parser/Makefile view
@@ -6,8 +6,8 @@ .PHONY: check clean check:- ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) -i$(HELPER_LOCATION) \- --make EventParserTest.hs+ @ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) -i$(HELPER_LOCATION) \+ --make EventParserTest.hs >& /dev/null @./EventParserTest
− test/check_irreversible/Makefile
@@ -1,19 +0,0 @@-include ../test_helpers/make_common---default: check--.PHONY: check clean-check:- @echo- @echo "Running irreversible reaction test 1"- @echo "This may take a while ...."- @./run_test.1.sh $(SIMGI_PATH)- @echo "Running irreversible reaction test 2"- @echo "This may take a while ...."- @./run_test.2.sh $(SIMGI_PATH)- @echo---clean:- rm -f *.dat
− test/check_irreversible/irreversible.1.sgl
@@ -1,22 +0,0 @@--def parameters- time = 1.0- systemVol = 1.25e-19 - outputBuffer = 50000 - outputFreq = 100- outputFile = "irreversible.1.dat"-end--def molecules- a = 1000- b = 1000- c = 0-end--def reactions- a + b -> c | 1e6 |-end --def output- [a, b, c]-end
− test/check_irreversible/irreversible.2.sgl
@@ -1,22 +0,0 @@--def parameters- time = 1.0- systemVol = 1.25e-19 - outputBuffer = 50000 - outputFreq = 100- outputFile = "irreversible.2.dat"-end--def molecules- a = 1000- b = 1000- c = 0-end--def reactions- b -> c | 1e6 |-end --def output- [a, b, c]-end
− test/check_irreversible/run_test.1.sh
@@ -1,60 +0,0 @@-#!/bin/bash-#-# short wrapper for runing a number of reversible-# simulations and then checking if we can reproduce-# the correct average product concentration-#--# expected values of molecule counts-a_expect=0.000000000000000-b_expect=0.000000000000000-c_expect=1000.000000000000000--# -simgi_exe="${1}"--# our global status-status=0--for ((counter=0; counter <= 100; counter++)); do-- # provide a little "progressbar"- printf "."-- # run and process- ${simgi_exe} irreversible.1.sgl >& /dev/null -- a=$(tail -n 1 irreversible.1.dat | gawk ' { print $3 }')- b=$(tail -n 1 irreversible.1.dat | gawk ' { print $4 }')- c=$(tail -n 1 irreversible.1.dat | gawk ' { print $5 }')-- if [[ ${a_expect} != ${a} || ${b_expect} != ${b} \- || ${c_expect} != ${c} ]];- then- status=1- fi-- # unlink- rm -f irreversible.1.dat || return 1- -done--# check if all the tests passed--# brief output-if [[ ${status} == 0 ]]; then- echo- echo- echo "Congratulations - the irreversible reaction test 1 passed!"- echo- echo-else- echo- echo- echo "Error - the irreversible reaction test failed. Please check!"- echo- echo-fi--# return status of deviation check-exit ${status}
− test/check_irreversible/run_test.2.sh
@@ -1,60 +0,0 @@-#!/bin/bash-#-# short wrapper for runing a number of reversible-# simulations and then checking if we can reproduce-# the correct average product concentration-#--# expected values of molecule counts-a_expect=1000.000000000000000-b_expect=0.000000000000000-c_expect=1000.000000000000000--# -simgi_exe="${1}"--# our global status-status=0--for ((counter=0; counter <= 100; counter++)); do-- # provide a little "progressbar"- printf "."-- # run and process- ${simgi_exe} irreversible.2.sgl >& /dev/null -- a=$(tail -n 1 irreversible.2.dat | gawk ' { print $3 }')- b=$(tail -n 1 irreversible.2.dat | gawk ' { print $4 }')- c=$(tail -n 1 irreversible.2.dat | gawk ' { print $5 }')-- if [[ ${a_expect} != ${a} || ${b_expect} != ${b} \- || ${c_expect} != ${c} ]];- then- status=1- fi-- # unlink- rm -f irreversible.2.dat || return 1- -done--# check if all the tests passed--# brief output-if [[ ${status} == 0 ]]; then- echo- echo- echo "Congratulations - the irreversible reaction test 2 passed!"- echo- echo-else- echo- echo- echo "Error - the irreversible reaction test failed. Please check!"- echo- echo-fi--# return status of deviation check-exit ${status}
+ test/check_irreversible_bimol/Makefile view
@@ -0,0 +1,17 @@+include ../test_helpers/make_common+++default: check++.PHONY: check clean+check:+ @echo+ @echo "****** Running irreversible bimolecular reaction test 1 ******"+ @./run_test.1.sh $(SIMGI_PATH)+ @echo "****** Running irreversible bimolecular reaction test 2 ******" + @./run_test.2.sh $(SIMGI_PATH)+ @echo+++clean:+ rm -f *.dat
+ test/check_irreversible_bimol/irreversible_bimol.1.sgl view
@@ -0,0 +1,21 @@+parameters+ time = 1.0+ systemVol = 1.25e-19 + outputBuffer = 50000 + outputFreq = 100+end++molecules+ a = 1000+ b = 1000+ c = 0+end++reactions+ a + b -> c | 1e6 |+end ++output+ outputFile = "irreversible_bimol.1.dat"+ [TIME, ITERATION, a, b, c]+end
+ test/check_irreversible_bimol/irreversible_bimol.2.sgl view
@@ -0,0 +1,21 @@+parameters+ time = 1.0+ systemVol = 1.25e-19 + outputBuffer = 50000 + outputFreq = 100+end++molecules+ a = 1000+ b = 1000+ c = 0+end++reactions+ b -> c | 1e6 |+end ++output+ [TIME, ITERATION, a, b, c]+ outputFile = "irreversible_bimol.2.dat"+end
+ test/check_irreversible_bimol/run_test.1.sh view
@@ -0,0 +1,63 @@+#!/bin/bash+#+# short wrapper for runing a number of reversible+# simulations and then checking if we can reproduce+# the correct average product concentration+#++# expected values of molecule counts+a_expect=0.0+b_expect=0.0+c_expect=1000.0++# +simgi_exe="${1}"++# our global status+status=0++for ((counter=0; counter <= 100; counter++)); do++ # provide a little "progressbar"+ printf "."++ # run and process+ ${simgi_exe} irreversible_bimol.1.sgl >& /dev/null ++ a=$(tail -n 1 irreversible_bimol.1.dat | gawk ' { print $3 }')+ b=$(tail -n 1 irreversible_bimol.1.dat | gawk ' { print $4 }')+ c=$(tail -n 1 irreversible_bimol.1.dat | gawk ' { print $5 }')++ result_a=$(echo "${a} == ${a_expect}" | bc)+ result_b=$(echo "${b} == ${b_expect}" | bc)+ result_c=$(echo "${c} == ${c_expect}" | bc)++ if [[ ${result_a} == 0 || ${result_b} == 0 || ${result_c} == 0 ]];+ then+ status=1+ fi++ # unlink+ rm -f irreversible_bimol.1.dat || return 1+ +done++# check if all the tests passed++# brief output+if [[ ${status} == 0 ]]; then+ echo+ echo+ echo "Congratulations - the irreversible reaction test 1 passed!"+ echo+ echo+else+ echo+ echo+ echo "Error - the irreversible reaction test failed. Please check!"+ echo+ echo+fi++# return status of deviation check+exit ${status}
+ test/check_irreversible_bimol/run_test.2.sh view
@@ -0,0 +1,63 @@+#!/bin/bash+#+# short wrapper for runing a number of reversible+# simulations and then checking if we can reproduce+# the correct average product concentration+#++# expected values of molecule counts+a_expect=1000.000000000000000+b_expect=0.000000000000000+c_expect=1000.000000000000000++# +simgi_exe="${1}"++# our global status+status=0++for ((counter=0; counter <= 100; counter++)); do++ # provide a little "progressbar"+ printf "."++ # run and process+ ${simgi_exe} irreversible_bimol.2.sgl >& /dev/null ++ a=$(tail -n 1 irreversible_bimol.2.dat | gawk ' { print $3 }')+ b=$(tail -n 1 irreversible_bimol.2.dat | gawk ' { print $4 }')+ c=$(tail -n 1 irreversible_bimol.2.dat | gawk ' { print $5 }')++ result_a=$(echo "${a} == ${a_expect}" | bc)+ result_b=$(echo "${b} == ${b_expect}" | bc)+ result_c=$(echo "${c} == ${c_expect}" | bc)++ if [[ ${result_a} == 0 || ${result_b} == 0 || ${result_c} == 0 ]];+ then+ status=1+ fi++ # unlink+ rm -f irreversible_bimol.2.dat || return 1+ +done++# check if all the tests passed++# brief output+if [[ ${status} == 0 ]]; then+ echo+ echo+ echo "Congratulations - the irreversible reaction test 2 passed!"+ echo+ echo+else+ echo+ echo+ echo "Error - the irreversible reaction test failed. Please check!"+ echo+ echo+fi++# return status of deviation check+exit ${status}
+ test/check_irreversible_trimol/Makefile view
@@ -0,0 +1,17 @@+include ../test_helpers/make_common+++default: check++.PHONY: check clean+check:+ @echo+ @echo "****** Running irreversible trimolecular reaction test 1 ******"+ @./run_test.1.sh $(SIMGI_PATH)+ @echo "****** Running irreversible trimolecular reaction test 2 ******" + @./run_test.2.sh $(SIMGI_PATH)+ @echo+++clean:+ rm -f *.dat
+ test/check_irreversible_trimol/irreversible_trimol.1.sgl view
@@ -0,0 +1,38 @@+{-----------------------------------------------------++ this is the input deck for a simple 3 way reaction+ (C) 2010 Markus Dittrich++------------------------------------------------------}++variables+ Na = 6.022e23+ myConc = 50e-6+ cubeVol_um = 0.05+ cubeVol = { cubeVol_um * 1e-15 }+ myMol = { myConc * cubeVol } + myRelease = { myMol * Na }+end++parameters+ time = 100000.0+ outputBuffer = 1 + outputFreq = 1+ systemVol = { cubeVol }+end++molecules+ A = { myRelease }+ B = { myRelease }+ C = { myRelease }+ D = 0+end++reactions+ A + B + C -> D | 1e11 |+end++output+ outputFile = "irreversible_trimol.1.dat"+ [A,B,C,D]+end
+ test/check_irreversible_trimol/irreversible_trimol.2.sgl view
@@ -0,0 +1,38 @@+{-----------------------------------------------------++ this is the input deck for a simple 3 way reaction+ (C) 2010 Markus Dittrich++------------------------------------------------------}++variables+ Na = 6.022e23+ myConc = 30e-6+ cubeVol_um = 0.05+ cubeVol = { cubeVol_um * 1e-15 }+ myMol = { myConc * cubeVol } + myRelease = { myMol * Na }+end++parameters+ time = 100000.0+ outputBuffer = 1 + outputFreq = 1+ systemVol = { cubeVol }+end++molecules+ A = { myRelease }+ B = { myRelease }+ C = { myRelease }+ D = 0+end++reactions+ A + B + C -> D | 1e11 |+end++output+ outputFile = "irreversible_trimol.2.dat"+ [A,B,C,D]+end
+ test/check_irreversible_trimol/run_test.1.sh view
@@ -0,0 +1,67 @@+#!/bin/bash+#+# short wrapper for runing a number of reversible+# simulations and then checking if we can reproduce+# the correct average product concentration+#++# expected values of molecule counts+a_expect=0.0+b_expect=0.0+c_expect=0.0+d_expect=1505.000000000000000++# +simgi_exe="${1}"++# our global status+status=0++for ((counter=0; counter <= 100; counter++)); do++ # provide a little "progressbar"+ printf "."++ # run and process+ ${simgi_exe} irreversible_trimol.1.sgl >& /dev/null ++ a=$(tail -n 1 irreversible_trimol.1.dat | gawk ' { print $1 }')+ b=$(tail -n 1 irreversible_trimol.1.dat | gawk ' { print $2 }')+ c=$(tail -n 1 irreversible_trimol.1.dat | gawk ' { print $3 }')+ d=$(tail -n 1 irreversible_trimol.1.dat | gawk ' { print $4 }')++ result_a=$(echo "${a} == ${a_expect}" | bc)+ result_b=$(echo "${b} == ${b_expect}" | bc)+ result_c=$(echo "${c} == ${c_expect}" | bc)+ result_d=$(echo "${d} == ${d_expect}" | bc)++ if [[ ${result_a} == 0 || ${result_b} == 0 || ${result_c} == 0 \+ || ${result_d} == 0 ]];+ then+ status=1+ fi++ # unlink+ rm -f irreversible_trimol.1.dat || return 1+ +done++# check if all the tests passed++# brief output+if [[ ${status} == 0 ]]; then+ echo+ echo+ echo "Congratulations - the irreversible reaction test 1 passed!"+ echo+ echo+else+ echo+ echo+ echo "Error - the irreversible reaction test failed. Please check!"+ echo+ echo+fi++# return status of deviation check+exit ${status}
+ test/check_irreversible_trimol/run_test.2.sh view
@@ -0,0 +1,67 @@+#!/bin/bash+#+# short wrapper for runing a number of reversible+# simulations and then checking if we can reproduce+# the correct average product concentration+#++# expected values of molecule counts+a_expect=0.0+b_expect=0.0+c_expect=0.0+d_expect=903.000000000000000++# +simgi_exe="${1}"++# our global status+status=0++for ((counter=0; counter <= 100; counter++)); do++ # provide a little "progressbar"+ printf "."++ # run and process+ ${simgi_exe} irreversible_trimol.2.sgl >& /dev/null ++ a=$(tail -n 1 irreversible_trimol.2.dat | gawk ' { print $1 }')+ b=$(tail -n 1 irreversible_trimol.2.dat | gawk ' { print $2 }')+ c=$(tail -n 1 irreversible_trimol.2.dat | gawk ' { print $3 }')+ d=$(tail -n 1 irreversible_trimol.2.dat | gawk ' { print $4 }')++ result_a=$(echo "${a} == ${a_expect}" | bc)+ result_b=$(echo "${b} == ${b_expect}" | bc)+ result_c=$(echo "${c} == ${c_expect}" | bc)+ result_d=$(echo "${d} == ${d_expect}" | bc)++ if [[ ${result_a} == 0 || ${result_b} == 0 || ${result_c} == 0 \+ || ${result_d} == 0 ]];+ then+ status=1+ fi++ # unlink+ rm -f irreversible_trimol.2.dat || return 1+ +done++# check if all the tests passed++# brief output+if [[ ${status} == 0 ]]; then+ echo+ echo+ echo "Congratulations - the irreversible reaction test 1 passed!"+ echo+ echo+else+ echo+ echo+ echo "Error - the irreversible reaction test failed. Please check!"+ echo+ echo+fi++# return status of deviation check+exit ${status}
test/check_reaction_parser/Makefile view
@@ -6,8 +6,8 @@ .PHONY: check clean check:- ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) -i$(HELPER_LOCATION) \- --make ReactionParserTest.hs+ @ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) -i$(HELPER_LOCATION) \+ --make ReactionParserTest.hs >& /dev/null @./ReactionParserTest
test/check_reaction_parser/ReactionParserTest.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -115,7 +118,8 @@ [("x",1),("y",1),("z",1)]) , ("nil -> nil |{ sqrt(2.0) } |",- Reaction (Function . RpnStack $ [Number 2.0, UnaFunc sqrt])+ -- Reaction (Function . RpnStack $ [Number 2.0, UnaFunc sqrt])+ Reaction (Constant 1.4142135623730951) [] []) ]@@ -147,7 +151,7 @@ -- | main test driver main :: IO ()-main = putStrLn "\n\n\nTesting Reaction Parser"+main = putStrLn "\n****** Testing Reaction Parser ******" -- check event parser >> (putStr $ color_string Cyan "\nReaction parse tests:\n")
− test/check_reversible/Makefile
@@ -1,19 +0,0 @@-include ../test_helpers/make_common---default: check--.PHONY: check clean-check:- ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) --make check_deviation.hs- ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) --make average.hs- @echo- @echo "Running reversible reaction test."- @echo "This may take a while ...."- @./run_test.sh $(SIMGI_PATH)- @echo- --clean:- rm -f *.hi *.o check_deviation average reversible.dat \- simgi.*
− test/check_reversible/average.hs
@@ -1,38 +0,0 @@-{------------------------------------------------------------------ - (c) 2009 Markus Dittrich - - This program is free software; you can redistribute it - and/or modify it under the terms of the GNU General Public - License Version 3 as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful,- but WITHOUT ANY WARRANTY; without even the implied warranty of- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the- GNU General Public License Version 3 for more details.- - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA.----------------------------------------------------------------------}---- | short helper script for averaging a file containing a single--- column of doubles-module Main where----- imports-import Prelude---main :: IO ()-main = getContents- >>= \content -> - let- items = map (read) . lines $ content :: [Double]- theSum = foldr (+) 0 items- average = theSum/(fromIntegral . length $ items)- in- putStrLn (show average)
− test/check_reversible/check_deviation.hs
@@ -1,46 +0,0 @@-{------------------------------------------------------------------ - (c) 2009 Markus Dittrich - - This program is free software; you can redistribute it - and/or modify it under the terms of the GNU General Public - License Version 3 as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful,- but WITHOUT ANY WARRANTY; without even the implied warranty of- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the- GNU General Public License Version 3 for more details.- - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA.----------------------------------------------------------------------}---- | short helper script for averaging a file containing a single--- column of doubles-module Main where---- imports-import Prelude-import System-import System.Environment---main :: IO Int-main = getArgs - >>= \(name:value:tol:_) -> readFile name- >>= \content -> - let- items = map (read) . lines $ content :: [Double]- theSum = foldr (+) 0 items- average = theSum/(fromIntegral . length $ items)- expected = read value :: Double- tolerance = read tol :: Double- deviation = abs((average - expected)/expected)- in- if ( deviation < tolerance )- then exitWith ExitSuccess- else exitWith $ ExitFailure 1-
− test/check_reversible/reversible.sgl
@@ -1,29 +0,0 @@-{------------------------------------------------------- this is the input deck for the oregonator model - (C) 2009 Markus Dittrich--------------------------------------------------------}--def parameters- time = 1.0e-4- systemVol = 1.25e-19- outputBuffer = 50000- outputFreq = 10- outputFile = "reversible.dat"-end--def molecules- a = 1000- b = 1000- c = 0-end--def reactions- a + b -> c | {1e6*10} |- c -> a + b | 1e5 |-end--def output- [a, b, c]-end
− test/check_reversible/run_test.sh
@@ -1,53 +0,0 @@-#!/bin/bash-#-# short wrapper for runing a number of reversible-# simulations and then checking if we can reproduce-# the correct average product concentration-#--# -simgi_exe="${1}"--# create a global tempfile to collect the data-globalFile=$(mktemp simgi.XXXXXXXXXXXXX)--for ((counter=0; counter <= 100; counter++)); do-- # provide a little "progressbar"- printf "."-- # run and process- ${simgi_exe} -s ${counter} reversible.sgl >& /dev/null - tail -n 400 reversible.dat | gawk ' { print $5}' | ./average >> ${globalFile} || return 1-- # unlink- rm -f reversible.dat || return 1- -done--# check if we're within the specs-# the expected number of products is 430.643462709951-# and we allow 0.5% tolerance-./check_deviation ${globalFile} 430.643462709951 5e-3-status=$?--# brief output-if [[ ${status} == 0 ]]; then- echo- echo- echo "Congratulations - the reversible reaction test passed!"- echo- echo-else- echo- echo- echo "Error - the reversible reaction test failed. Please check!"- echo- echo-fi--# remove files-rm -f ${globalFile}--# return status of deviation check-exit ${status}
+ test/check_reversible_bimol/Makefile view
@@ -0,0 +1,16 @@+include ../test_helpers/make_common+++default: check++.PHONY: check clean+check:+ @echo+ @echo "****** Running reversible bimolecular reaction test ******"+ @./run_test.sh $(SIMGI_PATH)+ @echo+ ++clean:+ rm -f *.hi *.o check_deviation average reversible.dat \+ simgi.*
+ test/check_reversible_bimol/reversible_bimol.sgl view
@@ -0,0 +1,29 @@+{-----------------------------------------------------++ this is the input deck for the oregonator model + (C) 2009 Markus Dittrich++------------------------------------------------------}++parameters+ time = 1.0e-4+ systemVol = 1.25e-19+ outputBuffer = 50000+ outputFreq = 10+end++molecules+ a = 1000+ b = 1000+ c = 0+end++reactions+ a + b -> c | {1e6*10} |+ c -> a + b | 1e5 |+end++output+ [ITERATION, TIME, a, b, c]+ outputFile = "reversible_bimol.dat"+end
+ test/check_reversible_bimol/run_test.sh view
@@ -0,0 +1,53 @@+#!/bin/bash+#+# short wrapper for runing a number of reversible+# simulations and then checking if we can reproduce+# the correct average product concentration+#++# +simgi_exe="${1}"++# create a global tempfile to collect the data+globalFile=$(mktemp simgi.XXXXXXXXXXXXX)++for ((counter=0; counter <= 100; counter++)); do++ # provide a little "progressbar"+ printf "."++ # run and process+ ${simgi_exe} -s ${counter} reversible_bimol.sgl >& /dev/null + tail -n 400 reversible_bimol.dat | gawk ' { print $5}' | ../test_helpers/average >> ${globalFile} || return 1++ # unlink+ rm -f reversible_bimol.dat || return 1+ +done++# check if we're within the specs+# the expected number of products is 430.643462709951+# and we allow 0.5% tolerance+../test_helpers/check_deviation ${globalFile} 430.643462709951 5e-3+status=$?++# brief output+if [[ ${status} == 0 ]]; then+ echo+ echo+ echo "Congratulations - the reversible reaction test passed!"+ echo+ echo+else+ echo+ echo+ echo "Error - the reversible reaction test failed. Please check!"+ echo+ echo+fi++# remove files+rm -f ${globalFile}++# return status of deviation check+exit ${status}
+ test/check_reversible_trimol/Makefile view
@@ -0,0 +1,19 @@+include ../test_helpers/make_common+++default: check++.PHONY: check clean+check:+ @echo+ @echo "****** Running reversible trimolecular reaction test 1 ******"+ @./run_test.1.sh $(SIMGI_PATH)+ @echo+ @echo "****** Running reversible trimolecular reaction test 2 ******"+ @./run_test.2.sh $(SIMGI_PATH)+ @echo++ ++clean:+ rm -f *.hi *.o *.dat simgi.*
+ test/check_reversible_trimol/reversible_trimol.1.sgl view
@@ -0,0 +1,39 @@+{-----------------------------------------------------++ this is the input deck for a simple 3 way reaction+ (C) 2010 Markus Dittrich++------------------------------------------------------}++variables+ Na = 6.022e23+ myConc = 50e-6+ cubeVol_um = 0.05+ cubeVol = { cubeVol_um * 1e-15 }+ myMol = { myConc * cubeVol } + myRelease = { myMol * Na }+end++parameters+ time = 0.004+ outputBuffer = 50+ outputFreq = 1+ systemVol = { cubeVol }+end++molecules+ A = { myRelease }+ B = { myRelease }+ C = { myRelease }+ D = 0+end++reactions+ A + B + C -> D | 1e12|+ D -> A + B + C | 1e3 |+end++output+ outputFile = "reversible_trimol.1.dat"+ [{D/cubeVol/Na}]+end
+ test/check_reversible_trimol/reversible_trimol.2.sgl view
@@ -0,0 +1,39 @@+{-----------------------------------------------------++ this is the input deck for a simple 3 way reaction+ (C) 2010 Markus Dittrich++------------------------------------------------------}++variables+ Na = 6.022e23+ myConc = 50e-6+ cubeVol_um = 0.05+ cubeVol = { cubeVol_um * 1e-15 }+ myMol = { myConc * cubeVol } + myRelease = { myMol * Na }+end++parameters+ time = 0.15+ outputBuffer = 50+ outputFreq = 1+ systemVol = { cubeVol }+end++molecules+ A = { myRelease }+ B = { myRelease }+ C = { myRelease }+ D = 0+end++reactions+ A + B + C -> D | 1e12 |+ D -> A + B + C | 1e1 |+end++output+ outputFile = "reversible_trimol.2.dat"+ [{D/cubeVol/Na}]+end
+ test/check_reversible_trimol/run_test.1.sh view
@@ -0,0 +1,53 @@+#!/bin/bash+#+# short wrapper for runing a number of reversible+# simulations and then checking if we can reproduce+# the correct average product concentration+#++# +simgi_exe="${1}"++# create a global tempfile to collect the data+globalFile=$(mktemp simgi.XXXXXXXXXXXXX)++for ((counter=0; counter <= 200; counter++)); do++ # provide a little "progressbar"+ printf "."++ # run and process+ ${simgi_exe} -s ${counter} reversible_trimol.1.sgl >& /dev/null + tail -n 2000 reversible_trimol.1.dat | ../test_helpers/average >> ${globalFile} || return 1++ # unlink+ rm -f reversible_trimol.1..dat || return 1+ +done++# check if we're within the specs+# the expected concentration is 2.1986e-05 mol+# and we allow 0.05% relative deviation+../test_helpers/check_deviation ${globalFile} 2.1986e-05 5e-4+status=$?++# brief output+if [[ ${status} == 0 ]]; then+ echo+ echo+ echo "Congratulations - the reversible reaction test passed!"+ echo+ echo+else+ echo+ echo+ echo "Error - the reversible reaction test failed. Please check!"+ echo+ echo+fi++# remove files+rm -f ${globalFile}++# return status of deviation check+exit ${status}
+ test/check_reversible_trimol/run_test.2.sh view
@@ -0,0 +1,53 @@+#!/bin/bash+#+# short wrapper for runing a number of reversible+# simulations and then checking if we can reproduce+# the correct average product concentration+#++# +simgi_exe="${1}"++# create a global tempfile to collect the data+globalFile=$(mktemp simgi.XXXXXXXXXXXXX)++for ((counter=0; counter <= 200; counter++)); do++ # provide a little "progressbar"+ printf "."++ # run and process+ ${simgi_exe} -s ${counter} reversible_trimol.2.sgl >& /dev/null + tail -n 2000 reversible_trimol.2.dat | ../test_helpers/average >> ${globalFile} || return 1++ # unlink+ rm -f reversible_trimol.2.dat || return 1+ +done++# check if we're within the specs+# the expected concentration is 2.1986e-05 mol+# and we allow 0.05% relative deviation+../test_helpers/check_deviation ${globalFile} 4.2482e-5 5e-4+status=$?++# brief output+if [[ ${status} == 0 ]]; then+ echo+ echo+ echo "Congratulations - the reversible reaction test passed!"+ echo+ echo+else+ echo+ echo+ echo "Error - the reversible reaction test failed. Please check!"+ echo+ echo+fi++# remove files+rm -f ${globalFile}++# return status of deviation check+exit ${status}
test/check_rpnstack/Makefile view
@@ -6,8 +6,8 @@ .PHONY: check clean check:- ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) -i$(HELPER_LOCATION) \- --make RpnStackTest.hs+ @ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) -i$(HELPER_LOCATION) \+ --make RpnStackTest.hs &> /dev/null @./RpnStackTest
test/check_rpnstack/RpnStackTest.hs view
@@ -1,7 +1,10 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich,+ National Resource for Biomedical Supercomputing &+ Carnegie Mellon University + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. @@ -126,7 +129,7 @@ -- | main test driver main :: IO ()-main = putStrLn "\n\n\nTesting RPN stack (parser/compute engine)"+main = putStrLn "\n****** Testing RPN stack (parser/compute engine) ******" -- run simple tests >> (putStr $ color_string Cyan "\nSimple tests:\n")
+ test/test_helpers/Makefile view
@@ -0,0 +1,16 @@+include ./make_common+++default: check_deviation average++check_deviation: check_deviation.hs+ ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) --make check_deviation.hs &> /dev/null++average: average.hs+ ghc $(GHC_FLAGS_DEVEL) -i$(SRC_LOCATION) --make average.hs &> /dev/null+++.PHONY: clean++clean:+ rm -f *.hi *.o check_deviation average
test/test_helpers/TestHelpers.hs view
@@ -1,6 +1,6 @@ {----------------------------------------------------------------- - (c) 2009 Markus Dittrich + (c) 2009-2010 Markus Dittrich This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public @@ -107,4 +107,5 @@ , outputFreq = 1000 , outputCache = [] , outfileName = ""+ , variables = M.empty }
+ test/test_helpers/average.hs view
@@ -0,0 +1,38 @@+{-----------------------------------------------------------------+ + (c) 2009-2010 Markus Dittrich + + This program is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License Version 3 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License Version 3 for more details.+ + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA.++--------------------------------------------------------------------}++-- | short helper script for averaging a file containing a single+-- column of doubles+module Main where+++-- imports+import Prelude+++main :: IO ()+main = getContents+ >>= \content -> + let+ items = map (read) . lines $ content :: [Double]+ theSum = foldr (+) 0 items+ average = theSum/(fromIntegral . length $ items)+ in+ putStrLn (show average)
+ test/test_helpers/check_deviation.hs view
@@ -0,0 +1,46 @@+{-----------------------------------------------------------------+ + (c) 2009-2010 Markus Dittrich + + This program is free software; you can redistribute it + and/or modify it under the terms of the GNU General Public + License Version 3 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful,+ but WITHOUT ANY WARRANTY; without even the implied warranty of+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the+ GNU General Public License Version 3 for more details.+ + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA.++--------------------------------------------------------------------}++-- | short helper script for averaging a file containing a single+-- column of doubles+module Main where++-- imports+import Prelude+import System+import System.Environment+++main :: IO Int+main = getArgs + >>= \(name:value:tol:_) -> readFile name+ >>= \content -> + let+ items = map (read) . lines $ content :: [Double]+ theSum = foldr (+) 0 items+ average = theSum/(fromIntegral . length $ items)+ expected = read value :: Double+ tolerance = read tol :: Double+ deviation = abs((average - expected)/expected)+ in+ if ( deviation < tolerance )+ then exitWith ExitSuccess+ else exitWith $ ExitFailure 1+