Mercurial > dylan
changeset 2:b4de894a1e2e
initial import
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/categorical/imperative.html Fri Oct 28 00:03:05 2011 -0700 1.3 @@ -0,0 +1,1207 @@ 1.4 +<?xml version="1.0" encoding="utf-8"?> 1.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 1.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 1.7 +<html xmlns="http://www.w3.org/1999/xhtml" 1.8 +lang="en" xml:lang="en"> 1.9 +<head> 1.10 +<title>LAMBDA: The Ultimate Imperative</title> 1.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 1.12 +<meta name="generator" content="Org-mode"/> 1.13 +<meta name="generated" content="2011-07-15 02:49:04 EDT"/> 1.14 +<meta name="author" content="Guy Lewis Steele Jr. and Gerald Jay Sussman"/> 1.15 +<meta name="description" content=""/> 1.16 +<meta name="keywords" content=""/> 1.17 +<style type="text/css"> 1.18 + <!--/*--><![CDATA[/*><!--*/ 1.19 + html { font-family: Times, serif; font-size: 12pt; } 1.20 + .title { text-align: center; } 1.21 + .todo { color: red; } 1.22 + .done { color: green; } 1.23 + .tag { background-color: #add8e6; font-weight:normal } 1.24 + .target { } 1.25 + .timestamp { color: #bebebe; } 1.26 + .timestamp-kwd { color: #5f9ea0; } 1.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 1.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 1.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 1.30 + p.verse { margin-left: 3% } 1.31 + pre { 1.32 + border: 1pt solid #AEBDCC; 1.33 + background-color: #F3F5F7; 1.34 + padding: 5pt; 1.35 + font-family: courier, monospace; 1.36 + font-size: 90%; 1.37 + overflow:auto; 1.38 + } 1.39 + table { border-collapse: collapse; } 1.40 + td, th { vertical-align: top; } 1.41 + th.right { text-align:center; } 1.42 + th.left { text-align:center; } 1.43 + th.center { text-align:center; } 1.44 + td.right { text-align:right; } 1.45 + td.left { text-align:left; } 1.46 + td.center { text-align:center; } 1.47 + dt { font-weight: bold; } 1.48 + div.figure { padding: 0.5em; } 1.49 + div.figure p { text-align: center; } 1.50 + textarea { overflow-x: auto; } 1.51 + .linenr { font-size:smaller } 1.52 + .code-highlighted {background-color:#ffff00;} 1.53 + .org-info-js_info-navigation { border-style:none; } 1.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 1.55 + white-space:nowrap; } 1.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 1.57 + font-weight:bold; } 1.58 + /*]]>*/--> 1.59 +</style> 1.60 +<script type="text/javascript"> 1.61 +<!--/*--><![CDATA[/*><!--*/ 1.62 + function CodeHighlightOn(elem, id) 1.63 + { 1.64 + var target = document.getElementById(id); 1.65 + if(null != target) { 1.66 + elem.cacheClassElem = elem.className; 1.67 + elem.cacheClassTarget = target.className; 1.68 + target.className = "code-highlighted"; 1.69 + elem.className = "code-highlighted"; 1.70 + } 1.71 + } 1.72 + function CodeHighlightOff(elem, id) 1.73 + { 1.74 + var target = document.getElementById(id); 1.75 + if(elem.cacheClassElem) 1.76 + elem.className = elem.cacheClassElem; 1.77 + if(elem.cacheClassTarget) 1.78 + target.className = elem.cacheClassTarget; 1.79 + } 1.80 +/*]]>*///--> 1.81 +</script> 1.82 +<script type="text/javascript" src="http://orgmode.org/mathjax/MathJax.js"> 1.83 +<!--/*--><![CDATA[/*><!--*/ 1.84 + MathJax.Hub.Config({ 1.85 + // Only one of the two following lines, depending on user settings 1.86 + // First allows browser-native MathML display, second forces HTML/CSS 1.87 + // config: ["MMLorHTML.js"], jax: ["input/TeX"], 1.88 + jax: ["input/TeX", "output/HTML-CSS"], 1.89 + extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js", 1.90 + "TeX/noUndefined.js"], 1.91 + tex2jax: { 1.92 + inlineMath: [ ["\\(","\\)"] ], 1.93 + displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ], 1.94 + skipTags: ["script","noscript","style","textarea","pre","code"], 1.95 + ignoreClass: "tex2jax_ignore", 1.96 + processEscapes: false, 1.97 + processEnvironments: true, 1.98 + preview: "TeX" 1.99 + }, 1.100 + showProcessingMessages: true, 1.101 + displayAlign: "center", 1.102 + displayIndent: "2em", 1.103 + 1.104 + "HTML-CSS": { 1.105 + scale: 100, 1.106 + availableFonts: ["STIX","TeX"], 1.107 + preferredFont: "TeX", 1.108 + webFont: "TeX", 1.109 + imageFont: "TeX", 1.110 + showMathMenu: true, 1.111 + }, 1.112 + MMLorHTML: { 1.113 + prefer: { 1.114 + MSIE: "MML", 1.115 + Firefox: "MML", 1.116 + Opera: "HTML", 1.117 + other: "HTML" 1.118 + } 1.119 + } 1.120 + }); 1.121 +/*]]>*///--> 1.122 +</script> 1.123 +</head> 1.124 +<body> 1.125 + 1.126 +<div id="content"> 1.127 + 1.128 + 1.129 + 1.130 +<div id="table-of-contents"> 1.131 +<h2>Table of Contents</h2> 1.132 +<div id="text-table-of-contents"> 1.133 +<ul> 1.134 +<li><a href="#sec-1">1 Abstract </a></li> 1.135 +<li><a href="#sec-2">2 Introduction </a> 1.136 +<ul> 1.137 +<li><a href="#sec-2-1">2.1 Simple Loops </a> 1.138 +<ul> 1.139 +<li><a href="#sec-2-1-1">2.1.1 Simple Recursion </a></li> 1.140 +<li><a href="#sec-2-1-2">2.1.2 Iteration </a></li> 1.141 +</ul></li> 1.142 +</ul> 1.143 +</li> 1.144 +<li><a href="#sec-3">3 Imperative Programming </a> 1.145 +<ul> 1.146 +<li><a href="#sec-3-1">3.1 Compound Statements </a></li> 1.147 +<li><a href="#sec-3-2">3.2 2.2. The G0 TO Statement </a></li> 1.148 +<li><a href="#sec-3-3">3.3 2.3. Simple Assignment </a></li> 1.149 +<li><a href="#sec-3-4">3.4 Compound Expressions ' </a></li> 1.150 +</ul> 1.151 +</li> 1.152 +<li><a href="#sec-4">4 Continuations </a> 1.153 +<ul> 1.154 +<li><a href="#sec-4-1">4.1 Continuation-Passing Recursion </a></li> 1.155 +<li><a href="#sec-4-2">4.2 Escape Expressions </a></li> 1.156 +</ul> 1.157 +</li> 1.158 +</ul> 1.159 +</div> 1.160 +</div> 1.161 + 1.162 +<div id="outline-container-1" class="outline-2"> 1.163 +<h2 id="sec-1"><span class="section-number-2">1</span> Abstract </h2> 1.164 +<div class="outline-text-2" id="text-1"> 1.165 + 1.166 + 1.167 +<p> 1.168 +We demonstrate how to model the following common programming constructs in 1.169 +terms of an applicative order language similar to LISP: 1.170 +</p><ul> 1.171 +<li>Simple Recursion 1.172 +</li> 1.173 +<li>Iteration 1.174 +</li> 1.175 +<li>Compound Statements and Expressions 1.176 +</li> 1.177 +<li>GO TO and Assignment 1.178 +</li> 1.179 +<li>Continuation—Passing 1.180 +</li> 1.181 +<li>Escape Expressions 1.182 +</li> 1.183 +<li>Fluid Variables 1.184 +</li> 1.185 +<li>Call by Name, Call by Need, and Call by Reference 1.186 +</li> 1.187 +</ul> 1.188 + 1.189 +<p>The models require only (possibly self-referent) lambda application, 1.190 +conditionals, and (rarely) assignment. No complex data structures such as 1.191 +stacks are used. The models are transparent, involving only local syntactic 1.192 +transformations. 1.193 +Some of these models, such as those for GO TO and assignment, are already well 1.194 +known, and appear in the work of Landin, Reynolds, and others. The models for 1.195 +escape expressions, fluid variables, and call by need with side effects are 1.196 +new. This paper is partly tutorial in intent, gathering all the models 1.197 +together for purposes of context. 1.198 +This report describes research done at the Artificial Intelligence Laboratory 1.199 +of the Massachusetts Institute of Teehnology. Support for the laboratory's 1.200 +artificial intelligence research is provided in part by the Advanced Research 1.201 +Projects Agency of the Department of Defense under Office of Naval Research 1.202 +contract N000l4-75-C-0643. 1.203 +</p> 1.204 +</div> 1.205 + 1.206 +</div> 1.207 + 1.208 +<div id="outline-container-2" class="outline-2"> 1.209 +<h2 id="sec-2"><span class="section-number-2">2</span> Introduction </h2> 1.210 +<div class="outline-text-2" id="text-2"> 1.211 + 1.212 + 1.213 +<p> 1.214 + We catalogue a number of common programming constructs. For each 1.215 +construct we examine "typical" usage in well-known programming languages, and 1.216 +then capture the essence of the semantics of the construct in terms of a 1.217 +common meta-language. 1.218 +The lambda calculus {Note Alonzowins} is often used as such a meta- 1.219 +language. Lambda calculus offers clean semantics, but it is clumsy because it 1.220 +was designed to be a minimal language rather than a convenient one. All 1.221 +lambda calculus "functions" must take exactly one "argument"; the only "data 1.222 +type" is lambda expressions; and the only "primitive operation‘ is variable‘ 1.223 +substitution. While its utter simplicity makes lambda calculus ideal for 1.224 +logicians, it is too primitive for use by programmers. The meta-language we 1.225 +use is a programming language called SCHEME {Note Schemepaper) which is based 1.226 +on lambda calculus. 1.227 +SCHEME is a dialect of LISP. [McCarthy 62] It is an expression- 1.228 +oriented, applicative order, interpreter-based language which allows one to 1.229 +manipulate programs as data. It differs from most current dialects of LISP in 1.230 +that it closes all lambda expressions in the environment of their definition 1.231 +or declaration, rather than in the execution environment. {Note Closures} 1.232 +This preserves the substitution semantics of lambda calculus, and has the 1.233 +consequence that all variables are lexically scoped, as in ALGOL. [Naur 63] 1.234 +Another difference is that SCHEME is implemented in such a way that tail- 1.235 +recursions execute without net growth of the interpreter stack. {Note 1.236 +Schemenote} We have chosen to use LISP syntax rather than, say, ALGOL syntax 1.237 +because we want to treat programs as data for the purpose of describing 1.238 +transformations on the code. LISP supplies names for the parts of an 1.239 +executable expression and standard operators for constructing expressions and 1.240 +extracting their components. The use of LISP syntax makes the structure of 1.241 +such expressions manifest. We use ALGOL as an expository language, because it 1.242 +is familiar to many people, but ALGOL is not sufficiently powerful to express 1.243 +the necessary concepts; in particular, it does not allow functions to return 1.244 +functions as values. we are thus forced to use a dialect of LISP in many 1.245 +cases. 1.246 +We will consider various complex programming language constructs and 1.247 +show how to model them in terms of only a few simple ones. As far as possible 1.248 +we will use only three control constructs from SCHEME: LAMBDA expressions, as 1.249 +in LISP, which are Just functions with lexically scoped free variables; 1.250 +LABELS, which allows declaration of mutually recursive procedures (Note 1.251 +Labelsdef}; and IF, a primitive conditional expression. For more complex 1.252 +modelling we will introduce an assignment primitive (ASET).i We will freely 1.253 +assume the existence of other comon primitives, such as arithmetic functions. 1.254 +The constructs we will examine are divided into four broad classes. 1.255 +The first is sfinph?Lo0pl; this contains simple recursions and iterations, and 1.256 +an introduction to the notion of continuations. The second is hmponflivo 1.257 +Connrucls; this includes compound statements, G0 T0, and simple variable 1.258 +assignments. The third is continuations, which encompasses the distinction between statements and expressions, escape operators (such as Landin's J- 1.259 +operator [Landin 65] and Reynold's escape expression [Reynolds 72]). and fluid 1.260 +(dynamically bound) variables. The fourth is Parameter Passing Mechanisms, such 1.261 +as ALGOL call—by-name and FORTRAN call-by-location. 1.262 +Some of the models presented here are already well-known, particularly 1.263 +those for G0 T0 and assignment. [McCarthy 60] [Landin 65] [Reynolds 72] 1.264 +Those for escape operators, fluid variables, and call-by-need with side 1.265 +effects are new. 1.266 +</p> 1.267 +</div> 1.268 + 1.269 +<div id="outline-container-2-1" class="outline-3"> 1.270 +<h3 id="sec-2-1"><span class="section-number-3">2.1</span> Simple Loops </h3> 1.271 +<div class="outline-text-3" id="text-2-1"> 1.272 + 1.273 +<p>By <i>simple loops</i> we mean constructs which enable programs to execute the 1.274 +same piece of code repeatedly in a controlled manner. Variables may be made 1.275 +to take on different values during each repetition, and the number of 1.276 +repetitions may depend on data given to the program. 1.277 +</p> 1.278 +</div> 1.279 + 1.280 +<div id="outline-container-2-1-1" class="outline-4"> 1.281 +<h4 id="sec-2-1-1"><span class="section-number-4">2.1.1</span> Simple Recursion </h4> 1.282 +<div class="outline-text-4" id="text-2-1-1"> 1.283 + 1.284 +<p>One of the easiest ways to produce a looping control structure is to 1.285 +use a recursive function, one which calls itself to perform a subcomputation. 1.286 +For example, the familiar factorial function may be written recursively in 1.287 +ALGOL: ' 1.288 +</p> 1.289 + 1.290 + 1.291 +<pre class="src src-algol">integer procedure fact(n) value n: integer n: 1.292 +fact := if n=0 then 1 else n*fact(n-1); 1.293 + 1.294 +</pre> 1.295 + 1.296 + 1.297 + 1.298 + 1.299 +<p> 1.300 +The invocation <code>fact(n)</code> computes the product of the integers from 1 to n using 1.301 +the identity n!=n(n-1)! (n>0). If \(n\) is zero, 1 is returned; otherwise <code>fact</code>: 1.302 +calls itself recursively to compute \((n-1)!\) , then multiplies the result by \(n\) 1.303 +and returns it. 1.304 +</p> 1.305 +<p> 1.306 +This same function may be written in Clojure as follows: 1.307 +</p> 1.308 + 1.309 + 1.310 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">ns</span> categorical.imperative) 1.311 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">fact</span>[n] 1.312 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">=</span> n 0) 1 (<span style="color: #8cd0d3;">*</span> n (fact (<span style="color: #8cd0d3;">dec</span> n)))) 1.313 +) 1.314 + 1.315 +</pre> 1.316 + 1.317 + 1.318 + 1.319 + 1.320 + 1.321 +<p> 1.322 +Clojure does not require an assignment to the ``variable'' fan: to return a value 1.323 +as ALGOL does. The IF primitive is the ALGOL if-then-else rendered in LISP 1.324 +syntax. Note that the arithmetic primitives are prefix operators in SCHEME. 1.325 +</p> 1.326 +</div> 1.327 + 1.328 +</div> 1.329 + 1.330 +<div id="outline-container-2-1-2" class="outline-4"> 1.331 +<h4 id="sec-2-1-2"><span class="section-number-4">2.1.2</span> Iteration </h4> 1.332 +<div class="outline-text-4" id="text-2-1-2"> 1.333 + 1.334 +<p>There are many other ways to compute factorial. One important way is 1.335 +through the use of <i>iteration</i>. 1.336 +A comon iterative construct is the DO loop. The most general form we 1.337 +have seen in any programming language is the MacLISP DO [Moon 74]. It permits 1.338 +the simultaneous initialization of any number of control variables and the 1.339 +simultaneous stepping of these variables by arbitrary functions at each 1.340 +iteration step. The loop is terminated by an arbitrary predicate, and an 1.341 +arbitrary value may be returned. The DO loop may have a body, a series of 1.342 +expressions executed for effect on each iteration. A version of the MacLISP 1.343 +DO construct has been adopted in SCHEME. 1.344 +</p> 1.345 +<p> 1.346 +The general form of a SCHEME DO is: 1.347 +</p> 1.348 + 1.349 + 1.350 +<pre class="src src-nothing">(DO ((<var1> (init1> <stepl>) 1.351 +((var2> <init2> <step2>) 1.352 +(<varn> <intn> (stepn>)) 1.353 +(<pred> (value>) 1.354 +(optional body>) 1.355 + 1.356 +</pre> 1.357 + 1.358 + 1.359 + 1.360 +<p> 1.361 +The semantics of this are that the variables are bound and initialized to the 1.362 +values of the <initi> expressions, which must all be evaluated in the 1.363 +environment outside the D0; then the predicate <pred> is evaluated in the new 1.364 +environment, and if TRUE, the (value) is evaluated and returned. Otherwise 1.365 +the (optional body) is evaluated, then each of the steppers <stepi> is 1.366 +evaluated in the current environment, all the variables made to have the 1.367 +results as their values, the predicate evaluated again, and so on. 1.368 +Using D0 loops in both ALGOL and SCHEME, we may express FACT by means 1.369 +of iteration. 1.370 +</p> 1.371 + 1.372 + 1.373 +<pre class="src src-algol">integer procedure fact(n); value n; integer n: 1.374 +begin 1.375 +integer m, ans; 1.376 +ans := 1; 1.377 +for m := n step -l until 0 do ans := m*ans; 1.378 +fact := ans; 1.379 +end; 1.380 + 1.381 +</pre> 1.382 + 1.383 + 1.384 + 1.385 + 1.386 + 1.387 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'categorical.imperative) 1.388 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">fact-do</span>[n] 1.389 +) 1.390 + 1.391 +</pre> 1.392 + 1.393 + 1.394 + 1.395 + 1.396 +<p> 1.397 +Note that the SCHEME D0 loop in FACT has no body – the stepping functions do 1.398 +all the work. The ALGOL DO loop has an assignment in its body; because an 1.399 +ALGOL DO loop can step only one variable, we need the assignment to step the 1.400 +the variable "manually'. 1.401 +In reality the SCHEME DO construct is not a primitive; it is a macro 1.402 +which expands into a function which performs the iteration by tail—recursion. 1.403 +Consider the following definition of FACT in SCHEME. Although it appears to 1.404 +be recursive, since it "calls itself", it is entirely equivalent to the DO 1.405 +loop given above, for it is the code that the DO macro expands into! It 1.406 +captures the essence of our intuitive notion of iteration, because execution 1.407 +of this program will not produce internal structures (e.g. stacks or variable 1.408 +bindings) which increase in size with the number of iteration steps. 1.409 +</p> 1.410 + 1.411 + 1.412 + 1.413 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'categorical.imperative) 1.414 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">fact-do-expand</span>[n] 1.415 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [fact1 1.416 + (<span style="color: #8cd0d3;">fn</span>[m ans] 1.417 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (zero? m) ans 1.418 + (<span style="color: #f0dfaf; font-weight: bold;">recur</span> (<span style="color: #8cd0d3;">dec</span> m) (<span style="color: #8cd0d3;">*</span> m ans))))] 1.419 + (fact1 n 1))) 1.420 + 1.421 +</pre> 1.422 + 1.423 + 1.424 + 1.425 + 1.426 +<p> 1.427 +From this we can infer a general way to express iterations in SCHEME in 1.428 +a manner isomorphic to the HacLISP D0. The expansion of the general D0 loop 1.429 +</p> 1.430 + 1.431 + 1.432 +<pre class="src src-nothing">(DO ((<varl> <init1> <step1>) 1.433 +(<var2> (init2) <step2>) 1.434 +... 1.435 +(<varn> <initn> <stepn>)) 1.436 +(<pred> <va1ue>) 1.437 +<body>) 1.438 + 1.439 +</pre> 1.440 + 1.441 + 1.442 + 1.443 +<p> 1.444 +is this: 1.445 +</p> 1.446 + 1.447 + 1.448 +<pre class="src src-nothing">(let [doloop 1.449 +(fn [dummy <var1> <var2> ... <varn>) 1.450 +(if <pred> <value> 1.451 +(recur <body> <step1> <step2> ... <stepn>)))] 1.452 + 1.453 +(doloop nil <init1> <init2> ... <initn>)) 1.454 + 1.455 +</pre> 1.456 + 1.457 + 1.458 + 1.459 +<p> 1.460 +The identifiers <code>doloop</code> and <code>dummy</code> are chosen so as not to conflict with any 1.461 +other identifiers in the program. 1.462 +Note that, unlike most implementations of D0, there are no side effects 1.463 +in the steppings of the iteration variables. D0 loops are usually modelled 1.464 +using assignment statements. For example: 1.465 +</p> 1.466 + 1.467 + 1.468 +<pre class="src src-nothing">for r :1 0 step b until c do <statement>; 1.469 + 1.470 +</pre> 1.471 + 1.472 + 1.473 + 1.474 + 1.475 +<p> 1.476 +can be modelled as follows: [Naur 63] 1.477 +</p> 1.478 + 1.479 + 1.480 +<pre class="src src-nothing">begin 1.481 +x := a; 1.482 +L: if (x-c)*sign(n) > 0 then go to Endloop; 1.483 +<statement>; 1.484 +x := x+b; 1.485 +go to L: 1.486 +Endloop: 1.487 +end; 1.488 + 1.489 +</pre> 1.490 + 1.491 + 1.492 + 1.493 +<p> 1.494 +Later we will see how such assignment statements can in general be 1.495 +modelled without using side effects. 1.496 +</p> 1.497 +</div> 1.498 +</div> 1.499 +</div> 1.500 + 1.501 +</div> 1.502 + 1.503 +<div id="outline-container-3" class="outline-2"> 1.504 +<h2 id="sec-3"><span class="section-number-2">3</span> Imperative Programming </h2> 1.505 +<div class="outline-text-2" id="text-3"> 1.506 + 1.507 +<p>Lambda calculus (and related languages, such as ``pure LISP'') is often 1.508 +used for modelling the applicative constructs of programming languages. 1.509 +However, they are generally thought of as inappropriate for modelling 1.510 +imperative constructs. In this section we show how imperative constructs may 1.511 +be modelled by applicative SCHEME constructs. 1.512 +</p> 1.513 +</div> 1.514 + 1.515 +<div id="outline-container-3-1" class="outline-3"> 1.516 +<h3 id="sec-3-1"><span class="section-number-3">3.1</span> Compound Statements </h3> 1.517 +<div class="outline-text-3" id="text-3-1"> 1.518 + 1.519 +<p>The simplest kind of imperative construct is the statement sequencer, 1.520 +for example the compound statement in ALGOL: 1.521 +</p> 1.522 + 1.523 + 1.524 +<pre class="src src-algol">begin 1.525 +S1; 1.526 +S2; 1.527 +end 1.528 + 1.529 +</pre> 1.530 + 1.531 + 1.532 + 1.533 + 1.534 +<p> 1.535 +This construct has two interesting properties: 1.536 +</p><ul> 1.537 +<li>(1) It performs statement S1 before S2, and so may be used for 1.538 + sequencing. 1.539 +</li> 1.540 +<li>(2) S1 is useful only for its side effects. (In ALGOL, S2 must also 1.541 + be a statement, and so is also useful only for side effects, but 1.542 + other languages have compound expressions containing a statement 1.543 + followed by an expression.) 1.544 +</li> 1.545 +</ul> 1.546 + 1.547 + 1.548 +<p> 1.549 +The ALGOL compound statement may actually contain any number of statements, 1.550 +but such statements can be expressed as a series of nested two-statement 1.551 +compounds. That is: 1.552 +</p> 1.553 + 1.554 + 1.555 +<pre class="src src-algol">begin 1.556 +S1; 1.557 +S2; 1.558 +... 1.559 +Sn-1; 1.560 +Sn; 1.561 +end 1.562 + 1.563 +</pre> 1.564 + 1.565 + 1.566 + 1.567 +<p> 1.568 +is equivalent to: 1.569 +</p> 1.570 + 1.571 + 1.572 + 1.573 +<pre class="src src-algol">begin 1.574 +S1; 1.575 +begin 1.576 +S2; 1.577 +begin 1.578 +... 1.579 + 1.580 +begin 1.581 +Sn-1; 1.582 +Sn; 1.583 +end; 1.584 +end; 1.585 +end: 1.586 +end 1.587 + 1.588 +</pre> 1.589 + 1.590 + 1.591 + 1.592 + 1.593 +<p> 1.594 +It is not immediately apparent that this sequencing can be expressed in a 1.595 +purely applicative language. We can, however, take advantage of the implicit 1.596 +sequencing of applicative order evaluation. Thus, for example, we may write a 1.597 +two-statement sequence as follows: 1.598 +</p> 1.599 + 1.600 + 1.601 + 1.602 +<pre class="src src-clojure">((<span style="color: #8cd0d3;">fn</span>[dummy] S2) S1) 1.603 + 1.604 +</pre> 1.605 + 1.606 + 1.607 + 1.608 + 1.609 +<p> 1.610 +where <code>dummy</code> is an identifier not used in S2. From this it is 1.611 +manifest that the value of S1 is ignored, and so is useful only for 1.612 +side effects. (Note that we did not claim that S1 is expressed in a 1.613 +purely applicative language, but only that the sequencing can be so 1.614 +expressed.) From now on we will use the form <code>(BLOCK S1 S2)</code> as an 1.615 +abbreviation for this expression, and <code>(BLOCK S1 S2...Sn-1 Sn)</code> as an 1.616 +abbreviation for 1.617 +</p> 1.618 + 1.619 + 1.620 + 1.621 +<pre class="src src-algol">(BLOCK S1 (BLOCK S2 (BLOCK ... (BLOCK Sn-1 Sn)...))) 1.622 + 1.623 +</pre> 1.624 + 1.625 + 1.626 + 1.627 + 1.628 +</div> 1.629 + 1.630 +</div> 1.631 + 1.632 +<div id="outline-container-3-2" class="outline-3"> 1.633 +<h3 id="sec-3-2"><span class="section-number-3">3.2</span> 2.2. The G0 TO Statement </h3> 1.634 +<div class="outline-text-3" id="text-3-2"> 1.635 + 1.636 + 1.637 +<p> 1.638 +A more general imperative structure is the compound statement with 1.639 +labels and G0 T0s. Consider the following code fragment due to 1.640 +Jacopini, taken from Knuth: [Knuth 74] 1.641 +</p> 1.642 + 1.643 + 1.644 +<pre class="src src-algol">begin 1.645 +L1: if B1 then go to L2; S1; 1.646 + if B2 then go to L2; S2; 1.647 + go to L1; 1.648 +L2: S3; 1.649 + 1.650 +</pre> 1.651 + 1.652 + 1.653 + 1.654 + 1.655 +<p> 1.656 +It is perhaps surprising that this piece of code can be <i>syntactically</i> 1.657 +transformed into a purely applicative style. For example, in SCHEME we 1.658 +could write: 1.659 +</p> 1.660 + 1.661 + 1.662 + 1.663 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'categorical.imperative) 1.664 +(<span style="color: #f0dfaf; font-weight: bold;">let</span> 1.665 + [L1 (<span style="color: #8cd0d3;">fn</span>[] 1.666 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> B1 (L2) (<span style="color: #f0dfaf; font-weight: bold;">do</span> S1 1.667 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> B2 (L2) (<span style="color: #f0dfaf; font-weight: bold;">do</span> S2 (L1)))))) 1.668 + L2 (<span style="color: #8cd0d3;">fn</span>[] S3)] 1.669 + (L1)) 1.670 + 1.671 +</pre> 1.672 + 1.673 + 1.674 + 1.675 + 1.676 +<p> 1.677 +As with the D0 loop, this transformation depends critically on SCHEME's 1.678 +treatment of tail-recursion and on lexical scoping of variables. The labels 1.679 +are names of functions of no arguments. In order to ‘go to" the labeled code, 1.680 +we merely call the function named by that label. 1.681 +</p> 1.682 +</div> 1.683 + 1.684 +</div> 1.685 + 1.686 +<div id="outline-container-3-3" class="outline-3"> 1.687 +<h3 id="sec-3-3"><span class="section-number-3">3.3</span> 2.3. Simple Assignment </h3> 1.688 +<div class="outline-text-3" id="text-3-3"> 1.689 + 1.690 +<p>Of course, all this sequencing of statements is useless unless the 1.691 +statements have side effects. An important side effect is assignment. For 1.692 +example, one often uses assignment to place intermediate results in a named 1.693 +location (i.e. a variable) so that they may be used more than once later 1.694 +without recomputing them: 1.695 +</p> 1.696 + 1.697 + 1.698 + 1.699 +<pre class="src src-algol">begin 1.700 +real a2, sqrtdisc; 1.701 +a2 := 2*a; 1.702 +sqrtdisc := sqrt(b^2 - 4*a*c); 1.703 +root1 := (- b + sqrtdisc) / a2; 1.704 +root2 := (- b - sqrtdisc) / a2; 1.705 +print(root1); 1.706 +print(root2); 1.707 +print(root1 + root2); 1.708 +end 1.709 + 1.710 +</pre> 1.711 + 1.712 + 1.713 + 1.714 + 1.715 +<p> 1.716 +It is well known that such naming of intermediate results may be accomplished 1.717 +by calling a function and binding the formal parameter variables to the 1.718 +results: 1.719 +</p> 1.720 + 1.721 + 1.722 + 1.723 +<pre class="src src-clojure">(<span style="color: #8cd0d3;">fn</span> [a2 sqrtdisc] 1.724 + ((<span style="color: #8cd0d3;">fn</span>[root1 root2] 1.725 + (<span style="color: #f0dfaf; font-weight: bold;">do</span> (<span style="color: #8cd0d3;">println</span> root1) 1.726 + (<span style="color: #8cd0d3;">println</span> root2) 1.727 + (<span style="color: #8cd0d3;">println</span> (<span style="color: #8cd0d3;">+</span> root1 root2)))) 1.728 + (<span style="color: #8cd0d3;">/</span> (<span style="color: #8cd0d3;">+</span> (<span style="color: #8cd0d3;">-</span> b) sqrtdisc) a2) 1.729 + (<span style="color: #8cd0d3;">/</span> (<span style="color: #8cd0d3;">-</span> (<span style="color: #8cd0d3;">-</span> b) sqrtdisc) a2)) 1.730 + 1.731 + (<span style="color: #8cd0d3;">*</span> 2 a) 1.732 + (sqrt (<span style="color: #8cd0d3;">-</span> (<span style="color: #8cd0d3;">*</span> b b) (<span style="color: #8cd0d3;">*</span> 4 a c)))) 1.733 + 1.734 +</pre> 1.735 + 1.736 + 1.737 + 1.738 +<p> 1.739 +This technique can be extended to handle all simple variable assignments which 1.740 +appear as statements in blocks, even if arbitrary G0 T0 statements also appear 1.741 +in such blocks. {Note Mccarthywins} 1.742 +</p> 1.743 +<p> 1.744 +For example, here is a program which uses G0 TO statements in the form 1.745 +presented before; it determines the parity of a non-negative integer by 1.746 +counting it down until it reaches zero. 1.747 +</p> 1.748 + 1.749 + 1.750 + 1.751 +<pre class="src src-algol">begin 1.752 +L1: if a = 0 then begin parity := 0; go to L2; end; 1.753 + a := a - 1; 1.754 + if a = 0 then begin parity := 1; go to L2; end; 1.755 + a := a - 1; 1.756 + go to L1; 1.757 +L2: print(parity); 1.758 + 1.759 +</pre> 1.760 + 1.761 + 1.762 + 1.763 + 1.764 +<p> 1.765 +This can be expressed in SCHEME: 1.766 +</p> 1.767 + 1.768 + 1.769 + 1.770 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">let</span> 1.771 + [L1 (<span style="color: #8cd0d3;">fn</span> [a parity] 1.772 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (zero? a) (L2 a 0) 1.773 + (L3 (<span style="color: #8cd0d3;">dec</span> a) parity))) 1.774 + L3 (<span style="color: #8cd0d3;">fn</span> [a parity] 1.775 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (zero? a) (L2 a 1) 1.776 + (L1 (<span style="color: #8cd0d3;">dec</span> a) parity))) 1.777 + L2 (<span style="color: #8cd0d3;">fn</span> [a parity] 1.778 + (<span style="color: #8cd0d3;">println</span> parity))] 1.779 + (L1 a parity)) 1.780 + 1.781 +</pre> 1.782 + 1.783 + 1.784 + 1.785 + 1.786 +<p> 1.787 +The trick is to pass the set of variables which may be altered as arguments to 1.788 +the label functions. {Note Flowgraph} It may be necessary to introduce new 1.789 +labels (such as L3) so that an assignment may be transformed into the binding 1.790 +for a function call. At worst, one may need as many labels as there are 1.791 +statements (not counting the eliminated assignment and GO TO statements). 1.792 +</p> 1.793 +</div> 1.794 + 1.795 +</div> 1.796 + 1.797 +<div id="outline-container-3-4" class="outline-3"> 1.798 +<h3 id="sec-3-4"><span class="section-number-3">3.4</span> Compound Expressions ' </h3> 1.799 +<div class="outline-text-3" id="text-3-4"> 1.800 + 1.801 +<p>At this point we are almost in a position to model the most general 1.802 +form of compound statement. In LISP, this is called the 'PROG feature". In 1.803 +addition to statement sequencing and G0 T0 statements, one can return a <i>value</i> 1.804 +from a PROG by using the RETURN statement. 1.805 +</p> 1.806 +<p> 1.807 +Let us first consider the simplest compound statement, which in SCHEME 1.808 +we call BLOCK. Recall that 1.809 +<code>(BLOCK s1 sz)</code> is defined to be <code>((lambda (dummy) s2) s1)</code> 1.810 +</p> 1.811 +<p> 1.812 +Notice that this not only performs Sl before S2, but also returns the value of 1.813 +S2. Furthermore, we defined <code>(BLOCK S1 S2 ... Sn)</code> so that it returns the value 1.814 +of <code>Sn</code>. Thus BLOCK may be used as a compound expression, and models a LISP 1.815 +PROGN, which is a PROG with no G0 T0 statements and an implicit RETURN of the 1.816 +last ``statement'' (really an expression). 1.817 +</p> 1.818 +<p> 1.819 +Host LISP compilers compile D0 expressions by macro-expansion. We have 1.820 +already seen one way to do this in SCHEME using only variable binding. A more 1.821 +common technique is to expand the D0 into a PROG, using variable assignments 1.822 +instead of bindings. Thus the iterative factorial program: 1.823 +</p> 1.824 + 1.825 + 1.826 + 1.827 +<pre class="src src-clojure">(oarxnz FACT . 1.828 +(LAMaoA (n) . 1.829 +(D0 ((M N (<span style="color: #8cd0d3;">-</span> H 1)) 1.830 +(Ans 1 (<span style="color: #8cd0d3;">*</span> M Ans))) 1.831 +((<span style="color: #8cd0d3;">-</span> H 0) A<span style="color: #cc9393;">"$))))</span> 1.832 + 1.833 +</pre> 1.834 + 1.835 + 1.836 + 1.837 + 1.838 +<p> 1.839 +would expand into: 1.840 +</p> 1.841 + 1.842 + 1.843 + 1.844 +<pre class="src src-clojure">(DEFINE FACT 1.845 +. (LAMeoA (M) 1.846 +(PRO6 (M Ans) 1.847 +(sszro M n 1.848 +Ans 1) ~ 1.849 +LP (tr (<span style="color: #8cd0d3;">-</span> M 0) (RETURN Ans)) 1.850 +(ssero M (<span style="color: #8cd0d3;">-</span> n 1) 1.851 +Ans (' M Ans)) 1.852 +(60 LP)))) 1.853 + 1.854 +</pre> 1.855 + 1.856 + 1.857 + 1.858 + 1.859 +<p> 1.860 +where SSETQ is a simultaneous multiple assignment operator. (SSETQ is not a 1.861 +SCHEME (or LISP) primitive. It can be defined in terms of a single assignment 1.862 +operator, but we are more interested here in RETURN than in simultaneous 1.863 +assignment. The SSETQ's will all be removed anyway and modelled by lambda 1.864 +binding.) We can apply the same technique we used before to eliminate G0 T0 1.865 +statements and assignments from compound statements: 1.866 +</p> 1.867 + 1.868 + 1.869 + 1.870 +<pre class="src src-clojure">(DEFINE FACT 1.871 +(LAHBOA (I) 1.872 +(LABELS ((L1 (LAManA (M Ans) 1.873 +(LP n 1))) 1.874 +(LP (LAMaoA (M Ans) 1.875 +(IF (<span style="color: #8cd0d3;">-</span> M o) (nztunn Ans) 1.876 +(£2 H An$)))) 1.877 +(L2 (LAMaoA (M An ) 1.878 +(LP (<span style="color: #8cd0d3;">-</span> <span style="color: #cc9393;">" 1) (' H flN$)))))</span> 1.879 +<span style="color: #e37170; background-color: #332323;">(</span><span style="color: #cc9393;">L1 NIL NlL))))</span> 1.880 + 1.881 +</pre> 1.882 + 1.883 + 1.884 +<p> 1.885 + clojure 1.886 +</p> 1.887 +<p> 1.888 +We still haven't done anything about RETURN. Let's see… 1.889 +</p><ul> 1.890 +<li>==> the value of (FACT 0) is the value of (Ll NIL NIL) 1.891 +</li> 1.892 +<li>==> which is the value of (LP 0 1) 1.893 +</li> 1.894 +<li>==> which is the value of (IF (= 0 0) (RETURN 1) (L2 0 1)) 1.895 +</li> 1.896 +<li>==> which is the value of (RETURN 1) 1.897 +</li> 1.898 +</ul> 1.899 + 1.900 + 1.901 +<p> 1.902 +Notice that if RETURN were the <i>identity function</i> (LAMBDA (X) X), we would get the right answer. This is in fact a 1.903 +general truth: if we Just replace a call to RETURN with its argument, then 1.904 +our old transformation on compound statements extends to general compound 1.905 +expressions, i.e. PROG. 1.906 +</p> 1.907 +</div> 1.908 +</div> 1.909 + 1.910 +</div> 1.911 + 1.912 +<div id="outline-container-4" class="outline-2"> 1.913 +<h2 id="sec-4"><span class="section-number-2">4</span> Continuations </h2> 1.914 +<div class="outline-text-2" id="text-4"> 1.915 + 1.916 +<p>Up to now we have thought of SCHEME's LAMBDA expressions as functions, 1.917 +and of a combination such as <code>(G (F X Y))</code> as meaning ``apply the function F to 1.918 +the values of X and Y, and return a value so that the function G can be 1.919 +applied and return a value …'' But notice that we have seldom used LAMBDA 1.920 +expressions as functions. Rather, we have used them as control structures and 1.921 +environment modifiers. For example, consider the expression: 1.922 +<code>(BLOCK (PRINT 3) (PRINT 4))</code> 1.923 +</p> 1.924 +<p> 1.925 +This is defined to be an abbreviation for: 1.926 +<code>((LAMBDA (DUMMY) (PRINT 4)) (PRINT 3))</code> 1.927 +</p> 1.928 +<p> 1.929 +We do not care about the value of this BLOCK expression; it follows that we 1.930 +do not care about the value of the <code>(LAMBDA (DUMMY) ...)</code>. We are not using 1.931 +LAMBDA as a function at all. 1.932 +</p> 1.933 +<p> 1.934 +It is possible to write useful programs in terms of LAHBDA expressions 1.935 +in which we never care about the value of <i>any</i> lambda expression. We have 1.936 +already demonstrated how one could represent any "FORTRAN" program in these 1.937 +terms: all one needs is PROG (with G0 and SETQ), and PRINT to get the answers 1.938 +out. The ultimate generalization of this imperative programing style is 1.939 +<i>continuation-passing</i>. (Note Churchwins} . 1.940 +</p> 1.941 + 1.942 +</div> 1.943 + 1.944 +<div id="outline-container-4-1" class="outline-3"> 1.945 +<h3 id="sec-4-1"><span class="section-number-3">4.1</span> Continuation-Passing Recursion </h3> 1.946 +<div class="outline-text-3" id="text-4-1"> 1.947 + 1.948 +<p>Consider the following alternative definition of FACT. It has an extra 1.949 +argument, the continuation, which is a function to call with the answer, when 1.950 +we have it, rather than return a value 1.951 +</p> 1.952 + 1.953 + 1.954 + 1.955 +<pre class="src src-algol.">procedure Inc!(n, c); value n, c; 1.956 +integer n: procedure c(integer value); 1.957 +if n-=0 then c(l) else 1.958 +begin 1.959 +procedure l(!mp(d) value a: integer a; 1.960 +c(mm); 1.961 +Iacl(n-1, romp): 1.962 +end; 1.963 + 1.964 +</pre> 1.965 + 1.966 + 1.967 + 1.968 + 1.969 + 1.970 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'categorical.imperative) 1.971 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">fact-cps</span>[n k] 1.972 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (zero? n) (k 1) 1.973 + (<span style="color: #f0dfaf; font-weight: bold;">recur</span> (<span style="color: #8cd0d3;">dec</span> n) (<span style="color: #8cd0d3;">fn</span>[a] (k (<span style="color: #8cd0d3;">*</span> n a)))))) 1.974 + 1.975 +</pre> 1.976 + 1.977 + 1.978 +<p> 1.979 + clojure 1.980 +It is fairly clumsy to use this version of‘ FACT in ALGOL; it is necessary to 1.981 +do something like this: 1.982 +</p> 1.983 + 1.984 + 1.985 + 1.986 +<pre class="src src-algol">begin 1.987 +integer ann 1.988 +procedure :emp(x); value 2:; integer x; 1.989 +ans :1 x; 1.990 +]'act(3. temp); 1.991 +comment Now the variable <span style="color: #cc9393;">"am"</span> has 6; 1.992 +end; 1.993 + 1.994 +</pre> 1.995 + 1.996 + 1.997 + 1.998 + 1.999 +<p> 1.1000 +Procedure <code>fact</code> does not return a value, nor does <code>temp</code>; we must use a side 1.1001 +effect to get the answer out. 1.1002 +</p> 1.1003 +<p> 1.1004 +<code>FACT</code> is somewhat easier to use in SCHEME. We can call it like an 1.1005 +ordinary function in SCHEME if we supply an identity function as the second 1.1006 +argument. For example, <code>(FACT 3 (LAMBDA (X) X))</code> returns 6. Alternatively, we 1.1007 +could write <code>(FACT 3 (LAHBDA (X) (PRINT X)))</code>; we do not care about the value 1.1008 +of this, but about what gets printed. A third way to use the value is to 1.1009 +write 1.1010 +<code>(FACT 3 (LAMBDA (x) (SQRT x)))</code> 1.1011 +instead of 1.1012 +<code>(SQRT (FACT 3 (LAMBDA (x) x)))</code> 1.1013 +</p> 1.1014 +<p> 1.1015 +In either of these cases we care about the value of the continuation given to 1.1016 +FACT. Thus we care about the value of FACT if and only if we care about the 1.1017 +value of its continuation! 1.1018 +</p> 1.1019 +<p> 1.1020 +We can redefine other functions to take continuations in the same way. 1.1021 +For example, suppose we had arithmetic primitives which took continuations; to 1.1022 +prevent confusion, call the version of "+" which takes a continuation '++", 1.1023 +etc. Instead of writing 1.1024 +<code>(- (+ B Z)(* 4 A C))</code> 1.1025 +we can write 1.1026 +</p> 1.1027 + 1.1028 + 1.1029 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'categorical.imperative) 1.1030 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">enable-continuation</span> <span style="color: #8fb28f;">"Makes f take a continuation as an additional argument."</span>[f] 1.1031 + (<span style="color: #8cd0d3;">fn</span>[& args] ((<span style="color: #8cd0d3;">fn</span>[k] (k (<span style="color: #8cd0d3;">apply</span> f (<span style="color: #8cd0d3;">reverse</span> (<span style="color: #8cd0d3;">rest</span> (<span style="color: #8cd0d3;">reverse</span> args)))))) (<span style="color: #8cd0d3;">last</span> args)) )) 1.1032 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">+&</span> (enable-continuation +)) 1.1033 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">*&</span> (enable-continuation *)) 1.1034 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">-&</span> (enable-continuation -)) 1.1035 + 1.1036 + 1.1037 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">quadratic</span>[a b c k] 1.1038 +(*& b b 1.1039 + (<span style="color: #8cd0d3;">fn</span>[x] (*& 4 a c 1.1040 + (<span style="color: #8cd0d3;">fn</span>[y] 1.1041 + (-& x y k)))))) 1.1042 + 1.1043 +</pre> 1.1044 + 1.1045 + 1.1046 + 1.1047 + 1.1048 +<p> 1.1049 +where <code>k</code> is the continuation for the entire expression. 1.1050 +</p> 1.1051 +<p> 1.1052 +This is an obscure way to write an algebraic expression, and we would 1.1053 +not advise writing code this way in general, but continuation-passing brings 1.1054 +out certain important features of the computation: 1.1055 +</p><ul> 1.1056 +<li><sup><a class="footref" name="fnr.1" href="#fn.1">1</a></sup> The operations to be performed appear in the order in which they are 1.1057 +</li> 1.1058 +</ul> 1.1059 + 1.1060 +<p>performed. In fact, they <i>must</i> be performed in this 1.1061 +order. Continuation- passing removes the need for the rule about 1.1062 +left-to-right argument evaluation{Note Evalorder) 1.1063 +</p><ul> 1.1064 +<li><sup><a class="footref" name="fnr.2" href="#fn.2">2</a></sup> In the usual applicative expression there are two implicit 1.1065 + temporary values: those of <code>(* B B)</code> and <code>(* 4 A C)</code>. The first of 1.1066 + these values must be preserved over the computation of the second, 1.1067 + whereas the second is used as soon as it is produced. These facts 1.1068 + are <i>manifest</i> in the appearance and use of the variable X and Y in 1.1069 + the continuation-passing version. 1.1070 +</li> 1.1071 +</ul> 1.1072 + 1.1073 + 1.1074 +<p> 1.1075 +In short, the continuation-passing version specifies <i>exactly</i> and 1.1076 + explicitly what steps are necessary to compute the value of the 1.1077 + expression. One can think of conventional functional application 1.1078 + for value as being an abbreviation for the more explicit 1.1079 + continuation-passing style. Alternatively, one can think of the 1.1080 + interpreter as supplying to each function an implicit default 1.1081 + continuation of one argument. This continuation will receive the 1.1082 + value of the function as its argument, and then carry on the 1.1083 + computation. In an interpreter this implicit continuation is 1.1084 + represented by the control stack mechanism for function returns. 1.1085 + Now consider what computational steps are implied by: 1.1086 +</p> 1.1087 +<p> 1.1088 +<code>(LAMBDA (A B C ...) (F X Y Z ...))</code> when we "apply" the LAMBDA 1.1089 + expression we have some values to apply it to; we let the names A, 1.1090 + B, C … refer to these values. We then determine the values of X, 1.1091 + Y, Z … and pass these values (along with "the buck", 1.1092 + i.e. control!) to the lambda expression F (F is either a lambda 1.1093 + expression or a name for one). Passing control to F is an 1.1094 + unconditional transfer. (Note Jrsthack) {Note Hewitthack) Note that 1.1095 + we want values from X, Y, Z, … If these are simple expressions, 1.1096 + such as variables, constants, or LAMBDA expressions, the evaluation 1.1097 + process is trivial, in that no temporary storage is required. In 1.1098 + pure continuation-passing style, all evaluations are trivial: no 1.1099 + combination is nested within another, and therefore no ‘hidden 1.1100 + temporaries" are required. But if X is a combination, say (G P Q), 1.1101 + then we want to think of G as a function, because we want a value 1.1102 + from it, and we will need an implicit temporary place to keep the 1.1103 + result while evaluating Y and Z. (An interpreter usually keeps these 1.1104 + temporary places in the control stack!) On the other hand, we do not 1.1105 + necessarily need a value from F. This is what we mean by tail- 1.1106 + recursion: F is called tail-recursively, whereas G is not. A better 1.1107 + name for tail-recursion would be "tail-transfer", since no real 1.1108 + recursion is implied. This is why we have made such a fuss about 1.1109 + tail-recursion: it can be used for transfer of control without 1.1110 + making any commitment about whether the expression expected to 1.1111 + return a value. Thus it can be used to model statement-like control 1.1112 + structures. Put another way, tail—recursion does not require a 1.1113 + control stack as nested recursion does. In our models of iteration 1.1114 + and imperative style all the LAMBDA expressions used for control (to 1.1115 + simulate GO statements, for example) are called in tail-recursive 1.1116 + fashion. 1.1117 +</p> 1.1118 +</div> 1.1119 + 1.1120 +</div> 1.1121 + 1.1122 +<div id="outline-container-4-2" class="outline-3"> 1.1123 +<h3 id="sec-4-2"><span class="section-number-3">4.2</span> Escape Expressions </h3> 1.1124 +<div class="outline-text-3" id="text-4-2"> 1.1125 + 1.1126 +<p>Reynolds [Reynolds 72] defines the construction 1.1127 += escape x in r = 1.1128 +</p> 1.1129 +<p> 1.1130 +to evaluate the expression \(r\) in an environment such that the variable \(x\) is 1.1131 +bound to an escape function. If the escape function is never applied, then 1.1132 +the value of the escape expression is the value of \(r\). If the escape function 1.1133 +is applied to an argument \(a\), however, then evaluation of \(r\) is aborted and the 1.1134 +escape expression returns \(a\). {Note J-operator} (Reynolds points out that 1.1135 +this definition is not quite accurate, since the escape function may be called 1.1136 +even after the escape expression has returned a value; if this happens, it 1.1137 +“returns again"!) 1.1138 +</p> 1.1139 +<p> 1.1140 +As an example of the use of an escape expression, consider this 1.1141 +procedure to compute the harmonic mean of an array of numbers. If any of the 1.1142 +numbers is zero, we want the answer to be zero. We have a function hannaunl 1.1143 +which will sum the reciprocals of numbers in an array, or call an escape 1.1144 +function with zero if any of the numbers is zero. (The implementation shown 1.1145 +here is awkward because ALGOL requires that a function return its value by 1.1146 +assignment.) 1.1147 +</p> 1.1148 + 1.1149 + 1.1150 +<pre class="src src-algol">begin 1.1151 +real procedure Imrmsum(a, n. escfun)§ p 1.1152 +real array at integer n; real procedure esciun(real); 1.1153 +begin 1.1154 +real sum; 1.1155 +sum := 0; 1.1156 +for i :1 0 until n-l do 1.1157 +begin 1.1158 +if a[i]=0 then cscfun(0); 1.1159 +sum :1 sum ¢ I/a[i]; 1.1160 +enm 1.1161 +harmsum SI sum; 1.1162 +end: . 1.1163 +real array b[0:99]: 1.1164 +print(escape x in I00/hm-m.mm(b, 100, x)); 1.1165 +end 1.1166 + 1.1167 +</pre> 1.1168 + 1.1169 + 1.1170 + 1.1171 + 1.1172 +<p> 1.1173 +If harmsum exits normally, the number of elements is divided by the sum and 1.1174 +printed. Otherwise, zero is returned from the escape expression and printed 1.1175 +without the division ever occurring. 1.1176 +This program can be written in SCHEME using the built-in escape 1.1177 +operator <code>CATCH</code>: 1.1178 +</p> 1.1179 + 1.1180 + 1.1181 + 1.1182 +<pre class="src src-clojure">abc 1.1183 + 1.1184 +</pre> 1.1185 + 1.1186 + 1.1187 + 1.1188 +<div id="footnotes"> 1.1189 +<h2 class="footnotes">Footnotes: </h2> 1.1190 +<div id="text-footnotes"> 1.1191 +<p class="footnote"><sup><a class="footnum" name="fn.1" href="#fnr.1">1</a></sup> DEFINITION NOT FOUND: 1 1.1192 +</p> 1.1193 + 1.1194 +<p class="footnote"><sup><a class="footnum" name="fn.2" href="#fnr.2">2</a></sup> DEFINITION NOT FOUND: 2 1.1195 +</p> 1.1196 +</div> 1.1197 +</div> 1.1198 +</div> 1.1199 + 1.1200 +</div> 1.1201 +</div> 1.1202 +<div id="postamble"> 1.1203 +<p class="date">Date: 2011-07-15 02:49:04 EDT</p> 1.1204 +<p class="author">Author: Guy Lewis Steele Jr. and Gerald Jay Sussman</p> 1.1205 +<p class="creator">Org version 7.6 with Emacs version 23</p> 1.1206 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 1.1207 +</div> 1.1208 +</div> 1.1209 +</body> 1.1210 +</html>
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/categorical/imperative.org Fri Oct 28 00:03:05 2011 -0700 2.3 @@ -0,0 +1,772 @@ 2.4 +#+TITLE: LAMBDA: The Ultimate Imperative 2.5 +#+AUTHOR: Guy Lewis Steele Jr. and Gerald Jay Sussman 2.6 + 2.7 +* Abstract 2.8 + 2.9 +We demonstrate how to model the following common programming constructs in 2.10 +terms of an applicative order language similar to LISP: 2.11 +- Simple Recursion 2.12 +- Iteration 2.13 +- Compound Statements and Expressions 2.14 +- GO TO and Assignment 2.15 +- Continuation—Passing 2.16 +- Escape Expressions 2.17 +- Fluid Variables 2.18 +- Call by Name, Call by Need, and Call by Reference 2.19 +The models require only (possibly self-referent) lambda application, 2.20 +conditionals, and (rarely) assignment. No complex data structures such as 2.21 +stacks are used. The models are transparent, involving only local syntactic 2.22 +transformations. 2.23 +Some of these models, such as those for GO TO and assignment, are already well 2.24 +known, and appear in the work of Landin, Reynolds, and others. The models for 2.25 +escape expressions, fluid variables, and call by need with side effects are 2.26 +new. This paper is partly tutorial in intent, gathering all the models 2.27 +together for purposes of context. 2.28 +This report describes research done at the Artificial Intelligence Laboratory 2.29 +of the Massachusetts Institute of Teehnology. Support for the laboratory's 2.30 +artificial intelligence research is provided in part by the Advanced Research 2.31 +Projects Agency of the Department of Defense under Office of Naval Research 2.32 +contract N000l4-75-C-0643. 2.33 + 2.34 +* Introduction 2.35 + 2.36 + We catalogue a number of common programming constructs. For each 2.37 +construct we examine "typical" usage in well-known programming languages, and 2.38 +then capture the essence of the semantics of the construct in terms of a 2.39 +common meta-language. 2.40 +The lambda calculus {Note Alonzowins} is often used as such a meta- 2.41 +language. Lambda calculus offers clean semantics, but it is clumsy because it 2.42 +was designed to be a minimal language rather than a convenient one. All 2.43 +lambda calculus "functions" must take exactly one "argument"; the only "data 2.44 +type" is lambda expressions; and the only "primitive operation‘ is variable‘ 2.45 +substitution. While its utter simplicity makes lambda calculus ideal for 2.46 +logicians, it is too primitive for use by programmers. The meta-language we 2.47 +use is a programming language called SCHEME {Note Schemepaper) which is based 2.48 +on lambda calculus. 2.49 +SCHEME is a dialect of LISP. [McCarthy 62] It is an expression- 2.50 +oriented, applicative order, interpreter-based language which allows one to 2.51 +manipulate programs as data. It differs from most current dialects of LISP in 2.52 +that it closes all lambda expressions in the environment of their definition 2.53 +or declaration, rather than in the execution environment. {Note Closures} 2.54 +This preserves the substitution semantics of lambda calculus, and has the 2.55 +consequence that all variables are lexically scoped, as in ALGOL. [Naur 63] 2.56 +Another difference is that SCHEME is implemented in such a way that tail- 2.57 +recursions execute without net growth of the interpreter stack. {Note 2.58 +Schemenote} We have chosen to use LISP syntax rather than, say, ALGOL syntax 2.59 +because we want to treat programs as data for the purpose of describing 2.60 +transformations on the code. LISP supplies names for the parts of an 2.61 +executable expression and standard operators for constructing expressions and 2.62 +extracting their components. The use of LISP syntax makes the structure of 2.63 +such expressions manifest. We use ALGOL as an expository language, because it 2.64 +is familiar to many people, but ALGOL is not sufficiently powerful to express 2.65 +the necessary concepts; in particular, it does not allow functions to return 2.66 +functions as values. we are thus forced to use a dialect of LISP in many 2.67 +cases. 2.68 +We will consider various complex programming language constructs and 2.69 +show how to model them in terms of only a few simple ones. As far as possible 2.70 +we will use only three control constructs from SCHEME: LAMBDA expressions, as 2.71 +in LISP, which are Just functions with lexically scoped free variables; 2.72 +LABELS, which allows declaration of mutually recursive procedures (Note 2.73 +Labelsdef}; and IF, a primitive conditional expression. For more complex 2.74 +modelling we will introduce an assignment primitive (ASET).i We will freely 2.75 +assume the existence of other comon primitives, such as arithmetic functions. 2.76 +The constructs we will examine are divided into four broad classes. 2.77 +The first is sfinph?Lo0pl; this contains simple recursions and iterations, and 2.78 +an introduction to the notion of continuations. The second is hmponflivo 2.79 +Connrucls; this includes compound statements, G0 T0, and simple variable 2.80 +assignments. The third is continuations, which encompasses the distinction between statements and expressions, escape operators (such as Landin's J- 2.81 +operator [Landin 65] and Reynold's escape expression [Reynolds 72]). and fluid 2.82 +(dynamically bound) variables. The fourth is Parameter Passing Mechanisms, such 2.83 +as ALGOL call—by-name and FORTRAN call-by-location. 2.84 +Some of the models presented here are already well-known, particularly 2.85 +those for G0 T0 and assignment. [McCarthy 60] [Landin 65] [Reynolds 72] 2.86 +Those for escape operators, fluid variables, and call-by-need with side 2.87 +effects are new. 2.88 +** Simple Loops 2.89 +By /simple loops/ we mean constructs which enable programs to execute the 2.90 +same piece of code repeatedly in a controlled manner. Variables may be made 2.91 +to take on different values during each repetition, and the number of 2.92 +repetitions may depend on data given to the program. 2.93 +*** Simple Recursion 2.94 +One of the easiest ways to produce a looping control structure is to 2.95 +use a recursive function, one which calls itself to perform a subcomputation. 2.96 +For example, the familiar factorial function may be written recursively in 2.97 +ALGOL: ' 2.98 +#+begin_src algol 2.99 +integer procedure fact(n) value n: integer n: 2.100 +fact := if n=0 then 1 else n*fact(n-1); 2.101 +#+end_src 2.102 + 2.103 +The invocation =fact(n)= computes the product of the integers from 1 to n using 2.104 +the identity n!=n(n-1)! (n>0). If $n$ is zero, 1 is returned; otherwise =fact=: 2.105 +calls itself recursively to compute $(n-1)!$ , then multiplies the result by $n$ 2.106 +and returns it. 2.107 + 2.108 +This same function may be written in Clojure as follows: 2.109 +#+begin_src clojure 2.110 +(ns categorical.imperative) 2.111 +(defn fact[n] 2.112 + (if (= n 0) 1 (* n (fact (dec n)))) 2.113 +) 2.114 +#+end_src 2.115 + 2.116 +#+results: 2.117 +: #'categorical.imperative/fact 2.118 + 2.119 +Clojure does not require an assignment to the ``variable'' fan: to return a value 2.120 +as ALGOL does. The IF primitive is the ALGOL if-then-else rendered in LISP 2.121 +syntax. Note that the arithmetic primitives are prefix operators in SCHEME. 2.122 + 2.123 +*** Iteration 2.124 +There are many other ways to compute factorial. One important way is 2.125 +through the use of /iteration/. 2.126 +A comon iterative construct is the DO loop. The most general form we 2.127 +have seen in any programming language is the MacLISP DO [Moon 74]. It permits 2.128 +the simultaneous initialization of any number of control variables and the 2.129 +simultaneous stepping of these variables by arbitrary functions at each 2.130 +iteration step. The loop is terminated by an arbitrary predicate, and an 2.131 +arbitrary value may be returned. The DO loop may have a body, a series of 2.132 +expressions executed for effect on each iteration. A version of the MacLISP 2.133 +DO construct has been adopted in SCHEME. 2.134 + 2.135 +The general form of a SCHEME DO is: 2.136 +#+begin_src nothing 2.137 +(DO ((<var1> (init1> <stepl>) 2.138 +((var2> <init2> <step2>) 2.139 +(<varn> <intn> (stepn>)) 2.140 +(<pred> (value>) 2.141 +(optional body>) 2.142 +#+end_src 2.143 +The semantics of this are that the variables are bound and initialized to the 2.144 +values of the <initi> expressions, which must all be evaluated in the 2.145 +environment outside the D0; then the predicate <pred> is evaluated in the new 2.146 +environment, and if TRUE, the (value) is evaluated and returned. Otherwise 2.147 +the (optional body) is evaluated, then each of the steppers <stepi> is 2.148 +evaluated in the current environment, all the variables made to have the 2.149 +results as their values, the predicate evaluated again, and so on. 2.150 +Using D0 loops in both ALGOL and SCHEME, we may express FACT by means 2.151 +of iteration. 2.152 +#+begin_src algol 2.153 +integer procedure fact(n); value n; integer n: 2.154 +begin 2.155 +integer m, ans; 2.156 +ans := 1; 2.157 +for m := n step -l until 0 do ans := m*ans; 2.158 +fact := ans; 2.159 +end; 2.160 +#+end_src 2.161 + 2.162 +#+begin_src clojure 2.163 +(in-ns 'categorical.imperative) 2.164 +(defn fact-do[n] 2.165 +) 2.166 +#+end_src 2.167 + 2.168 +Note that the SCHEME D0 loop in FACT has no body -- the stepping functions do 2.169 +all the work. The ALGOL DO loop has an assignment in its body; because an 2.170 +ALGOL DO loop can step only one variable, we need the assignment to step the 2.171 +the variable "manually'. 2.172 +In reality the SCHEME DO construct is not a primitive; it is a macro 2.173 +which expands into a function which performs the iteration by tail—recursion. 2.174 +Consider the following definition of FACT in SCHEME. Although it appears to 2.175 +be recursive, since it "calls itself", it is entirely equivalent to the DO 2.176 +loop given above, for it is the code that the DO macro expands into! It 2.177 +captures the essence of our intuitive notion of iteration, because execution 2.178 +of this program will not produce internal structures (e.g. stacks or variable 2.179 +bindings) which increase in size with the number of iteration steps. 2.180 + 2.181 +#+begin_src clojure 2.182 +(in-ns 'categorical.imperative) 2.183 +(defn fact-do-expand[n] 2.184 + (let [fact1 2.185 + (fn[m ans] 2.186 + (if (zero? m) ans 2.187 + (recur (dec m) (* m ans))))] 2.188 + (fact1 n 1))) 2.189 +#+end_src 2.190 + 2.191 +From this we can infer a general way to express iterations in SCHEME in 2.192 +a manner isomorphic to the HacLISP D0. The expansion of the general D0 loop 2.193 +#+begin_src nothing 2.194 +(DO ((<varl> <init1> <step1>) 2.195 +(<var2> (init2) <step2>) 2.196 +... 2.197 +(<varn> <initn> <stepn>)) 2.198 +(<pred> <va1ue>) 2.199 +<body>) 2.200 +#+end_src 2.201 +is this: 2.202 +#+begin_src nothing 2.203 +(let [doloop 2.204 +(fn [dummy <var1> <var2> ... <varn>) 2.205 +(if <pred> <value> 2.206 +(recur <body> <step1> <step2> ... <stepn>)))] 2.207 + 2.208 +(doloop nil <init1> <init2> ... <initn>)) 2.209 +#+end_src 2.210 +The identifiers =doloop= and =dummy= are chosen so as not to conflict with any 2.211 +other identifiers in the program. 2.212 +Note that, unlike most implementations of D0, there are no side effects 2.213 +in the steppings of the iteration variables. D0 loops are usually modelled 2.214 +using assignment statements. For example: 2.215 +#+begin_src nothing 2.216 +for r :1 0 step b until c do <statement>; 2.217 +#+end_src 2.218 + 2.219 +can be modelled as follows: [Naur 63] 2.220 +#+begin_src nothing 2.221 +begin 2.222 +x := a; 2.223 +L: if (x-c)*sign(n) > 0 then go to Endloop; 2.224 +<statement>; 2.225 +x := x+b; 2.226 +go to L: 2.227 +Endloop: 2.228 +end; 2.229 +#+end_src 2.230 +Later we will see how such assignment statements can in general be 2.231 +modelled without using side effects. 2.232 + 2.233 +* Imperative Programming 2.234 +Lambda calculus (and related languages, such as ``pure LISP'') is often 2.235 +used for modelling the applicative constructs of programming languages. 2.236 +However, they are generally thought of as inappropriate for modelling 2.237 +imperative constructs. In this section we show how imperative constructs may 2.238 +be modelled by applicative SCHEME constructs. 2.239 +** Compound Statements 2.240 +The simplest kind of imperative construct is the statement sequencer, 2.241 +for example the compound statement in ALGOL: 2.242 +#+begin_src algol 2.243 +begin 2.244 +S1; 2.245 +S2; 2.246 +end 2.247 +#+end_src 2.248 + 2.249 +This construct has two interesting properties: 2.250 +- (1) It performs statement S1 before S2, and so may be used for 2.251 + sequencing. 2.252 +- (2) S1 is useful only for its side effects. (In ALGOL, S2 must also 2.253 + be a statement, and so is also useful only for side effects, but 2.254 + other languages have compound expressions containing a statement 2.255 + followed by an expression.) 2.256 + 2.257 +The ALGOL compound statement may actually contain any number of statements, 2.258 +but such statements can be expressed as a series of nested two-statement 2.259 +compounds. That is: 2.260 +#+begin_src algol 2.261 +begin 2.262 +S1; 2.263 +S2; 2.264 +... 2.265 +Sn-1; 2.266 +Sn; 2.267 +end 2.268 +#+end_src 2.269 +is equivalent to: 2.270 + 2.271 +#+begin_src algol 2.272 +begin 2.273 +S1; 2.274 +begin 2.275 +S2; 2.276 +begin 2.277 +... 2.278 + 2.279 +begin 2.280 +Sn-1; 2.281 +Sn; 2.282 +end; 2.283 +end; 2.284 +end: 2.285 +end 2.286 +#+end_src 2.287 + 2.288 +It is not immediately apparent that this sequencing can be expressed in a 2.289 +purely applicative language. We can, however, take advantage of the implicit 2.290 +sequencing of applicative order evaluation. Thus, for example, we may write a 2.291 +two-statement sequence as follows: 2.292 + 2.293 +#+begin_src clojure 2.294 +((fn[dummy] S2) S1) 2.295 +#+end_src 2.296 + 2.297 +where =dummy= is an identifier not used in S2. From this it is 2.298 +manifest that the value of S1 is ignored, and so is useful only for 2.299 +side effects. (Note that we did not claim that S1 is expressed in a 2.300 +purely applicative language, but only that the sequencing can be so 2.301 +expressed.) From now on we will use the form =(BLOCK S1 S2)= as an 2.302 +abbreviation for this expression, and =(BLOCK S1 S2...Sn-1 Sn)= as an 2.303 +abbreviation for 2.304 + 2.305 +#+begin_src algol 2.306 +(BLOCK S1 (BLOCK S2 (BLOCK ... (BLOCK Sn-1 Sn)...))) 2.307 +#+end_src 2.308 + 2.309 +** 2.2. The G0 TO Statement 2.310 + 2.311 +A more general imperative structure is the compound statement with 2.312 +labels and G0 T0s. Consider the following code fragment due to 2.313 +Jacopini, taken from Knuth: [Knuth 74] 2.314 +#+begin_src algol 2.315 +begin 2.316 +L1: if B1 then go to L2; S1; 2.317 + if B2 then go to L2; S2; 2.318 + go to L1; 2.319 +L2: S3; 2.320 +#+end_src 2.321 + 2.322 +It is perhaps surprising that this piece of code can be /syntactically/ 2.323 +transformed into a purely applicative style. For example, in SCHEME we 2.324 +could write: 2.325 + 2.326 +#+begin_src clojure 2.327 +(in-ns 'categorical.imperative) 2.328 +(let 2.329 + [L1 (fn[] 2.330 + (if B1 (L2) (do S1 2.331 + (if B2 (L2) (do S2 (L1)))))) 2.332 + L2 (fn[] S3)] 2.333 + (L1)) 2.334 +#+end_src 2.335 + 2.336 +As with the D0 loop, this transformation depends critically on SCHEME's 2.337 +treatment of tail-recursion and on lexical scoping of variables. The labels 2.338 +are names of functions of no arguments. In order to ‘go to" the labeled code, 2.339 +we merely call the function named by that label. 2.340 + 2.341 +** 2.3. Simple Assignment 2.342 +Of course, all this sequencing of statements is useless unless the 2.343 +statements have side effects. An important side effect is assignment. For 2.344 +example, one often uses assignment to place intermediate results in a named 2.345 +location (i.e. a variable) so that they may be used more than once later 2.346 +without recomputing them: 2.347 + 2.348 +#+begin_src algol 2.349 +begin 2.350 +real a2, sqrtdisc; 2.351 +a2 := 2*a; 2.352 +sqrtdisc := sqrt(b^2 - 4*a*c); 2.353 +root1 := (- b + sqrtdisc) / a2; 2.354 +root2 := (- b - sqrtdisc) / a2; 2.355 +print(root1); 2.356 +print(root2); 2.357 +print(root1 + root2); 2.358 +end 2.359 +#+end_src 2.360 + 2.361 +It is well known that such naming of intermediate results may be accomplished 2.362 +by calling a function and binding the formal parameter variables to the 2.363 +results: 2.364 + 2.365 +#+begin_src clojure 2.366 +(fn [a2 sqrtdisc] 2.367 + ((fn[root1 root2] 2.368 + (do (println root1) 2.369 + (println root2) 2.370 + (println (+ root1 root2)))) 2.371 + (/ (+ (- b) sqrtdisc) a2) 2.372 + (/ (- (- b) sqrtdisc) a2)) 2.373 + 2.374 + (* 2 a) 2.375 + (sqrt (- (* b b) (* 4 a c)))) 2.376 +#+end_src 2.377 +This technique can be extended to handle all simple variable assignments which 2.378 +appear as statements in blocks, even if arbitrary G0 T0 statements also appear 2.379 +in such blocks. {Note Mccarthywins} 2.380 + 2.381 +For example, here is a program which uses G0 TO statements in the form 2.382 +presented before; it determines the parity of a non-negative integer by 2.383 +counting it down until it reaches zero. 2.384 + 2.385 +#+begin_src algol 2.386 +begin 2.387 +L1: if a = 0 then begin parity := 0; go to L2; end; 2.388 + a := a - 1; 2.389 + if a = 0 then begin parity := 1; go to L2; end; 2.390 + a := a - 1; 2.391 + go to L1; 2.392 +L2: print(parity); 2.393 +#+end_src 2.394 + 2.395 +This can be expressed in SCHEME: 2.396 + 2.397 +#+begin_src clojure 2.398 +(let 2.399 + [L1 (fn [a parity] 2.400 + (if (zero? a) (L2 a 0) 2.401 + (L3 (dec a) parity))) 2.402 + L3 (fn [a parity] 2.403 + (if (zero? a) (L2 a 1) 2.404 + (L1 (dec a) parity))) 2.405 + L2 (fn [a parity] 2.406 + (println parity))] 2.407 + (L1 a parity)) 2.408 +#+end_src 2.409 + 2.410 +The trick is to pass the set of variables which may be altered as arguments to 2.411 +the label functions. {Note Flowgraph} It may be necessary to introduce new 2.412 +labels (such as L3) so that an assignment may be transformed into the binding 2.413 +for a function call. At worst, one may need as many labels as there are 2.414 +statements (not counting the eliminated assignment and GO TO statements). 2.415 + 2.416 +** Compound Expressions ' 2.417 +At this point we are almost in a position to model the most general 2.418 +form of compound statement. In LISP, this is called the 'PROG feature". In 2.419 +addition to statement sequencing and G0 T0 statements, one can return a /value/ 2.420 +from a PROG by using the RETURN statement. 2.421 + 2.422 +Let us first consider the simplest compound statement, which in SCHEME 2.423 +we call BLOCK. Recall that 2.424 +=(BLOCK s1 sz)= is defined to be =((lambda (dummy) s2) s1)= 2.425 + 2.426 +Notice that this not only performs Sl before S2, but also returns the value of 2.427 +S2. Furthermore, we defined =(BLOCK S1 S2 ... Sn)= so that it returns the value 2.428 +of =Sn=. Thus BLOCK may be used as a compound expression, and models a LISP 2.429 +PROGN, which is a PROG with no G0 T0 statements and an implicit RETURN of the 2.430 +last ``statement'' (really an expression). 2.431 + 2.432 +Host LISP compilers compile D0 expressions by macro-expansion. We have 2.433 +already seen one way to do this in SCHEME using only variable binding. A more 2.434 +common technique is to expand the D0 into a PROG, using variable assignments 2.435 +instead of bindings. Thus the iterative factorial program: 2.436 + 2.437 +#+begin_src clojure 2.438 +(oarxnz FACT . 2.439 +(LAMaoA (n) . 2.440 +(D0 ((M N (- H 1)) 2.441 +(Ans 1 (* M Ans))) 2.442 +((- H 0) A"$)))) 2.443 +#+end_src 2.444 + 2.445 +would expand into: 2.446 + 2.447 +#+begin_src clojure 2.448 +(DEFINE FACT 2.449 +. (LAMeoA (M) 2.450 +(PRO6 (M Ans) 2.451 +(sszro M n 2.452 +Ans 1) ~ 2.453 +LP (tr (- M 0) (RETURN Ans)) 2.454 +(ssero M (- n 1) 2.455 +Ans (' M Ans)) 2.456 +(60 LP)))) 2.457 +#+end_src 2.458 + 2.459 +where SSETQ is a simultaneous multiple assignment operator. (SSETQ is not a 2.460 +SCHEME (or LISP) primitive. It can be defined in terms of a single assignment 2.461 +operator, but we are more interested here in RETURN than in simultaneous 2.462 +assignment. The SSETQ's will all be removed anyway and modelled by lambda 2.463 +binding.) We can apply the same technique we used before to eliminate G0 T0 2.464 +statements and assignments from compound statements: 2.465 + 2.466 +#+begin_src clojure 2.467 +(DEFINE FACT 2.468 +(LAHBOA (I) 2.469 +(LABELS ((L1 (LAManA (M Ans) 2.470 +(LP n 1))) 2.471 +(LP (LAMaoA (M Ans) 2.472 +(IF (- M o) (nztunn Ans) 2.473 +(£2 H An$)))) 2.474 +(L2 (LAMaoA (M An ) 2.475 +(LP (- " 1) (' H flN$))))) 2.476 +(L1 NIL NlL)))) 2.477 +#+end_src clojure 2.478 + 2.479 +We still haven't done anything about RETURN. Let's see... 2.480 +- ==> the value of (FACT 0) is the value of (Ll NIL NIL) 2.481 +- ==> which is the value of (LP 0 1) 2.482 +- ==> which is the value of (IF (= 0 0) (RETURN 1) (L2 0 1)) 2.483 +- ==> which is the value of (RETURN 1) 2.484 + 2.485 +Notice that if RETURN were the /identity 2.486 +function/ (LAMBDA (X) X), we would get the right answer. This is in fact a 2.487 +general truth: if we Just replace a call to RETURN with its argument, then 2.488 +our old transformation on compound statements extends to general compound 2.489 +expressions, i.e. PROG. 2.490 + 2.491 +* Continuations 2.492 +Up to now we have thought of SCHEME's LAMBDA expressions as functions, 2.493 +and of a combination such as =(G (F X Y))= as meaning ``apply the function F to 2.494 +the values of X and Y, and return a value so that the function G can be 2.495 +applied and return a value ...'' But notice that we have seldom used LAMBDA 2.496 +expressions as functions. Rather, we have used them as control structures and 2.497 +environment modifiers. For example, consider the expression: 2.498 +=(BLOCK (PRINT 3) (PRINT 4))= 2.499 + 2.500 +This is defined to be an abbreviation for: 2.501 +=((LAMBDA (DUMMY) (PRINT 4)) (PRINT 3))= 2.502 + 2.503 +We do not care about the value of this BLOCK expression; it follows that we 2.504 +do not care about the value of the =(LAMBDA (DUMMY) ...)=. We are not using 2.505 +LAMBDA as a function at all. 2.506 + 2.507 +It is possible to write useful programs in terms of LAHBDA expressions 2.508 +in which we never care about the value of /any/ lambda expression. We have 2.509 +already demonstrated how one could represent any "FORTRAN" program in these 2.510 +terms: all one needs is PROG (with G0 and SETQ), and PRINT to get the answers 2.511 +out. The ultimate generalization of this imperative programing style is 2.512 +/continuation-passing/. (Note Churchwins} . 2.513 + 2.514 +** Continuation-Passing Recursion 2.515 +Consider the following alternative definition of FACT. It has an extra 2.516 +argument, the continuation, which is a function to call with the answer, when 2.517 +we have it, rather than return a value 2.518 + 2.519 +#+begin_src algol. 2.520 +procedure Inc!(n, c); value n, c; 2.521 +integer n: procedure c(integer value); 2.522 +if n-=0 then c(l) else 2.523 +begin 2.524 +procedure l(!mp(d) value a: integer a; 2.525 +c(mm); 2.526 +Iacl(n-1, romp): 2.527 +end; 2.528 +#+end_src 2.529 + 2.530 +#+begin_src clojure 2.531 +(in-ns 'categorical.imperative) 2.532 +(defn fact-cps[n k] 2.533 + (if (zero? n) (k 1) 2.534 + (recur (dec n) (fn[a] (k (* n a)))))) 2.535 +#+end_src clojure 2.536 +It is fairly clumsy to use this version of‘ FACT in ALGOL; it is necessary to 2.537 +do something like this: 2.538 + 2.539 +#+begin_src algol 2.540 +begin 2.541 +integer ann 2.542 +procedure :emp(x); value 2:; integer x; 2.543 +ans :1 x; 2.544 +]'act(3. temp); 2.545 +comment Now the variable "am" has 6; 2.546 +end; 2.547 +#+end_src 2.548 + 2.549 +Procedure =fact= does not return a value, nor does =temp=; we must use a side 2.550 +effect to get the answer out. 2.551 + 2.552 +=FACT= is somewhat easier to use in SCHEME. We can call it like an 2.553 +ordinary function in SCHEME if we supply an identity function as the second 2.554 +argument. For example, =(FACT 3 (LAMBDA (X) X))= returns 6. Alternatively, we 2.555 +could write =(FACT 3 (LAHBDA (X) (PRINT X)))=; we do not care about the value 2.556 +of this, but about what gets printed. A third way to use the value is to 2.557 +write 2.558 +=(FACT 3 (LAMBDA (x) (SQRT x)))= 2.559 +instead of 2.560 +=(SQRT (FACT 3 (LAMBDA (x) x)))= 2.561 + 2.562 +In either of these cases we care about the value of the continuation given to 2.563 +FACT. Thus we care about the value of FACT if and only if we care about the 2.564 +value of its continuation! 2.565 + 2.566 +We can redefine other functions to take continuations in the same way. 2.567 +For example, suppose we had arithmetic primitives which took continuations; to 2.568 +prevent confusion, call the version of "+" which takes a continuation '++", 2.569 +etc. Instead of writing 2.570 +=(- (+ B Z)(* 4 A C))= 2.571 +we can write 2.572 +#+begin_src clojure 2.573 +(in-ns 'categorical.imperative) 2.574 +(defn enable-continuation "Makes f take a continuation as an additional argument."[f] 2.575 + (fn[& args] ((fn[k] (k (apply f (reverse (rest (reverse args)))))) (last args)) )) 2.576 +(def +& (enable-continuation +)) 2.577 +(def *& (enable-continuation *)) 2.578 +(def -& (enable-continuation -)) 2.579 + 2.580 + 2.581 +(defn quadratic[a b c k] 2.582 +(*& b b 2.583 + (fn[x] (*& 4 a c 2.584 + (fn[y] 2.585 + (-& x y k)))))) 2.586 +#+end_src 2.587 + 2.588 +where =k= is the continuation for the entire expression. 2.589 + 2.590 +This is an obscure way to write an algebraic expression, and we would 2.591 +not advise writing code this way in general, but continuation-passing brings 2.592 +out certain important features of the computation: 2.593 + - [1] The operations to be performed appear in the order in which they are 2.594 +performed. In fact, they /must/ be performed in this 2.595 +order. Continuation- passing removes the need for the rule about 2.596 +left-to-right argument evaluation{Note Evalorder) 2.597 +- [2] In the usual applicative expression there are two implicit 2.598 + temporary values: those of =(* B B)= and =(* 4 A C)=. The first of 2.599 + these values must be preserved over the computation of the second, 2.600 + whereas the second is used as soon as it is produced. These facts 2.601 + are /manifest/ in the appearance and use of the variable X and Y in 2.602 + the continuation-passing version. 2.603 + 2.604 +In short, the continuation-passing version specifies /exactly/ and 2.605 + explicitly what steps are necessary to compute the value of the 2.606 + expression. One can think of conventional functional application 2.607 + for value as being an abbreviation for the more explicit 2.608 + continuation-passing style. Alternatively, one can think of the 2.609 + interpreter as supplying to each function an implicit default 2.610 + continuation of one argument. This continuation will receive the 2.611 + value of the function as its argument, and then carry on the 2.612 + computation. In an interpreter this implicit continuation is 2.613 + represented by the control stack mechanism for function returns. 2.614 + Now consider what computational steps are implied by: 2.615 + 2.616 +=(LAMBDA (A B C ...) (F X Y Z ...))= when we "apply" the LAMBDA 2.617 + expression we have some values to apply it to; we let the names A, 2.618 + B, C ... refer to these values. We then determine the values of X, 2.619 + Y, Z ... and pass these values (along with "the buck", 2.620 + i.e. control!) to the lambda expression F (F is either a lambda 2.621 + expression or a name for one). Passing control to F is an 2.622 + unconditional transfer. (Note Jrsthack) {Note Hewitthack) Note that 2.623 + we want values from X, Y, Z, ... If these are simple expressions, 2.624 + such as variables, constants, or LAMBDA expressions, the evaluation 2.625 + process is trivial, in that no temporary storage is required. In 2.626 + pure continuation-passing style, all evaluations are trivial: no 2.627 + combination is nested within another, and therefore no ‘hidden 2.628 + temporaries" are required. But if X is a combination, say (G P Q), 2.629 + then we want to think of G as a function, because we want a value 2.630 + from it, and we will need an implicit temporary place to keep the 2.631 + result while evaluating Y and Z. (An interpreter usually keeps these 2.632 + temporary places in the control stack!) On the other hand, we do not 2.633 + necessarily need a value from F. This is what we mean by tail- 2.634 + recursion: F is called tail-recursively, whereas G is not. A better 2.635 + name for tail-recursion would be "tail-transfer", since no real 2.636 + recursion is implied. This is why we have made such a fuss about 2.637 + tail-recursion: it can be used for transfer of control without 2.638 + making any commitment about whether the expression expected to 2.639 + return a value. Thus it can be used to model statement-like control 2.640 + structures. Put another way, tail—recursion does not require a 2.641 + control stack as nested recursion does. In our models of iteration 2.642 + and imperative style all the LAMBDA expressions used for control (to 2.643 + simulate GO statements, for example) are called in tail-recursive 2.644 + fashion. 2.645 + 2.646 +** Escape Expressions 2.647 +Reynolds [Reynolds 72] defines the construction 2.648 += escape x in r = 2.649 + 2.650 +to evaluate the expression $r$ in an environment such that the variable $x$ is 2.651 +bound to an escape function. If the escape function is never applied, then 2.652 +the value of the escape expression is the value of $r$. If the escape function 2.653 +is applied to an argument $a$, however, then evaluation of $r$ is aborted and the 2.654 +escape expression returns $a$. {Note J-operator} (Reynolds points out that 2.655 +this definition is not quite accurate, since the escape function may be called 2.656 +even after the escape expression has returned a value; if this happens, it 2.657 +“returns again"!) 2.658 + 2.659 +As an example of the use of an escape expression, consider this 2.660 +procedure to compute the harmonic mean of an array of numbers. If any of the 2.661 +numbers is zero, we want the answer to be zero. We have a function hannaunl 2.662 +which will sum the reciprocals of numbers in an array, or call an escape 2.663 +function with zero if any of the numbers is zero. (The implementation shown 2.664 +here is awkward because ALGOL requires that a function return its value by 2.665 +assignment.) 2.666 +#+begin_src algol 2.667 +begin 2.668 +real procedure Imrmsum(a, n. escfun)§ p 2.669 +real array at integer n; real procedure esciun(real); 2.670 +begin 2.671 +real sum; 2.672 +sum := 0; 2.673 +for i :1 0 until n-l do 2.674 +begin 2.675 +if a[i]=0 then cscfun(0); 2.676 +sum :1 sum ¢ I/a[i]; 2.677 +enm 2.678 +harmsum SI sum; 2.679 +end: . 2.680 +real array b[0:99]: 2.681 +print(escape x in I00/hm-m.mm(b, 100, x)); 2.682 +end 2.683 +#+end_src 2.684 + 2.685 +If harmsum exits normally, the number of elements is divided by the sum and 2.686 +printed. Otherwise, zero is returned from the escape expression and printed 2.687 +without the division ever occurring. 2.688 +This program can be written in SCHEME using the built-in escape 2.689 +operator =CATCH=: 2.690 + 2.691 +#+begin_src clojure 2.692 +(in-ns 'categorical.imperative) 2.693 +(defn harmonic-sum[coll escape] 2.694 + ((fn [i sum] 2.695 + (cond (= i (count coll) ) sum 2.696 + (zero? (nth coll i)) (escape 0) 2.697 + :else (recur (inc i) (+ sum (/ 1 (nth coll i)))))) 2.698 + 0 0)) 2.699 + 2.700 +#+end_src 2.701 + 2.702 +This actually works, but elucidates very little about the nature of ESCAPE. 2.703 +We can eliminate the use of CATCH by using continuation-passing. Let us do 2.704 +for HARMSUM what we did earlier for FACT. Let it take an extra argument C, 2.705 +which is called as a function on the result. 2.706 + 2.707 +#+begin_src clojure 2.708 +(in-ns 'categorical.imperative) 2.709 +(defn harmonic-sum-escape[coll escape k] 2.710 + ((fn[i sum] 2.711 + (cond (= i (count coll)) (k sum) 2.712 + (zero? (nth coll i)) (escape 0) 2.713 + (recur (inc i) (+ sum (/ 1 (nth coll i)))))) 2.714 + 0 0)) 2.715 + 2.716 +(let [B (range 0 100) 2.717 + after-the-catch println] 2.718 + (harmonic-sum-escape B after-the-catch (fn[y] (after-the-catch (/ 100 y))))) 2.719 + 2.720 +#+end_src 2.721 + 2.722 +Notice that if we use ESCFUN, then C does not get called. In this way the 2.723 +division is avoided. This example shows how ESCFUN may be considered to be an 2.724 +"alternate continuation". 2.725 + 2.726 +** Dynamic Variable Scoping 2.727 +In this section we will consider the problem of dynamically scoped, or 2.728 +"fluid", variables. These do not exist in ALGOL, but are typical of many LISP 2.729 +implementations, ECL, and APL. He will see that fluid variables may be 2.730 +modelled in more than one way, and that one of these is closely related to 2.731 +continuation—pass1ng. 2.732 + 2.733 +*** Free (Global) Variables 2.734 +Consider the following program to compute square roots: 2.735 + 2.736 +#+begin_src clojure 2.737 +(defn sqrt[x tolerance] 2.738 + ( 2.739 +(DEFINE soar 2.740 +(LAHBDA (x EPSILON) 2.741 +(Pace (ANS) 2.742 +(stro ANS 1.0) 2.743 +A (coup ((< (ADS (-s x (~s ANS ANS))) EPSILON) 2.744 +(nzruau ANS))) ' 2.745 +(sero ANS (//s (+5 x (//s x ANS)) 2.0)) 2.746 +(60 A)))) . 2.747 +This function takes two arguments: the radicand and the numerical tolerance 2.748 +for the approximation. Now suppose we want to write a program QUAD to compute 2.749 +solutions to a quadratic equation; p 2.750 +(perms QUAD 2.751 +(LAHDDA (A a c) 2.752 +((LAHBDA (A2 sonmsc) ' 2.753 +(LIST (/ (+ (- a) SQRTDISC) AZ) 2.754 +(/ (- (- B) SORTOISC) AZ))) 2.755 +(' 2 A) 2.756 +- (SORT (- (9 D 2) (' 4 A C)) (tolerance>)))) 2.757 +#+end_src 2.758 +It is not clear what to write for (tolerance). One alternative is to pick 2.759 +some tolerance for use by QUAD and write it as a constant in the code. This 2.760 +is undesirable because it makes QUAD inflexible and hard to change. _Another 2.761 +is to make QUAD take an extra argument and pass it to SQRT: 2.762 +(DEFINE QUAD 2.763 +(LANODA (A 8 C EPSILON) 2.764 +(soar ... EPSILON) ...)) 2.765 +This is undesirable because EPSILDN is not really part of the problem QUAD is 2.766 +supposed to solve, and we don't want the user to have to provide it. 2.767 +Furthermore, if QUAD were built into some larger function, and that into 2.768 +another, all these functions would have to pass EPSILON down as an extra 2.769 +argument. A third.possibi1ity would be to pass the SQRT function as an 2.770 +argument to QUAD (don't laugh!), the theory being to bind EPSILON at the 2.771 +appropriate level like this: A U‘ A 2.772 +(QUAD 3 A 5 (LAMBDA (X) (SORT X <toIerance>))) 2.773 +where we define QUAD as: 2.774 +(DEFINE QUAD 2.775 +(LAMBDA (A a c soar) ...))
3.1 Binary file categorical/ltxpng/plausible_0dd51e4ab8cb4eb616439d758fbec4ed120e8a15.png has changed
4.1 Binary file categorical/ltxpng/plausible_327b1246bf52889b71445e990ea38a8414f683cc.png has changed
5.1 Binary file categorical/ltxpng/plausible_34a4f0f7fd91bf7212f437fd9e0fae7c04dbdae1.png has changed
6.1 Binary file categorical/ltxpng/plausible_5072ddd55abeb45994e1f467e2041032d8a90350.png has changed
7.1 Binary file categorical/ltxpng/plausible_5434f18d3d7ac2858cd4f914be8f5d2b49c79a90.png has changed
8.1 Binary file categorical/ltxpng/plausible_60c89d70f35bbeef7c8c5572941c3398e65f9eb1.png has changed
9.1 Binary file categorical/ltxpng/plausible_671e7f9a1d6c0ed854ad469bb2e6446cf536f6ce.png has changed
10.1 Binary file categorical/ltxpng/plausible_70e445784826d50e75fa759496de7dbd78e0c29e.png has changed
11.1 Binary file categorical/ltxpng/plausible_9471153ffb8045fd30a14628197f6e1a31c4d2bf.png has changed
12.1 Binary file categorical/ltxpng/plausible_c0cfa0be1f5f4c93c4a07d2bf03f296a87ddb3f5.png has changed
13.1 Binary file categorical/ltxpng/plausible_d282b164f31f8cb4d3238ea37d09715da89272aa.png has changed
14.1 Binary file categorical/ltxpng/plausible_dd81a36f0fc30866fc59a06fba09770696fbcfce.png has changed
15.1 Binary file categorical/ltxpng/plausible_df22ff07c07c3eae08269551b79e75e13ed321f9.png has changed
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/categorical/monad.clj Fri Oct 28 00:03:05 2011 -0700 16.3 @@ -0,0 +1,14 @@ 16.4 + 16.5 +(ns categorical.monad) 16.6 +(use 'clojure.contrib.monads) 16.7 + 16.8 +(in-ns 'categorical.monad) 16.9 + 16.10 +;; To implement nondeterministic programs, we'll use a lazy seq to represent a value which may be any one of the members of seq. 16.11 + 16.12 +(defmonad amb 16.13 + [ 16.14 + m-result (fn[& vals] (cons 'amb vals)) 16.15 + m-bind (fn[amb-seq f] (cons 'amb (map f (rest amb-seq)))) 16.16 + ] 16.17 +)
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/categorical/monad.html Fri Oct 28 00:03:05 2011 -0700 17.3 @@ -0,0 +1,251 @@ 17.4 +<?xml version="1.0" encoding="iso-8859-1"?> 17.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 17.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 17.7 +<html xmlns="http://www.w3.org/1999/xhtml" 17.8 +lang="en" xml:lang="en"> 17.9 +<head> 17.10 +<title>Monads in CS and Math</title> 17.11 +<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/> 17.12 +<meta name="generator" content="Org-mode"/> 17.13 +<meta name="generated" content="2011-07-11 03:07:07 EDT"/> 17.14 +<meta name="author" content="Robert McIntyre"/> 17.15 +<meta name="description" content=""/> 17.16 +<meta name="keywords" content=""/> 17.17 +<style type="text/css"> 17.18 + <!--/*--><![CDATA[/*><!--*/ 17.19 + html { font-family: Times, serif; font-size: 12pt; } 17.20 + .title { text-align: center; } 17.21 + .todo { color: red; } 17.22 + .done { color: green; } 17.23 + .tag { background-color: #add8e6; font-weight:normal } 17.24 + .target { } 17.25 + .timestamp { color: #bebebe; } 17.26 + .timestamp-kwd { color: #5f9ea0; } 17.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 17.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 17.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 17.30 + p.verse { margin-left: 3% } 17.31 + pre { 17.32 + border: 1pt solid #AEBDCC; 17.33 + background-color: #F3F5F7; 17.34 + padding: 5pt; 17.35 + font-family: courier, monospace; 17.36 + font-size: 90%; 17.37 + overflow:auto; 17.38 + } 17.39 + table { border-collapse: collapse; } 17.40 + td, th { vertical-align: top; } 17.41 + th.right { text-align:center; } 17.42 + th.left { text-align:center; } 17.43 + th.center { text-align:center; } 17.44 + td.right { text-align:right; } 17.45 + td.left { text-align:left; } 17.46 + td.center { text-align:center; } 17.47 + dt { font-weight: bold; } 17.48 + div.figure { padding: 0.5em; } 17.49 + div.figure p { text-align: center; } 17.50 + textarea { overflow-x: auto; } 17.51 + .linenr { font-size:smaller } 17.52 + .code-highlighted {background-color:#ffff00;} 17.53 + .org-info-js_info-navigation { border-style:none; } 17.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 17.55 + white-space:nowrap; } 17.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 17.57 + font-weight:bold; } 17.58 + /*]]>*/--> 17.59 +</style> 17.60 +<script type="text/javascript"> 17.61 +<!--/*--><![CDATA[/*><!--*/ 17.62 + function CodeHighlightOn(elem, id) 17.63 + { 17.64 + var target = document.getElementById(id); 17.65 + if(null != target) { 17.66 + elem.cacheClassElem = elem.className; 17.67 + elem.cacheClassTarget = target.className; 17.68 + target.className = "code-highlighted"; 17.69 + elem.className = "code-highlighted"; 17.70 + } 17.71 + } 17.72 + function CodeHighlightOff(elem, id) 17.73 + { 17.74 + var target = document.getElementById(id); 17.75 + if(elem.cacheClassElem) 17.76 + elem.className = elem.cacheClassElem; 17.77 + if(elem.cacheClassTarget) 17.78 + target.className = elem.cacheClassTarget; 17.79 + } 17.80 +/*]]>*///--> 17.81 +</script> 17.82 +<script type="text/javascript" src="http://orgmode.org/mathjax/MathJax.js"> 17.83 +<!--/*--><![CDATA[/*><!--*/ 17.84 + MathJax.Hub.Config({ 17.85 + // Only one of the two following lines, depending on user settings 17.86 + // First allows browser-native MathML display, second forces HTML/CSS 17.87 + // config: ["MMLorHTML.js"], jax: ["input/TeX"], 17.88 + jax: ["input/TeX", "output/HTML-CSS"], 17.89 + extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js", 17.90 + "TeX/noUndefined.js"], 17.91 + tex2jax: { 17.92 + inlineMath: [ ["\\(","\\)"] ], 17.93 + displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ], 17.94 + skipTags: ["script","noscript","style","textarea","pre","code"], 17.95 + ignoreClass: "tex2jax_ignore", 17.96 + processEscapes: false, 17.97 + processEnvironments: true, 17.98 + preview: "TeX" 17.99 + }, 17.100 + showProcessingMessages: true, 17.101 + displayAlign: "center", 17.102 + displayIndent: "2em", 17.103 + 17.104 + "HTML-CSS": { 17.105 + scale: 100, 17.106 + availableFonts: ["STIX","TeX"], 17.107 + preferredFont: "TeX", 17.108 + webFont: "TeX", 17.109 + imageFont: "TeX", 17.110 + showMathMenu: true, 17.111 + }, 17.112 + MMLorHTML: { 17.113 + prefer: { 17.114 + MSIE: "MML", 17.115 + Firefox: "MML", 17.116 + Opera: "HTML", 17.117 + other: "HTML" 17.118 + } 17.119 + } 17.120 + }); 17.121 +/*]]>*///--> 17.122 +</script> 17.123 +</head> 17.124 +<body> 17.125 +<div id="content"> 17.126 + 17.127 + 17.128 + 17.129 +<h1> 17.130 +Monads in CS and Math 17.131 +</h1> 17.132 + 17.133 +<p> 17.134 +The purpose of a <i>monad</i> is to introduce a new data type into your 17.135 +language and to integrate it with existing types; a monad augments a 17.136 +pre-existing data type \(A\), creating a new type \(B\). 17.137 +</p> 17.138 +<p> 17.139 +When describing monads, I will use the following terminology: 17.140 +</p><ul> 17.141 +<li>Values of type \(A\) are called <b>ordinary values</b>, because they belong 17.142 + to the pre-existing data type. 17.143 +</li> 17.144 +<li>Values of type \(B\) are called <b>monadic values</b>, because they 17.145 + belong to the type introduced by the monad. 17.146 +</li> 17.147 +<li>A function \(A\rightarrow B\) is called a <b>monadic function</b>; such 17.148 + functions accept regular values as input and return monadic values. 17.149 +</li> 17.150 +</ul> 17.151 + 17.152 + 17.153 +<p> 17.154 +A monad consists of 17.155 +two components for achieving this purpose: 17.156 +</p> 17.157 +<dl> 17.158 +<dt>A function that converts ordinary values into monadic values</dt><dd> 17.159 +<p> 17.160 + First, in order to create a new data type, each monad has an 17.161 + <i>upgrade function</i> which systematically adds structure to values of 17.162 + the existing data type, \(A\). Because the upgrade function produces 17.163 + enhanced values in a systematic way, the enhanced values constitute 17.164 + a sort of new data type, \(B\). 17.165 +</p></dd> 17.166 +</dl> 17.167 + 17.168 + 17.169 +<blockquote> 17.170 + 17.171 + 17.172 +\(\text{upgrade}:A\rightarrow B\) 17.173 + 17.174 +</blockquote> 17.175 + 17.176 + 17.177 +<dl> 17.178 +<dt>A function that enables monadic functions to accept monadic values</dt><dd>Second, each monad has a <i>pipe function</i> which is a 17.179 + protocol for combining a monadic function and a monadic value to 17.180 + produce a monadic value. The pipe function facilitates composition: 17.181 + notice that a collection of monadic functions \(A\rightarrow B\) is composable only if they have been modified by the 17.182 + pipe function to become functions of type \(B\rightarrow B\), otherwise their input and output types do not match. 17.183 +</dd> 17.184 +</dl> 17.185 + 17.186 +<blockquote> 17.187 + 17.188 + 17.189 +\(\text{pipe}:B\times B^A\rightarrow B\) 17.190 + 17.191 +</blockquote> 17.192 + 17.193 + 17.194 + 17.195 + 17.196 + 17.197 + 17.198 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">ns</span> categorical.monad) 17.199 + 17.200 +</pre> 17.201 + 17.202 + 17.203 + 17.204 + 17.205 + 17.206 +<div id="table-of-contents"> 17.207 +<h2>Table of Contents</h2> 17.208 +<div id="text-table-of-contents"> 17.209 +<ul> 17.210 +<li><a href="#sec-1">1 Examples of monads </a> 17.211 +<ul> 17.212 +<li><a href="#sec-1-1">1.1 The nondeterministic monad </a></li> 17.213 +</ul> 17.214 +</li> 17.215 +</ul> 17.216 +</div> 17.217 +</div> 17.218 + 17.219 +<div id="outline-container-1" class="outline-2"> 17.220 +<h2 id="sec-1"><span class="section-number-2">1</span> Examples of monads </h2> 17.221 +<div class="outline-text-2" id="text-1"> 17.222 + 17.223 + 17.224 +</div> 17.225 + 17.226 +<div id="outline-container-1-1" class="outline-3"> 17.227 +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> The nondeterministic monad </h3> 17.228 +<div class="outline-text-3" id="text-1-1"> 17.229 + 17.230 + 17.231 +<p> 17.232 +We'll implement nondeterministic programming by defining a monad <code>amb</code> 17.233 +that transforms ordinary deterministic functions into functions that ``ambiguously'' return zero or more 17.234 +values. 17.235 +</p> 17.236 + 17.237 + 17.238 + 17.239 +<pre class="src src-clojure"></pre> 17.240 + 17.241 + 17.242 + 17.243 +</div> 17.244 +</div> 17.245 +</div> 17.246 +<div id="postamble"> 17.247 +<p class="date">Date: 2011-07-11 03:07:07 EDT</p> 17.248 +<p class="author">Author: Robert McIntyre</p> 17.249 +<p class="creator">Org version 7.6 with Emacs version 23</p> 17.250 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 17.251 +</div> 17.252 +</div> 17.253 +</body> 17.254 +</html>
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/categorical/monad.org Fri Oct 28 00:03:05 2011 -0700 18.3 @@ -0,0 +1,76 @@ 18.4 +#+TITLE: Monads in CS and Math 18.5 +#+BEGIN_HTML 18.6 +<h1> 18.7 +{{{TITLE}}} 18.8 +</h1> 18.9 +#+END_HTML 18.10 + 18.11 +The purpose of a /monad/ is to introduce a new data type into your 18.12 +language and to integrate it with existing types; a monad augments a 18.13 +pre-existing data type $A$, creating a new type $B$. 18.14 + 18.15 +When describing monads, I will use the following terminology: 18.16 +- Values of type $A$ are called *ordinary values*, because they belong 18.17 + to the pre-existing data type. 18.18 +- Values of type $B$ are called *monadic values*, because they 18.19 + belong to the type introduced by the monad. 18.20 +- A function $A\rightarrow B$ is called a *monadic function*; such 18.21 + functions accept regular values as input and return monadic values. 18.22 + 18.23 + 18.24 + 18.25 +A monad consists of 18.26 +two components for achieving this purpose: 18.27 + 18.28 +- A function that converts ordinary values into monadic values :: 18.29 + First, in order to create a new data type, each monad has an 18.30 + /upgrade function/ which systematically adds structure to values of 18.31 + the existing data type, $A$. Because the upgrade function produces 18.32 + enhanced values in a systematic way, the enhanced values constitute 18.33 + a sort of new data type, $B$. 18.34 + 18.35 +#+begin_quote 18.36 +$\text{upgrade}:A\rightarrow B$ 18.37 +#+end_quote 18.38 + 18.39 +- A function that enables monadic functions to accept monadic values :: Second, each monad has a /pipe function/ which is a 18.40 + protocol for combining a monadic function and a monadic value to 18.41 + produce a monadic value. The pipe function facilitates composition: 18.42 + notice that a collection of monadic functions $A\rightarrow B$ is composable only if they have been modified by the 18.43 + pipe function to become functions of type $B\rightarrow B$, otherwise their input and output types do not match. 18.44 +#+begin_quote 18.45 +$\text{pipe}:B\times B^A\rightarrow B$ 18.46 +#+end_quote 18.47 + 18.48 +#+srcname: intro 18.49 +#+begin_src clojure :results silent 18.50 +(ns categorical.monad) 18.51 +(use 'clojure.contrib.monads) 18.52 +#+end_src 18.53 + 18.54 + 18.55 +* Examples of monads 18.56 +** The nondeterministic monad 18.57 + 18.58 +We'll implement nondeterministic programming by defining a monad =amb= 18.59 +that transforms ordinary deterministic functions into functions that ``ambiguously'' return zero or more 18.60 +values. 18.61 + 18.62 +#+srcname: stuff 18.63 +#+begin_src clojure :results silent 18.64 +(in-ns 'categorical.monad) 18.65 + 18.66 +;; To implement nondeterministic programs, we'll use a lazy seq to represent a value which may be any one of the members of seq. 18.67 + 18.68 +(defmonad amb 18.69 + [ 18.70 + m-result (fn[& vals] (cons 'amb vals)) 18.71 + m-bind (fn[amb-seq f] (cons 'amb (map f (rest amb-seq)))) 18.72 + ] 18.73 +) 18.74 +#+end_src 18.75 + 18.76 +#+begin_src clojure :results silent :tangle monad.clj :noweb yes 18.77 +<<intro>> 18.78 +<<stuff>> 18.79 +#+end_src
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/categorical/morphisms.html Fri Oct 28 00:03:05 2011 -0700 19.3 @@ -0,0 +1,240 @@ 19.4 +<?xml version="1.0" encoding="iso-8859-1"?> 19.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 19.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 19.7 +<html xmlns="http://www.w3.org/1999/xhtml" 19.8 +lang="en" xml:lang="en"> 19.9 +<head> 19.10 +<title>Categorical Programs</title> 19.11 +<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/> 19.12 +<meta name="generator" content="Org-mode"/> 19.13 +<meta name="generated" content="2011-07-01 12:28:39 CDT"/> 19.14 +<meta name="author" content="Dylan Holmes"/> 19.15 +<meta name="description" content=""/> 19.16 +<meta name="keywords" content=""/> 19.17 +<style type="text/css"> 19.18 + <!--/*--><![CDATA[/*><!--*/ 19.19 + html { font-family: Times, serif; font-size: 12pt; } 19.20 + .title { text-align: center; } 19.21 + .todo { color: red; } 19.22 + .done { color: green; } 19.23 + .tag { background-color: #add8e6; font-weight:normal } 19.24 + .target { } 19.25 + .timestamp { color: #bebebe; } 19.26 + .timestamp-kwd { color: #5f9ea0; } 19.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 19.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 19.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 19.30 + p.verse { margin-left: 3% } 19.31 + pre { 19.32 + border: 1pt solid #AEBDCC; 19.33 + background-color: #F3F5F7; 19.34 + padding: 5pt; 19.35 + font-family: courier, monospace; 19.36 + font-size: 90%; 19.37 + overflow:auto; 19.38 + } 19.39 + table { border-collapse: collapse; } 19.40 + td, th { vertical-align: top; } 19.41 + th.right { text-align:center; } 19.42 + th.left { text-align:center; } 19.43 + th.center { text-align:center; } 19.44 + td.right { text-align:right; } 19.45 + td.left { text-align:left; } 19.46 + td.center { text-align:center; } 19.47 + dt { font-weight: bold; } 19.48 + div.figure { padding: 0.5em; } 19.49 + div.figure p { text-align: center; } 19.50 + textarea { overflow-x: auto; } 19.51 + .linenr { font-size:smaller } 19.52 + .code-highlighted {background-color:#ffff00;} 19.53 + .org-info-js_info-navigation { border-style:none; } 19.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 19.55 + white-space:nowrap; } 19.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 19.57 + font-weight:bold; } 19.58 + /*]]>*/--> 19.59 +</style> 19.60 +<link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 19.61 +<script type="text/javascript"> 19.62 +<!--/*--><![CDATA[/*><!--*/ 19.63 + function CodeHighlightOn(elem, id) 19.64 + { 19.65 + var target = document.getElementById(id); 19.66 + if(null != target) { 19.67 + elem.cacheClassElem = elem.className; 19.68 + elem.cacheClassTarget = target.className; 19.69 + target.className = "code-highlighted"; 19.70 + elem.className = "code-highlighted"; 19.71 + } 19.72 + } 19.73 + function CodeHighlightOff(elem, id) 19.74 + { 19.75 + var target = document.getElementById(id); 19.76 + if(elem.cacheClassElem) 19.77 + elem.className = elem.cacheClassElem; 19.78 + if(elem.cacheClassTarget) 19.79 + target.className = elem.cacheClassTarget; 19.80 + } 19.81 +/*]]>*///--> 19.82 +</script> 19.83 +<script type="text/javascript" src="http://orgmode.org/mathjax/MathJax.js"> 19.84 +<!--/*--><![CDATA[/*><!--*/ 19.85 + MathJax.Hub.Config({ 19.86 + // Only one of the two following lines, depending on user settings 19.87 + // First allows browser-native MathML display, second forces HTML/CSS 19.88 + // config: ["MMLorHTML.js"], jax: ["input/TeX"], 19.89 + jax: ["input/TeX", "output/HTML-CSS"], 19.90 + extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js", 19.91 + "TeX/noUndefined.js"], 19.92 + tex2jax: { 19.93 + inlineMath: [ ["\\(","\\)"] ], 19.94 + displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ], 19.95 + skipTags: ["script","noscript","style","textarea","pre","code"], 19.96 + ignoreClass: "tex2jax_ignore", 19.97 + processEscapes: false, 19.98 + processEnvironments: true, 19.99 + preview: "TeX" 19.100 + }, 19.101 + showProcessingMessages: true, 19.102 + displayAlign: "center", 19.103 + displayIndent: "2em", 19.104 + 19.105 + "HTML-CSS": { 19.106 + scale: 100, 19.107 + availableFonts: ["STIX","TeX"], 19.108 + preferredFont: "TeX", 19.109 + webFont: "TeX", 19.110 + imageFont: "TeX", 19.111 + showMathMenu: true, 19.112 + }, 19.113 + MMLorHTML: { 19.114 + prefer: { 19.115 + MSIE: "MML", 19.116 + Firefox: "MML", 19.117 + Opera: "HTML", 19.118 + other: "HTML" 19.119 + } 19.120 + } 19.121 + }); 19.122 +/*]]>*///--> 19.123 +</script> 19.124 +</head> 19.125 +<body> 19.126 +<div id="content"> 19.127 + 19.128 + 19.129 + 19.130 + 19.131 + 19.132 +<h1>Categorical Programs</h1> 19.133 + 19.134 + 19.135 +<div id="table-of-contents"> 19.136 +<h2>Table of Contents</h2> 19.137 +<div id="text-table-of-contents"> 19.138 +<ul> 19.139 +<li><a href="#sec-1">1 The Category of Types </a> 19.140 +<ul> 19.141 +<li><a href="#sec-1-1">1.1 Building new data types out of existing ones </a></li> 19.142 +</ul> 19.143 +</li> 19.144 +</ul> 19.145 +</div> 19.146 +</div> 19.147 + 19.148 +<div id="outline-container-1" class="outline-2"> 19.149 +<h2 id="sec-1"><span class="section-number-2">1</span> The Category of Types </h2> 19.150 +<div class="outline-text-2" id="text-1"> 19.151 + 19.152 +<p>Every computer language with data types (such as Integers, 19.153 +Floats, or 19.154 +Strings) corresponds with a certain category; the objects of the category are the data types 19.155 +of the language, and there is one arrow between data types \(A\) and \(B\) 19.156 +for every function in the language whose argument has type \(A\) and whose return value 19.157 +has type \(B\). 19.158 +</p> 19.159 + 19.160 + 19.161 + 19.162 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">ns</span> categorical.morphisms) 19.163 + 19.164 +</pre> 19.165 + 19.166 + 19.167 + 19.168 + 19.169 + 19.170 +</div> 19.171 + 19.172 +<div id="outline-container-1-1" class="outline-3"> 19.173 +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> Building new data types out of existing ones </h3> 19.174 +<div class="outline-text-3" id="text-1-1"> 19.175 + 19.176 + 19.177 +<p> 19.178 +We will now discuss two processes which combine existing 19.179 +data types to yield composite data types. These higher-order processes will be 19.180 +<i>functorial</i>, which means that they will recombine not only the objects of 19.181 +our category (the data types), but the arrows as well (functions with 19.182 +typed input and output). 19.183 +</p> 19.184 +<p> 19.185 +The <code>product</code> functor combines two data types, \(A\) and \(B\), producing 19.186 +a new type, denoted \(A\times B\). Conceptually, values with the data type \(A\times 19.187 +B\) have two components, the first of which is a value of type \(A\), the 19.188 +second of which is a value of type \(B\). Concretely, the data type \(A\times B\) 19.189 +can be implemented as pairs of values, the first of which is 19.190 +of type \(A\) and the second of which is of type \(B\). With this 19.191 +implementation in mind, you can see that the type \(A\) and type \(B\) 19.192 +constituents of type \(A\times B\) value can be recovered; the so-called 19.193 +projection functors <code>first</code> and <code>second</code> recover them. A third 19.194 +functor, the <code>diagonal</code> functor, completes our toolkit; given 19.195 +value \(a\) of type \(A\), it produces the value \((a,a)\) of type \(A\times A\). 19.196 +</p> 19.197 + 19.198 + 19.199 + 19.200 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">product</span>[a b] (<span style="color: #8cd0d3;">list</span> a b)) 19.201 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">projections</span> (<span style="color: #8cd0d3;">list</span> first second)) 19.202 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">diagonal</span>[a] (product a a)) 19.203 + 19.204 +</pre> 19.205 + 19.206 + 19.207 + 19.208 + 19.209 +<p> 19.210 +The <code>coproduct</code> functor combines two data types, \(A\) and \(B\), 19.211 +producing a new type, denoted \(A+B\). Conceptually, you construct the 19.212 +\(A+B\) datatype by creating labelled versions of the data types \(A\) and 19.213 +\(B\) — we'll call them black-\(A\) and white-\(B\) — and 19.214 +then creating a data type \(A+B\) which contains all the black-\(A\) 19.215 +values and all the white-\(B\) values. Concretely, you can implement the 19.216 +\(A+B\) data type using label-value pairs: the first value in the pair 19.217 +is either the label `black' or the label `white'; the second 19.218 +value must have type \(A\) if the label is black, or type \(B\) if the 19.219 +label is white. 19.220 +</p> 19.221 +<p> 19.222 +Now, the <code>product</code> functor came with projection functors <code>first</code> 19.223 +and <code>second</code> that take \(A\times B\) values and return (respectively) \(A\) values and 19.224 +\(B\) values. The <code>coproduct</code> functor, conversely, comes with two 19.225 +injection functors <code>make-black</code> and <code>make-white</code> that perform the 19.226 +opposite function: they take (respectively) \(A\) values and \(B\) values, 19.227 +promoting them to the \(A+B\) datatype by making the \(A\)'s into 19.228 +black-\(A\)'s and the \(B\)'s into white-\(B\)'s. 19.229 +</p> 19.230 + 19.231 + 19.232 +</div> 19.233 +</div> 19.234 +</div> 19.235 +<div id="postamble"> 19.236 +<p class="date">Date: 2011-07-01 12:28:39 CDT</p> 19.237 +<p class="author">Author: Dylan Holmes</p> 19.238 +<p class="creator">Org version 7.5 with Emacs version 23</p> 19.239 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 19.240 +</div> 19.241 +</div> 19.242 +</body> 19.243 +</html>
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/categorical/morphisms.org Fri Oct 28 00:03:05 2011 -0700 20.3 @@ -0,0 +1,81 @@ 20.4 +#+TITLE: Categorical Programs 20.5 +#+AUTHOR: Dylan Holmes 20.6 + 20.7 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 20.8 + 20.9 +#+BEGIN_HTML 20.10 +<h1>{{{title}}}</h1> 20.11 +#+END_HTML 20.12 + 20.13 +* The Category of Types 20.14 +Every computer language with data types (such as Integers, 20.15 +Floats, or 20.16 +Strings) corresponds with a certain category; the objects of the category are the data types 20.17 +of the language, and there is one arrow between data types $A$ and $B$ 20.18 +for every function in the language whose argument has type $A$ and whose return value 20.19 +has type $B$. 20.20 + 20.21 +#+begin_src clojure :results silent 20.22 +(ns categorical.morphisms) 20.23 +#+end_src 20.24 + 20.25 +** Building new data types out of existing ones 20.26 + 20.27 +We will now discuss two processes which combine existing 20.28 +data types to yield composite data types. These higher-order processes will be 20.29 +/functorial/, which means that they will recombine not only the objects of 20.30 +our category (the data types), but the arrows as well (functions with 20.31 +typed input and output). 20.32 + 20.33 +The =product= functor combines two data types, $A$ and $B$, producing 20.34 +a new type, denoted $A\times B$. Conceptually, values with the data type $A\times 20.35 +B$ have two components, the first of which is a value of type $A$, the 20.36 +second of which is a value of type $B$. Concretely, the data type $A\times B$ 20.37 +can be implemented as pairs of values, the first of which is 20.38 +of type $A$ and the second of which is of type $B$. With this 20.39 +implementation in mind, you can see that the type $A$ and type $B$ 20.40 +constituents of type $A\times B$ value can be recovered; the so-called 20.41 +projection functors =first= and =second= recover them. A third 20.42 +functor, the =diagonal= functor, completes our toolkit; given 20.43 +value $a$ of type $A$, it produces the value $(a,a)$ of type $A\times A$. 20.44 + 20.45 +#+begin_src clojure :results silent 20.46 +(defn product[a b] (list a b)) 20.47 +(def projections (list first second)) 20.48 +(defn diagonal[a] (product a a)) 20.49 +#+end_src 20.50 + 20.51 +The =coproduct= functor combines two data types, $A$ and $B$, 20.52 +producing a new type, denoted $A+B$. Conceptually, you construct the 20.53 +$A+B$ datatype by creating labelled versions of the data types $A$ and 20.54 +$B$ \mdash{} we'll call them black-$A$ and white-$B$ \mdash{} and 20.55 +then creating a data type $A+B$ which contains all the black-$A$ 20.56 +values and all the white-$B$ values. Concretely, you can implement the 20.57 +$A+B$ data type using label-value pairs: the first value in the pair 20.58 +is either the label `black' or the label `white'; the second 20.59 +value must have type $A$ if the label is black, or type $B$ if the 20.60 +label is white. 20.61 + 20.62 +Now, the =product= functor came with projection functors =first= 20.63 +and =second= that take $A\times B$ values and return (respectively) $A$ values and 20.64 +$B$ values. The =coproduct= functor, conversely, comes with two 20.65 +injection functors =make-black= and =make-white= that perform the 20.66 +opposite function: they take (respectively) $A$ values and $B$ values, 20.67 +promoting them to the $A+B$ datatype by making the $A$'s into 20.68 +black-$A$'s and the $B$'s into white-$B$'s. 20.69 + 20.70 +#the =coproduct= functor comes with two injection functors =make-black= 20.71 +#and =make-white= that take (respectively) $A$ values and $B$ values, 20.72 +#promoting them to the $A+B$ datatype by making them into black-$A$'s 20.73 +#or white-$B$'s. 20.74 + 20.75 + 20.76 +#The =coproduct= functor combines two data types, $A$ and $B$, 20.77 +#producing a new type, denoted $A+B$. Conceptually, values with the 20.78 +#data type $A+B$ can be either values with type $A$ that are designated /of the first 20.79 +#kind/, or values with type $B$ that are designated /of the second 20.80 +#kind/. Concretely, the data type $A+B$ can be implemented using pairs 20.81 +#of values in conjunction with a labelling convention; the first value 20.82 +#in the pair is of either type $A$ or $B$, and the second value is a label 20.83 +#indicating whether it is of the first or second kind. Our labelling 20.84 +#scheme uses the keywords =:black= and =:white= for this purpose.
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/categorical/plausible.html Fri Oct 28 00:03:05 2011 -0700 21.3 @@ -0,0 +1,336 @@ 21.4 +<?xml version="1.0" encoding="iso-8859-1"?> 21.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 21.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 21.7 +<html xmlns="http://www.w3.org/1999/xhtml" 21.8 +lang="en" xml:lang="en"> 21.9 +<head> 21.10 +<title>Categorification of Plausible Reasoning</title> 21.11 +<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/> 21.12 +<meta name="generator" content="Org-mode"/> 21.13 +<meta name="generated" content="2011-07-09 14:19:42 EDT"/> 21.14 +<meta name="author" content="Dylan Holmes"/> 21.15 +<meta name="description" content=""/> 21.16 +<meta name="keywords" content=""/> 21.17 +<style type="text/css"> 21.18 + <!--/*--><![CDATA[/*><!--*/ 21.19 + html { font-family: Times, serif; font-size: 12pt; } 21.20 + .title { text-align: center; } 21.21 + .todo { color: red; } 21.22 + .done { color: green; } 21.23 + .tag { background-color: #add8e6; font-weight:normal } 21.24 + .target { } 21.25 + .timestamp { color: #bebebe; } 21.26 + .timestamp-kwd { color: #5f9ea0; } 21.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 21.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 21.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 21.30 + p.verse { margin-left: 3% } 21.31 + pre { 21.32 + border: 1pt solid #AEBDCC; 21.33 + background-color: #F3F5F7; 21.34 + padding: 5pt; 21.35 + font-family: courier, monospace; 21.36 + font-size: 90%; 21.37 + overflow:auto; 21.38 + } 21.39 + table { border-collapse: collapse; } 21.40 + td, th { vertical-align: top; } 21.41 + th.right { text-align:center; } 21.42 + th.left { text-align:center; } 21.43 + th.center { text-align:center; } 21.44 + td.right { text-align:right; } 21.45 + td.left { text-align:left; } 21.46 + td.center { text-align:center; } 21.47 + dt { font-weight: bold; } 21.48 + div.figure { padding: 0.5em; } 21.49 + div.figure p { text-align: center; } 21.50 + textarea { overflow-x: auto; } 21.51 + .linenr { font-size:smaller } 21.52 + .code-highlighted {background-color:#ffff00;} 21.53 + .org-info-js_info-navigation { border-style:none; } 21.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 21.55 + white-space:nowrap; } 21.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 21.57 + font-weight:bold; } 21.58 + /*]]>*/--> 21.59 +</style> 21.60 +<script type="text/javascript"> 21.61 +<!--/*--><![CDATA[/*><!--*/ 21.62 + function CodeHighlightOn(elem, id) 21.63 + { 21.64 + var target = document.getElementById(id); 21.65 + if(null != target) { 21.66 + elem.cacheClassElem = elem.className; 21.67 + elem.cacheClassTarget = target.className; 21.68 + target.className = "code-highlighted"; 21.69 + elem.className = "code-highlighted"; 21.70 + } 21.71 + } 21.72 + function CodeHighlightOff(elem, id) 21.73 + { 21.74 + var target = document.getElementById(id); 21.75 + if(elem.cacheClassElem) 21.76 + elem.className = elem.cacheClassElem; 21.77 + if(elem.cacheClassTarget) 21.78 + target.className = elem.cacheClassTarget; 21.79 + } 21.80 +/*]]>*///--> 21.81 +</script> 21.82 +<script type="text/javascript" src="../MathJax/MathJax.js"> 21.83 +<!--/*--><![CDATA[/*><!--*/ 21.84 + MathJax.Hub.Config({ 21.85 + // Only one of the two following lines, depending on user settings 21.86 + // First allows browser-native MathML display, second forces HTML/CSS 21.87 + config: ["MMLorHTML.js"], jax: ["input/TeX"], 21.88 + // jax: ["input/TeX", "output/HTML-CSS"], 21.89 + extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js", 21.90 + "TeX/noUndefined.js"], 21.91 + tex2jax: { 21.92 + inlineMath: [ ["\\(","\\)"] ], 21.93 + displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ], 21.94 + skipTags: ["script","noscript","style","textarea","pre","code"], 21.95 + ignoreClass: "tex2jax_ignore", 21.96 + processEscapes: false, 21.97 + processEnvironments: true, 21.98 + preview: "TeX" 21.99 + }, 21.100 + showProcessingMessages: true, 21.101 + displayAlign: "left", 21.102 + displayIndent: "2em", 21.103 + 21.104 + "HTML-CSS": { 21.105 + scale: 100, 21.106 + availableFonts: ["STIX","TeX"], 21.107 + preferredFont: "TeX", 21.108 + webFont: "TeX", 21.109 + imageFont: "TeX", 21.110 + showMathMenu: true, 21.111 + }, 21.112 + MMLorHTML: { 21.113 + prefer: { 21.114 + MSIE: "MML", 21.115 + Firefox: "MML", 21.116 + Opera: "HTML", 21.117 + other: "HTML" 21.118 + } 21.119 + } 21.120 + }); 21.121 +/*]]>*///--> 21.122 +</script> 21.123 +</head> 21.124 +<body> 21.125 +<div id="content"> 21.126 + 21.127 + 21.128 + 21.129 + 21.130 +<div id="table-of-contents"> 21.131 +<h2>Table of Contents</h2> 21.132 +<div id="text-table-of-contents"> 21.133 +<ul> 21.134 +<li><a href="#sec-1">1 Deductive and inductive posets </a> 21.135 +<ul> 21.136 +<li><a href="#sec-1-1">1.1 Definition </a></li> 21.137 +<li><a href="#sec-1-2">1.2 A canonical map from deductive posets to inductive posets </a></li> 21.138 +</ul> 21.139 +</li> 21.140 +<li><a href="#sec-2">2 Assigning plausibilities to inductive posets </a> 21.141 +<ul> 21.142 +<li><a href="#sec-2-1">2.1 Consistent reasoning as a commutative diagram </a></li> 21.143 +<li><a href="#sec-2-2">2.2 ``Multiplicity'' is reciprocal probability </a></li> 21.144 +<li><a href="#sec-2-3">2.3 Laws for multiplicity </a></li> 21.145 +</ul> 21.146 +</li> 21.147 +</ul> 21.148 +</div> 21.149 +</div> 21.150 + 21.151 +<div id="outline-container-1" class="outline-2"> 21.152 +<h2 id="sec-1"><span class="section-number-2">1</span> Deductive and inductive posets </h2> 21.153 +<div class="outline-text-2" id="text-1"> 21.154 + 21.155 + 21.156 + 21.157 +</div> 21.158 + 21.159 +<div id="outline-container-1-1" class="outline-3"> 21.160 +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> Definition </h3> 21.161 +<div class="outline-text-3" id="text-1-1"> 21.162 + 21.163 +<p>If you have a collection \(P\) of logical propositions, you can order them by 21.164 +implication: \(a\) precedes \(b\) if and only if \(a\) implies 21.165 +\(b\). This makes \(P\) into a poset. Since the ordering arose from 21.166 +deductive implication, we'll call this a <i>deductive poset</i>. 21.167 +</p> 21.168 +<p> 21.169 +If you have a deductive poset \(P\), you can create a related poset \(P^*\) 21.170 +as follows: the underlying set is the same, and for any two 21.171 +propositions \(a\) and \(b\) in \(P\), \(a\) precedes 21.172 +\(ab\) in \(P^*\). We'll call this an <i>inductive poset</i>. 21.173 +</p> 21.174 +</div> 21.175 + 21.176 +</div> 21.177 + 21.178 +<div id="outline-container-1-2" class="outline-3"> 21.179 +<h3 id="sec-1-2"><span class="section-number-3">1.2</span> A canonical map from deductive posets to inductive posets </h3> 21.180 +<div class="outline-text-3" id="text-1-2"> 21.181 + 21.182 +<p>Each poset corresponds with a poset-category, that is a category with 21.183 +at most one arrow between any two objects. Considered as categories, 21.184 +inductive and deuctive posets are related as follows: there is a map 21.185 +\(\mathscr{F}\) which sends each arrow \(a\rightarrow b\) in \(P\) to 21.186 +the arrow \(a\rightarrow ab\) in \(P^*\). In fact, since \(a\) implies 21.187 +\(b\) if and only if \(a = ab\), \(\mathscr{F}\) sends each arrow in \(P\) to 21.188 +an identity arrow in \(P^*\) (specifically, it sends the arrow 21.189 +\(a\rightarrow b\) to the identity arrow \(a\rightarrow a\)). 21.190 +</p> 21.191 + 21.192 +</div> 21.193 +</div> 21.194 + 21.195 +</div> 21.196 + 21.197 +<div id="outline-container-2" class="outline-2"> 21.198 +<h2 id="sec-2"><span class="section-number-2">2</span> Assigning plausibilities to inductive posets </h2> 21.199 +<div class="outline-text-2" id="text-2"> 21.200 + 21.201 + 21.202 +<p> 21.203 +Inductive posets encode the relative (<i>qualitative</i>) plausibilities of its 21.204 +propositions: there exists an arrow \(x\rightarrow y\) only if \(x\) 21.205 +is at least as plausible as \(y\). 21.206 +</p> 21.207 + 21.208 +</div> 21.209 + 21.210 +<div id="outline-container-2-1" class="outline-3"> 21.211 +<h3 id="sec-2-1"><span class="section-number-3">2.1</span> Consistent reasoning as a commutative diagram </h3> 21.212 +<div class="outline-text-3" id="text-2-1"> 21.213 + 21.214 +<p>Inductive categories enable the following neat trick: we can interpret 21.215 +the objects of \(P^*\) as states of given information and interpret 21.216 +each arrow \(a\rightarrow ab\) in \(P^*\) as an inductive inference: the arrow 21.217 +\(a\rightarrow ab\) represents an inferential leap from the state of 21.218 +knowledge where only \(a\) is given to the state of knowledge where 21.219 +both \(a\) and \(b\) are given— in this way, it represents 21.220 +the process of inferring \(b\) when given \(a\), and we label the 21.221 +arrow with \((b|a)\). 21.222 +</p> 21.223 +<p> 21.224 +This trick has several important features that suggest its usefulness, 21.225 +namely 21.226 +</p><ul> 21.227 +<li>Composition of arrows corresponds to compound inference. 21.228 +</li> 21.229 +<li>In the special case of deductive inference, the inferential arrow is an 21.230 + identity; the source and destination states of knowledge are the same. 21.231 +</li> 21.232 +<li>One aspect of the consistency requirement of Jaynes<sup><a class="footref" name="fnr.1" href="#fn.1">1</a></sup> takes the form of a 21.233 + commutative square: \(x\rightarrow ax \rightarrow abx\) = 21.234 + \(x\rightarrow bx \rightarrow abx\) is the categorified version of 21.235 + \((AB|X)=(A|X)\cdot(B|AX)=(B|X)\cdot(A|BX)\). 21.236 +</li> 21.237 +<li>We can make plausibility assignments by enriching the inductive 21.238 + category \(P^*\) over some monoidal category, e.g. the set of real numbers 21.239 + (considered as a category) with its usual multiplication. <i>When we do</i>, 21.240 + the identity arrows of \(P^*\) —corresponding to 21.241 + deductive inferences— are assigned a value of certainty automatically. 21.242 +</li> 21.243 +</ul> 21.244 + 21.245 + 21.246 +</div> 21.247 + 21.248 +</div> 21.249 + 21.250 +<div id="outline-container-2-2" class="outline-3"> 21.251 +<h3 id="sec-2-2"><span class="section-number-3">2.2</span> ``Multiplicity'' is reciprocal probability </h3> 21.252 +<div class="outline-text-3" id="text-2-2"> 21.253 + 21.254 +<p>The natural numbers have a comparatively concrete origin: they are the 21.255 +result of decategorifying the category of finite sets<sup><a class="footref" name="fnr.2" href="#fn.2">2</a></sup>, or the 21.256 +coequalizer of the arrows from a one-object category to a two-object 21.257 +category with a single nonidentity arrow. Extensions of the set of 21.258 +natural numbers— such as 21.259 +the set of integers or rational numbers or real numbers— strike 21.260 +me as being somewhat more abstract (however, see the Eudoxus 21.261 +construction of the real numbers). 21.262 +</p> 21.263 +<p> 21.264 +Jaynes points out that our existing choice of scale for probabilities 21.265 +(i.e., the scale from 0 for impossibility to 1 for 21.266 +certainty) has a degree of freedom: any monotonic function of 21.267 +probability encodes the same information that probability does. Though 21.268 +the resulting laws for compound probability and so on change in form 21.269 +when probabilities are changed, they do not change in content. 21.270 +</p> 21.271 +<p> 21.272 +With this in mind, it seems natural and permissible to use not <i>probability</i> but 21.273 +<i>reciprocal probability</i> instead. This scale, which we might 21.274 + call <i>multiplicity</i>, ranges from 1 (certainty) to 21.275 +positive infinity (impossibility); higher numbers are ascribed to 21.276 +less-plausible events. 21.277 +</p> 21.278 +<p> 21.279 +In this way, the ``probability'' 21.280 +associated with choosing one out of \(n\) indistinguishable choices 21.281 +becomes identified with \(n\). 21.282 +</p> 21.283 +</div> 21.284 + 21.285 +</div> 21.286 + 21.287 +<div id="outline-container-2-3" class="outline-3"> 21.288 +<h3 id="sec-2-3"><span class="section-number-3">2.3</span> Laws for multiplicity </h3> 21.289 +<div class="outline-text-3" id="text-2-3"> 21.290 + 21.291 +<p>Jaynes derives laws of probability; either his method or his results 21.292 +can be used to obtain laws for multiplicities. 21.293 +</p> 21.294 +<dl> 21.295 +<dt>product rule</dt><dd>The product rule is unchanged: \(\xi(AB|X)=\xi(A|X)\cdot 21.296 + \xi(B|AX) = \xi(B|X)\cdot \xi(A|BX)\) 21.297 +</dd> 21.298 +<dt>certainty</dt><dd>States of absolute certainty are assigned a multiplicity 21.299 + of 1. States of absolute impossibility are assigned a 21.300 + multiplicity of positive infinity. 21.301 +</dd> 21.302 +<dt>entropy</dt><dd>In terms of probability, entropy has the form \(S=-\sum_i 21.303 + p_i \ln{p_i} = \sum_i p_i (-\ln{p_i}) = \sum_i p_i \ln{(1/p_i)} 21.304 + \). Hence, in terms of multiplicity, entropy 21.305 + has the form \(S = \sum_i \frac{\ln{\xi_i}}{\xi_i} \). 21.306 + 21.307 +<p> 21.308 + Another interesting quantity is \(\exp{S}\), which behaves 21.309 + multiplicitively rather than additively. \(\exp{S} = 21.310 + \prod_i \exp{\frac{\ln{\xi_i}}{\xi_i}} = 21.311 + \left(\exp{\ln{\xi_i}}\right)^{1/\xi_i} = \prod_i \xi_i^{1/\xi_i} \) 21.312 +</p></dd> 21.313 +</dl> 21.314 + 21.315 + 21.316 + 21.317 +<div id="footnotes"> 21.318 +<h2 class="footnotes">Footnotes: </h2> 21.319 +<div id="text-footnotes"> 21.320 +<p class="footnote"><sup><a class="footnum" name="fn.1" href="#fnr.1">1</a></sup> <i>(IIIa) If a conclusion can be reasoned out in more than one way, then every possible way must lead to the same result.</i> 21.321 +</p> 21.322 + 21.323 +<p class="footnote"><sup><a class="footnum" name="fn.2" href="#fnr.2">2</a></sup> As Baez explains. 21.324 +</p> 21.325 +</div> 21.326 +</div> 21.327 +</div> 21.328 + 21.329 +</div> 21.330 +</div> 21.331 +<div id="postamble"> 21.332 +<p class="date">Date: 2011-07-09 14:19:42 EDT</p> 21.333 +<p class="author">Author: Dylan Holmes</p> 21.334 +<p class="creator">Org version 7.6 with Emacs version 23</p> 21.335 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 21.336 +</div> 21.337 +</div> 21.338 +</body> 21.339 +</html>
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/categorical/plausible.org Fri Oct 28 00:03:05 2011 -0700 22.3 @@ -0,0 +1,114 @@ 22.4 +#+TITLE: Categorification of Plausible Reasoning 22.5 +#+AUTHOR: Dylan Holmes 22.6 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js" 22.7 +* COMMENT #+OPTIONS: LaTeX:dvipng 22.8 + 22.9 +* Deductive and inductive posets 22.10 + 22.11 +** Definition 22.12 +If you have a collection \(P\) of logical propositions, you can order them by 22.13 +implication: \(a\) precedes \(b\) if and only if \(a\) implies 22.14 +\(b\). This makes \(P\) into a poset. Since the ordering arose from 22.15 +deductive implication, we'll call this a /deductive poset/. 22.16 + 22.17 +If you have a deductive poset \(P\), you can create a related poset \(P^*\) 22.18 +as follows: the underlying set is the same, and for any two 22.19 +propositions \(a\) and \(b\) in \(P\), \(a\) precedes 22.20 +\(ab\) in \(P^*\). We'll call this an /inductive poset/. 22.21 + 22.22 +** A canonical map from deductive posets to inductive posets 22.23 +Each poset corresponds with a poset-category, that is a category with 22.24 +at most one arrow between any two objects. Considered as categories, 22.25 +inductive and deuctive posets are related as follows: there is a map 22.26 +\(\mathscr{F}\) which sends each arrow \(a\rightarrow b\) in \(P\) to 22.27 +the arrow \(a\rightarrow ab\) in \(P^*\). In fact, since \(a\) implies 22.28 +\(b\) if and only if \(a = ab\), \(\mathscr{F}\) sends each arrow in \(P\) to 22.29 +an identity arrow in \(P^*\) (specifically, it sends the arrow 22.30 +\(a\rightarrow b\) to the identity arrow \(a\rightarrow a\)). 22.31 + 22.32 + 22.33 +** Assigning plausibilities to inductive posets 22.34 + 22.35 +Inductive posets encode the relative (/qualitative/) plausibilities of its 22.36 +propositions: there exists an arrow \(x\rightarrow y\) only if \(x\) 22.37 +is at least as plausible as \(y\). 22.38 + 22.39 +*** Consistent reasoning as a commutative diagram 22.40 +Inductive categories enable the following neat trick: we can interpret 22.41 +the objects of \(P^*\) as states of given information and interpret 22.42 +each arrow \(a\rightarrow ab\) in \(P^*\) as an inductive inference: the arrow 22.43 +\(a\rightarrow ab\) represents an inferential leap from the state of 22.44 +knowledge where only \(a\) is given to the state of knowledge where 22.45 +both \(a\) and \(b\) are given\mdash{} in this way, it represents 22.46 +the process of inferring \(b\) when given \(a\), and we label the 22.47 +arrow with \((b|a)\). 22.48 + 22.49 +This trick has several important features that suggest its usefulness, 22.50 +namely 22.51 + - Composition of arrows corresponds to compound inference. 22.52 + - In the special case of deductive inference, the inferential arrow is an 22.53 + identity; the source and destination states of knowledge are the same. 22.54 + - One aspect of the consistency requirement of Jaynes[fn:1] takes the form of a 22.55 + commutative square: \(x\rightarrow ax \rightarrow abx\) = 22.56 + \(x\rightarrow bx \rightarrow abx\) is the categorified version of 22.57 + \((AB|X)=(A|X)\cdot(B|AX)=(B|X)\cdot(A|BX)\). 22.58 + - We can make plausibility assignments by enriching the inductive 22.59 + category \(P^*\) over some monoidal category, e.g. the set of real numbers 22.60 + (considered as a category) with its usual multiplication. /When we do/, 22.61 + the identity arrows of \(P^*\) \mdash{}corresponding to 22.62 + deductive inferences\mdash{} are assigned a value of certainty automatically. 22.63 + 22.64 +[fn:1] /(IIIa) If a conclusion can be reasoned out in more than one 22.65 +way, then every possible way must lead to the same result./ 22.66 + 22.67 + 22.68 +*** Reciprocal probabilities 22.69 +The natural numbers have a comparatively concrete origin: they are the 22.70 +result of decategorifying the category of finite sets[fn:2], or the 22.71 +coequalizer of the arrows from a one-object category to a two-object 22.72 +category with a single nonidentity arrow. Extensions of the set of 22.73 +natural numbers\mdash{} such as 22.74 +the set of integers or rational numbers or real numbers\mdash{} strike 22.75 +me as being somewhat more abstract. 22.76 + 22.77 +Jaynes points out that our existing choice of scale for probabilities 22.78 +(i.e., the scale from 0 for impossibility to 1 for 22.79 +certainty) has a degree of freedom: any monotonic function of 22.80 +probability encodes the same information that probability does. 22.81 + 22.82 +With this in mind, it seems useful to use not /probability/ but 22.83 +/reciprocal probability/ instead. This scale, which we might 22.84 +tentatively call freeness, is a scale ranging 1 (certainty) to 22.85 +positive infinity (impossibility). 22.86 + 22.87 +In this way, the ``probability'' 22.88 +associated with choosing one out of \(n\) indistinguishable choices 22.89 +becomes identified with \(n\). 22.90 + 22.91 +The entropy 22.92 + 22.93 +[fn:2] As Baez says. 22.94 + 22.95 + 22.96 + 22.97 +** self-questions 22.98 + 22.99 +What circumstances would make \(\mathscr{F}\) an injection? 22.100 + 22.101 +What if \(P=\{\top,\bot\}\)? 22.102 + 22.103 + 22.104 + 22.105 +** COMMENT 22.106 +Inductive and deductive posets are related as follows: there is a monotone 22.107 +inclusion map \(\mathscr{i}:P^*\hookrightarrow P\) which\mdash{} since \(a\) 22.108 +implies \(b\) is equivalent to \(a=ab\)\mdash{} sends comparable 22.109 +propositions in \(P\) to the same proposition in \(P^*\). Conversely, 22.110 +only comparable propositions in \(P\) are sent to the same proposition 22.111 +in \(P^*\). 22.112 + 22.113 + 22.114 + 22.115 +** Inductive posets and plausibility 22.116 + 22.117 +* Inverse Probability
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/categorical/plausible.org_archive Fri Oct 28 00:03:05 2011 -0700 23.3 @@ -0,0 +1,40 @@ 23.4 +# -*- mode: org -*- 23.5 + 23.6 + 23.7 +Archived entries from file /home/r/aurellem/src/categorical/plausible.org 23.8 + 23.9 +* Consistent reasoning as a commutative diagram 23.10 + :PROPERTIES: 23.11 + :ARCHIVE_TIME: 2011-07-09 Sat 01:00 23.12 + :ARCHIVE_FILE: ~/aurellem/src/categorical/plausible.org 23.13 + :ARCHIVE_OLPATH: Deductive and inductive posets/Assigning plausibilities to inductive posets 23.14 + :ARCHIVE_CATEGORY: plausible 23.15 + :END: 23.16 +Inductive categories enable the following neat trick: we can interpret 23.17 +the objects of \(P^*\) as states of given information and interpret 23.18 +each arrow \(a\rightarrow ab\) in \(P^*\) as an inductive inference: the arrow 23.19 +\(a\rightarrow ab\) represents an inferential leap from the state of 23.20 +knowledge where only \(a\) is given to the state of knowledge where 23.21 +both \(a\) and \(b\) are given\mdash{} in this way, it represents 23.22 +the process of inferring \(b\) when given \(a\), and we label the 23.23 +arrow with \((b|a)\). 23.24 + 23.25 +This trick has several important features that suggest its usefulness, 23.26 +namely 23.27 + - Composition of arrows corresponds to compound inference. 23.28 + - In the special case of deductive inference, the inferential arrow is an 23.29 + identity; the source and destination states of knowledge are the same. 23.30 + - One aspect of the consistency requirement of Jaynes[fn:1] takes the form of a 23.31 + commutative square: \(x\rightarrow ax \rightarrow abx\) = 23.32 + \(x\rightarrow bx \rightarrow abx\) is the categorified version of 23.33 + \((AB|X)=(A|X)\cdot(B|AX)=(B|X)\cdot(A|BX)\). 23.34 + - We can make plausibility assignments by enriching the inductive 23.35 + category \(P^*\) over some monoidal category, e.g. the set of real numbers 23.36 + (considered as a category) with its usual multiplication. /When we do/, 23.37 + the identity arrows of \(P^*\) \mdash{}corresponding to 23.38 + deductive inferences\mdash{} are assigned a value of certainty automatically. 23.39 + 23.40 +[fn:1] /(IIIa) If a conclusion can be reasoned out in more than one 23.41 +way, then every possible way must lead to the same result./ 23.42 + 23.43 +
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/categorical/synthetic.html Fri Oct 28 00:03:05 2011 -0700 24.3 @@ -0,0 +1,282 @@ 24.4 +<?xml version="1.0" encoding="utf-8"?> 24.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 24.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 24.7 +<html xmlns="http://www.w3.org/1999/xhtml" 24.8 +lang="en" xml:lang="en"> 24.9 +<head> 24.10 +<title>Synthetic Differential Geometry</title> 24.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 24.12 +<meta name="generator" content="Org-mode"/> 24.13 +<meta name="generated" content="2011-08-15 22:42:41 EDT"/> 24.14 +<meta name="author" content="Dylan Holmes"/> 24.15 +<meta name="description" content=""/> 24.16 +<meta name="keywords" content=""/> 24.17 +<style type="text/css"> 24.18 + <!--/*--><![CDATA[/*><!--*/ 24.19 + html { font-family: Times, serif; font-size: 12pt; } 24.20 + .title { text-align: center; } 24.21 + .todo { color: red; } 24.22 + .done { color: green; } 24.23 + .tag { background-color: #add8e6; font-weight:normal } 24.24 + .target { } 24.25 + .timestamp { color: #bebebe; } 24.26 + .timestamp-kwd { color: #5f9ea0; } 24.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 24.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 24.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 24.30 + p.verse { margin-left: 3% } 24.31 + pre { 24.32 + border: 1pt solid #AEBDCC; 24.33 + background-color: #F3F5F7; 24.34 + padding: 5pt; 24.35 + font-family: courier, monospace; 24.36 + font-size: 90%; 24.37 + overflow:auto; 24.38 + } 24.39 + table { border-collapse: collapse; } 24.40 + td, th { vertical-align: top; } 24.41 + th.right { text-align:center; } 24.42 + th.left { text-align:center; } 24.43 + th.center { text-align:center; } 24.44 + td.right { text-align:right; } 24.45 + td.left { text-align:left; } 24.46 + td.center { text-align:center; } 24.47 + dt { font-weight: bold; } 24.48 + div.figure { padding: 0.5em; } 24.49 + div.figure p { text-align: center; } 24.50 + textarea { overflow-x: auto; } 24.51 + .linenr { font-size:smaller } 24.52 + .code-highlighted {background-color:#ffff00;} 24.53 + .org-info-js_info-navigation { border-style:none; } 24.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 24.55 + white-space:nowrap; } 24.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 24.57 + font-weight:bold; } 24.58 + /*]]>*/--> 24.59 +</style> 24.60 +<link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 24.61 +<script type="text/javascript"> 24.62 +<!--/*--><![CDATA[/*><!--*/ 24.63 + function CodeHighlightOn(elem, id) 24.64 + { 24.65 + var target = document.getElementById(id); 24.66 + if(null != target) { 24.67 + elem.cacheClassElem = elem.className; 24.68 + elem.cacheClassTarget = target.className; 24.69 + target.className = "code-highlighted"; 24.70 + elem.className = "code-highlighted"; 24.71 + } 24.72 + } 24.73 + function CodeHighlightOff(elem, id) 24.74 + { 24.75 + var target = document.getElementById(id); 24.76 + if(elem.cacheClassElem) 24.77 + elem.className = elem.cacheClassElem; 24.78 + if(elem.cacheClassTarget) 24.79 + target.className = elem.cacheClassTarget; 24.80 + } 24.81 +/*]]>*///--> 24.82 +</script> 24.83 +<script type="text/javascript" src="../MathJax/MathJax.js"> 24.84 +<!--/*--><![CDATA[/*><!--*/ 24.85 + MathJax.Hub.Config({ 24.86 + // Only one of the two following lines, depending on user settings 24.87 + // First allows browser-native MathML display, second forces HTML/CSS 24.88 + config: ["MMLorHTML.js"], jax: ["input/TeX"], 24.89 + // jax: ["input/TeX", "output/HTML-CSS"], 24.90 + extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js", 24.91 + "TeX/noUndefined.js"], 24.92 + tex2jax: { 24.93 + inlineMath: [ ["\\(","\\)"] ], 24.94 + displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ], 24.95 + skipTags: ["script","noscript","style","textarea","pre","code"], 24.96 + ignoreClass: "tex2jax_ignore", 24.97 + processEscapes: false, 24.98 + processEnvironments: true, 24.99 + preview: "TeX" 24.100 + }, 24.101 + showProcessingMessages: true, 24.102 + displayAlign: "left", 24.103 + displayIndent: "2em", 24.104 + 24.105 + "HTML-CSS": { 24.106 + scale: 100, 24.107 + availableFonts: ["STIX","TeX"], 24.108 + preferredFont: "TeX", 24.109 + webFont: "TeX", 24.110 + imageFont: "TeX", 24.111 + showMathMenu: true, 24.112 + }, 24.113 + MMLorHTML: { 24.114 + prefer: { 24.115 + MSIE: "MML", 24.116 + Firefox: "MML", 24.117 + Opera: "HTML", 24.118 + other: "HTML" 24.119 + } 24.120 + } 24.121 + }); 24.122 +/*]]>*///--> 24.123 +</script> 24.124 +</head> 24.125 +<body> 24.126 + 24.127 +<div id="content"> 24.128 + 24.129 + 24.130 + 24.131 +<div class="header"> 24.132 + <div class="float-right"> 24.133 + <!-- 24.134 + <form> 24.135 + <input type="text"/><input type="submit" value="search the blog »"/> 24.136 + </form> 24.137 + --> 24.138 + </div> 24.139 + 24.140 + <h1>aurellem <em>☉</em></h1> 24.141 + <ul class="nav"> 24.142 + <li><a href="/">read the blog »</a></li> 24.143 + <!-- li><a href="#">learn about us »</a></li--> 24.144 + </ul> 24.145 +</div> 24.146 + 24.147 +<h1 class="title">Synthetic Differential Geometry</h1> 24.148 +<div class="author">Written by <author>Dylan Holmes</author></div> 24.149 + 24.150 + 24.151 + 24.152 + 24.153 + 24.154 + 24.155 +<p> 24.156 +(My notes on Anders Kock's <i>Synthetic Differential Geometry</i>) 24.157 +</p> 24.158 + 24.159 +<div id="table-of-contents"> 24.160 +<h2>Table of Contents</h2> 24.161 +<div id="text-table-of-contents"> 24.162 +<ul> 24.163 +<li><a href="#sec-1">1 Revisiting the real line </a> 24.164 +<ul> 24.165 +<li><a href="#sec-1-1">1.1 The first anti-euclidean axiom </a></li> 24.166 +<li><a href="#sec-1-2">1.2 The first axiom \(\ldots\) in terms of arrows </a></li> 24.167 +<li><a href="#sec-1-3">1.3 Ex </a></li> 24.168 +</ul> 24.169 +</li> 24.170 +</ul> 24.171 +</div> 24.172 +</div> 24.173 + 24.174 +<div id="outline-container-1" class="outline-2"> 24.175 +<h2 id="sec-1"><span class="section-number-2">1</span> Revisiting the real line </h2> 24.176 +<div class="outline-text-2" id="text-1"> 24.177 + 24.178 + 24.179 +<p> 24.180 +<b>Lines</b>, the kind which Euclid talked about, each constitute a commutative 24.181 + ring: you choose any two points on the line to be 0 and 1, then add 24.182 + and multiply as if you were dealing with real numbers \(\mathbb{R}\). 24.183 +</p> 24.184 +<p> 24.185 +Euclid moreover uses the axiom that for any two points, <i>either</i> they are the 24.186 +same point <i>or</i> there is a unique line between them. Algebraically, 24.187 +this amounts to saying that each line is not only a commutative ring 24.188 +but a <b>field</b>, as well. This marks our first departure from euclidean 24.189 +geometry, as our first axiom denies that each line is a field. 24.190 +</p> 24.191 + 24.192 + 24.193 +</div> 24.194 + 24.195 +<div id="outline-container-1-1" class="outline-3"> 24.196 +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> The first anti-euclidean axiom </h3> 24.197 +<div class="outline-text-3" id="text-1-1"> 24.198 + 24.199 +<p>A point in a ring is called <b>nilpotent</b> if its square is 24.200 +zero. Normally (that is, in \(\mathbb{R}^n\)), only \(0\) is 24.201 +nilpotent. Here, as a consequence of the following axiom, there will 24.202 +exist other elements that are nilpotent. These elements will 24.203 +encapsulate our intuitive idea of “infinitesimally small” numbers. 24.204 +</p> 24.205 +<blockquote> 24.206 + 24.207 +<p><b>Axiom 1:</b> Let \(R\) be the line, considered as a commutative ring, and 24.208 + let \(D\subset R\) be the set of nilpotent elements on the line. Then for any 24.209 + morphism \(g:D\rightarrow R\), there exists a unique \(b\in R\) such that 24.210 +</p> 24.211 + 24.212 + 24.213 +\(\forall d\in D, g(d) = g(0)+ b\cdot d\) 24.214 + 24.215 +<p> 24.216 +Intuitively, this unique \(b\) is the slope of the function \(g\) near 24.217 +zero. Because every morphism \(g\) has exactly one such \(b\), we have the 24.218 +following results: 24.219 +</p> 24.220 +<ol> 24.221 +<li>The set \(D\) of nilpotent elements contains more than 24.222 + just 0. Indeed, suppose the contrary: if \(D=\{0\}\), then for any \(g\), <i>every</i> \(b\in R\) has the 24.223 + property described above;—\(b\) isn't uniquely defined. 24.224 +</li> 24.225 +<li>Pick \(b_1\) and \(b_2\) in \(R\). If every nilpotent \(d\) satisfies \(d\cdot 24.226 + b_1 = d\cdot b_2\), then \(b_1\) and \(b_2\) are equal. 24.227 +</li> 24.228 +</ol> 24.229 + 24.230 + 24.231 +</div> 24.232 + 24.233 +</div> 24.234 + 24.235 +<div id="outline-container-1-2" class="outline-3"> 24.236 +<h3 id="sec-1-2"><span class="section-number-3">1.2</span> The first axiom \(\ldots\) in terms of arrows </h3> 24.237 +<div class="outline-text-3" id="text-1-2"> 24.238 + 24.239 + 24.240 +<p> 24.241 +Define \(\xi:R\times R\rightarrow R^D\) by \(\xi:(a,b)\mapsto (d\mapsto 24.242 +a+b\cdot d)\). The first axiom is equivalent to the statement 24.243 +“ξ is invertible (i.e., a bijection)” 24.244 +</p> 24.245 +<p> 24.246 +We give \(R\times R\) the structure of an \(R\)-algebra by defining 24.247 +multiplication: \( (a_1,b_1)\star(a_2,b_2) = (a_1\cdot a_2,\quad 24.248 +a_1\cdot b_2 + a_2\cdot b_1)\). This is called <b>dual-numbers multiplication</b>, and is similar to muliplication of complex numbers. 24.249 +</p> 24.250 + 24.251 +</div> 24.252 + 24.253 +</div> 24.254 + 24.255 +<div id="outline-container-1-3" class="outline-3"> 24.256 +<h3 id="sec-1-3"><span class="section-number-3">1.3</span> Ex </h3> 24.257 +<div class="outline-text-3" id="text-1-3"> 24.258 + 24.259 +<ol> 24.260 +<li>If \(a\) and \(b\) are nilpotent, then \(ab\) is nilpotent. 24.261 +</li> 24.262 +<li>Even if \(a\) and \(b\) are nilpotent, the sum \(a+b\) may not be. 24.263 +</li> 24.264 +<li>Even if \(a+b\) is nilpotent, either summand \(a\), \(b\) may not be. 24.265 +</li> 24.266 +<li> 24.267 +</li> 24.268 +</ol> 24.269 + 24.270 + 24.271 + 24.272 +</blockquote> 24.273 + 24.274 +</div> 24.275 +</div> 24.276 +</div> 24.277 +<div id="postamble"> 24.278 +<p class="date">Date: 2011-08-15 22:42:41 EDT</p> 24.279 +<p class="author">Author: Dylan Holmes</p> 24.280 +<p class="creator">Org version 7.6 with Emacs version 23</p> 24.281 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 24.282 +</div> 24.283 +</div> 24.284 +</body> 24.285 +</html>
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/categorical/synthetic.org Fri Oct 28 00:03:05 2011 -0700 25.3 @@ -0,0 +1,68 @@ 25.4 +#+TITLE: Synthetic Differential Geometry 25.5 +#+author: Dylan Holmes 25.6 +#+EMAIL: rlm@mit.edu 25.7 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js" 25.8 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 25.9 +#+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 25.10 +#+SETUPFILE: ../templates/level-0.org 25.11 +#+INCLUDE: ../templates/level-0.org 25.12 +#+BABEL: :noweb yes :results silent 25.13 + 25.14 +(My notes on Anders Kock's /Synthetic Differential Geometry/) 25.15 + 25.16 +* Revisiting the real line 25.17 + 25.18 +*Lines*, the kind which Euclid talked about, each constitute a commutative 25.19 + ring: you choose any two points on the line to be 0 and 1, then add 25.20 + and multiply as if you were dealing with real numbers $\mathbb{R}$. 25.21 + 25.22 +Euclid moreover uses the axiom that for any two points, /either/ they are the 25.23 +same point /or/ there is a unique line between them. Algebraically, 25.24 +this amounts to saying that each line is not only a commutative ring 25.25 +but a *field*, as well. This marks our first departure from euclidean 25.26 +geometry, as our first axiom denies that each line is a field. 25.27 + 25.28 + 25.29 +** The first anti-euclidean axiom 25.30 +A point in a ring is called *nilpotent* if its square is 25.31 +zero. Normally (that is, in $\mathbb{R}^n$), only $0$ is 25.32 +nilpotent. Here, as a consequence of the following axiom, there will 25.33 +exist other elements that are nilpotent. These elements will 25.34 +encapsulate our intuitive idea of \ldquo{}infinitesimally small\rdquo{} numbers. 25.35 + 25.36 +#+begin_quote 25.37 +*Axiom 1:* Let $R$ be the line, considered as a commutative ring, and 25.38 + let $D\subset R$ be the set of nilpotent elements on the line. Then for any 25.39 + morphism $g:D\rightarrow R$, there exists a unique $b\in R$ such that 25.40 + 25.41 +\(\forall d\in D, g(d) = g(0)+ b\cdot d\) 25.42 + 25.43 +Intuitively, this unique $b$ is the slope of the function $g$ near 25.44 +zero. Because every morphism $g$ has exactly one such $b$, we have the 25.45 +following results: 25.46 + 25.47 +1. The set $D$ of nilpotent elements contains more than 25.48 + just 0. Indeed, suppose the contrary: if $D=\{0\}$, then for any $g$, /every/ $b\in R$ has the 25.49 + property described above;\mdash{}$b$ isn't uniquely defined. 25.50 +2. Pick $b_1$ and $b_2$ in $R$. If every nilpotent $d$ satisfies $d\cdot 25.51 + b_1 = d\cdot b_2$, then $b_1$ and $b_2$ are equal. 25.52 + 25.53 +** The first axiom $\ldots$ in terms of arrows 25.54 + 25.55 +Define $\xi:R\times R\rightarrow R^D$ by \(\xi:(a,b)\mapsto (d\mapsto 25.56 +a+b\cdot d)\). The first axiom is equivalent to the statement 25.57 +\ldquo{}\xi is invertible (i.e., a bijection)\rdquo{} 25.58 + 25.59 +We give $R\times R$ the structure of an $R$-algebra by defining 25.60 +multiplication: \( (a_1,b_1)\star(a_2,b_2) = (a_1\cdot a_2,\quad 25.61 +a_1\cdot b_2 + a_2\cdot b_1)\). This is called *dual-numbers 25.62 +multiplication*, and is similar to muliplication of complex numbers. 25.63 + 25.64 + 25.65 +** Ex 25.66 +1. If $a$ and $b$ are nilpotent, then $ab$ is nilpotent. 25.67 +2. Even if $a$ and $b$ are nilpotent, the sum $a+b$ may not be. 25.68 +3. Even if $a+b$ is nilpotent, either summand $a$, $b$ may not be. 25.69 +4. 25.70 + 25.71 +#+end_quote
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/chat/room.clj Fri Oct 28 00:03:05 2011 -0700 26.3 @@ -0,0 +1,34 @@ 26.4 +(ns chat.room 26.5 + (:use [clojure.contrib server-socket duck-streams str-utils]) 26.6 + (:gen-class)) 26.7 + 26.8 + 26.9 +;; CHAT ROOMS 26.10 + 26.11 +(def rooms (ref {})) 26.12 + 26.13 +(defn get-room! "Returns the chat room with the given name, creating it if necessary." [name] 26.14 + (dosync 26.15 + (or (@rooms name) 26.16 + (let [new-room (agent '())] 26.17 + (do (alter *rooms* assoc name new-room)))))) 26.18 + 26.19 +(defn say-in-room[room message] 26.20 + (doseq [[_ output] room] 26.21 + (binding [*out* output] 26.22 + (println message)))) 26.23 + 26.24 + 26.25 +;; USERS 26.26 + 26.27 +(defn user-join[room username output-channel] 26.28 + (conj room [username output-channel])) 26.29 +(defn user-leave[room username] 26.30 + (remove #(= (% 0) username) room)) 26.31 + 26.32 + 26.33 +(def *username* "Someone") 26.34 +(defn- join-room [room] 26.35 + (send room user-join *username* *out*) 26.36 + (send room 26.37 + )
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/clojure_magick/magick.clj Fri Oct 28 00:03:05 2011 -0700 27.3 @@ -0,0 +1,151 @@ 27.4 +(ns clojure-magick.magick) 27.5 +(import [org.im4java.core ConvertCmd IMOperation Stream2BufferedImage] ) 27.6 + 27.7 +(defn read-image "Read the image in the specified file; returns a BufferedImage." [filename] 27.8 + (let [op (doto (IMOperation.) 27.9 + (.addImage (into-array String [filename])) 27.10 + (.addImage (into-array String ["-"]))) 27.11 + s2b (Stream2BufferedImage.)] 27.12 + (doto (ConvertCmd.) 27.13 + (.setOutputConsumer s2b) 27.14 + (.run op (into-array Object []))) 27.15 + (.getImage s2b)) 27.16 +) 27.17 + 27.18 +(defn write-image "Write the image to the specified file." [img filename] 27.19 + (let [op (doto (IMOperation.) 27.20 + (.addImage) 27.21 + (.addImage))] 27.22 + (.run (ConvertCmd.) op (into-array Object [img filename]))) 27.23 +) 27.24 + 27.25 + 27.26 +(defn glue-vertical "Concatenate images in a sequence from top to bottom, producing a new image." [image & imgs] 27.27 + (let [imgs (cons image imgs) 27.28 + op (doto (IMOperation.) 27.29 + (.addImage (count imgs)) 27.30 + (.append) 27.31 + (.addImage (into-array String ["-"]))) 27.32 + s2b (Stream2BufferedImage.)] 27.33 + (doto (ConvertCmd.) 27.34 + (.setOutputConsumer s2b) 27.35 + (.run op (into-array Object (vec imgs)))) 27.36 + (.getImage s2b) 27.37 +)) 27.38 + 27.39 +(defn glue-horizontal "Concatenate images in a sequence from left to right, producing a new image." [image & imgs] 27.40 + (let [imgs (cons image imgs) 27.41 + op (doto (IMOperation.) 27.42 + (.addImage (count imgs)) 27.43 + (.p_append) 27.44 + (.addImage (into-array String ["-"]))) 27.45 + s2b (Stream2BufferedImage.)] 27.46 + (doto (ConvertCmd.) 27.47 + (.setOutputConsumer s2b) 27.48 + (.run op (into-array Object (vec imgs)))) 27.49 + (.getImage s2b) 27.50 + )) 27.51 + 27.52 + 27.53 + 27.54 +(defn resize "Resize the image, keeping the same aspect ratio." 27.55 + ([img width height] 27.56 + (let [op (doto (IMOperation.) 27.57 + (.addImage) 27.58 + (.resize width height) 27.59 + (.addImage (into-array String ["-"]))) 27.60 + s2b (Stream2BufferedImage.)] 27.61 + (doto (ConvertCmd.) 27.62 + (.setOutputConsumer s2b) 27.63 + (.run op (into-array Object [img]))) 27.64 + (.getImage s2b) 27.65 + )) 27.66 + ( 27.67 + [img width] 27.68 + (resize img width nil) 27.69 + ) 27.70 +) 27.71 + 27.72 + 27.73 +(defn upside-down "Flip the image upside down." 27.74 + [img] 27.75 + (let [op (doto (IMOperation.) 27.76 + (.addImage) 27.77 + (.flip) 27.78 + (.addImage (into-array String ["-"]))) 27.79 + s2b (Stream2BufferedImage.)] 27.80 + (doto (ConvertCmd.) 27.81 + (.setOutputConsumer s2b) 27.82 + (.run op (into-array Object [img]))) 27.83 + (.getImage s2b) 27.84 + ) 27.85 +) 27.86 + 27.87 + 27.88 +(defn scale-rotate-translate "Scale the image, then rotate the image about the axis coordinates, then translate the image by the given amount. Does not change the dimensions of the picture." 27.89 + ([img axis-x axis-y scale-x scale-y degrees translate-x translate-y] 27.90 + (let [arg-str (apply str (list axis-x "," axis-y " " scale-x "," scale-y " " degrees " " translate-x "," translate-y)) 27.91 + op (doto (IMOperation.) 27.92 + (.addImage) 27.93 + (.distort "ScaleRotateTranslate" arg-str) 27.94 + (.addImage (into-array String ["-"]))) 27.95 + s2b (Stream2BufferedImage.)] 27.96 + (doto (ConvertCmd.) 27.97 + (.setOutputConsumer s2b) 27.98 + (.run op (into-array Object [img]))) 27.99 + (.getImage s2b))) 27.100 + ([img axis-x axis-y scale degrees translate-x translate-y] 27.101 + (recur axis-x axis-y scale scale degrees translate-x translate-y)) 27.102 +) 27.103 + 27.104 + 27.105 +(defn rotate "Rotate the image clockwise by the given amount." [img degrees] 27.106 + (let [op (doto (IMOperation.) 27.107 + (.addImage) 27.108 + (.distort "ScaleRotateTranslate" (str degrees)) 27.109 + (.addImage (into-array String ["-"]))) 27.110 + s2b (Stream2BufferedImage.)] 27.111 + (doto (ConvertCmd.) 27.112 + (.setOutputConsumer s2b) 27.113 + (.run op (into-array Object [img]))) 27.114 + (.getImage s2b)) 27.115 +) 27.116 + 27.117 + 27.118 + 27.119 + 27.120 + 27.121 + 27.122 + 27.123 + 27.124 + 27.125 + 27.126 + 27.127 + 27.128 + 27.129 + 27.130 + 27.131 + 27.132 + 27.133 + 27.134 + 27.135 + 27.136 + 27.137 + 27.138 + 27.139 + 27.140 + 27.141 + 27.142 +(defn resize[] 27.143 + (let [op (doto (IMOperation.) 27.144 + (.addImage (into-array String ["/home/r/jiggly.gif"])) 27.145 + (.resize 800 600) 27.146 + (.addImage (into-array String ["/home/r/jiggly_sm.gif"])) 27.147 + )] 27.148 + (.run (ConvertCmd.) op (into-array Object [])))) 27.149 + 27.150 + 27.151 +(defn run-test[] 27.152 + (let [puff (read-image "/home/r/jiggly.gif")] 27.153 + (write-image (glue-horizontal puff puff puff) "/home/r/multijiggly.gif") 27.154 + ))
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/mtg/bk.clj Fri Oct 28 00:03:05 2011 -0700 28.3 @@ -0,0 +1,39 @@ 28.4 +(ns mtg.frame) 28.5 + 28.6 +;; GENERALLY USEFUL FUNCTIONS 28.7 + 28.8 +(defn assay "Takes x and a series of pred-value pairs. Returns a list of vals for which the corresponding preds are true of x." [x & pred-vals] 28.9 + (reduce #(if ((first %2) x) (conj %1 (second %2))) '() pred-vals) 28.10 + ) 28.11 +(defn alter-val "Applies f to the current value associated with each key, associating each key with the value returned." [m f & keys] 28.12 + (map #(assoc m % (f (get m %))) keys)) 28.13 + 28.14 +(defn every-nth "Returns every nth member of coll. If n is not positive, returns an empty list." [n coll] 28.15 + (if (<= n 0) '() 28.16 + (take-while (comp not nil?) (map first (iterate #(nthnext % n) coll))))) 28.17 + 28.18 + 28.19 + 28.20 + 28.21 + 28.22 +;; FRAME MANIPULATION 28.23 + 28.24 + 28.25 +(defn conj-key "Adds the xs to the seq associated with the given key." [map key & xs] 28.26 + (assoc map key (apply conj (get map key []) xs))) 28.27 + 28.28 +(defn update "Takes a frame and a sequence of key-fn pairs. Applies f to the current value associated with key, updating the current value with the result. Frames generate and store a unique id for each call to update." 28.29 + [frame & kfs] 28.30 + (let [id (gensym "up_") 28.31 + keys (every-nth 2 kfs) 28.32 + fns (every-nth 2 (rest kfs))] 28.33 + 28.34 + ((reduce comp (map (fn[k f](fn[m](conj-key m k (list id f) )) keys fns)) 28.35 + (conj-key frame :*bindings* (map (fn [k f](list id k)) keys fns)) 28.36 + ) 28.37 +)) 28.38 + 28.39 + 28.40 + 28.41 + 28.42 +(def *frame* (atom {:*bindings* '()}))
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/mtg/continuation.clj Fri Oct 28 00:03:05 2011 -0700 29.3 @@ -0,0 +1,159 @@ 29.4 +(ns mtg.continuation) 29.5 +;; convention: cps function names end in & 29.6 + 29.7 +(def not-nil? (comp not nil?)) 29.8 +(defn cpt "Continuation-passing transform. Makes f take a continuation as an additional argument."[f] 29.9 + (fn[& args] 29.10 + ((last args) (apply f (butlast args))))) 29.11 + 29.12 + 29.13 + 29.14 +;; Card operations 29.15 + 29.16 + 29.17 +;; Open predicates 29.18 + ;(defmacro literal-to-keyword[x] `(keyword (quote ~x))) 29.19 +(defrecord Oracle []) 29.20 +(def *oracle* (atom (Oracle.))) 29.21 + 29.22 +(defn ask* [m k](get @m k (cpt(constantly nil)))) 29.23 +(defn tell!* [m k v] (swap! m assoc k v)) 29.24 + 29.25 +(def ask(partial ask* *oracle*)) 29.26 +;(def ? (fn [k & args] (apply (ask k) args))) 29.27 + 29.28 +(def tell! (partial tell!* *oracle*)) 29.29 +(defn extend[k f] ((ask k) f)) 29.30 + 29.31 +;; PRELIMINARY DEFINITIONS 29.32 +(defmacro defq "Defines a query." [name params & body] 29.33 + `(tell! (keyword ~name) (fn ~params ~@body))) 29.34 +(defmacro ? "Asks a query." [name & args] 29.35 + `((ask (keyword name)) ~@args)) 29.36 + 29.37 +(defn true-preds "Returns a sequence of the preds for which (pred obj) returns true." 29.38 + [obj & preds] 29.39 + (map (comp (partial apply str) rest butlast str) 29.40 + (filter #(? % obj) preds))) 29.41 + 29.42 +(tell! :the-players #{}) 29.43 +(tell! :player? (fn[obj & _] (not-nil? (? the-players obj)))) 29.44 + 29.45 + 29.46 + 29.47 + 29.48 + 29.49 + 29.50 + 29.51 +(defq object? [obj & _] ;; 109.1 29.52 + ((comp not empty?)(true-preds obj :card? :copied-card? :token? :spell? :permanent? :emblem?))) 29.53 + 29.54 +(defq has-controller? [obj & _] 29.55 + (if (and (not (? in-zone 'battlefield obj)) 29.56 + (not (? on-stack obj))) false)) 29.57 + 29.58 +(defq take-turn [player & _] nil) 29.59 + 29.60 + 29.61 +(tell! :characteristics (fn[obj & _] 29.62 + (list :name :mana-cost :color :card-type :subtype :supertype :expansion-symbol :rules-text :abilities :power :toughness :loyalty :hand-modifier :life-modifier))) 29.63 + 29.64 + 29.65 + 29.66 + 29.67 +(tell! :colors 29.68 + (fn[obj & _] 29.69 + (true-preds obj :red? :blue? :green? :white? :black?))) 29.70 + 29.71 + 29.72 + 29.73 + 29.74 + 29.75 + 29.76 +;; GAME / TURN MECHANICS 29.77 +(defn new-game "Start a new two-player game."[] 29.78 + (tell! :the-players #{'PLAYERONE 'PLAYERTWO}) 29.79 + (tell! :life-total (reduce #(assoc %1 (keyword %2) 20) {} (ask :the-players) )) 29.80 +) 29.81 + 29.82 + 29.83 + 29.84 +;;(ask :blue) blue? = (fn[& args](fn[k] (k ...) )) 29.85 +;; (cpt (constantly nil)) 29.86 +;;(ask k) = (get self k (cpt(constantly nil))) 29.87 + 29.88 + 29.89 + 29.90 + 29.91 + 29.92 + 29.93 +(defn reverse&[coll k] 29.94 + (if (empty? coll) (k '()) 29.95 + (recur (rest coll) (fn[x](k (conj x (first coll)))) 29.96 + 29.97 + ))) 29.98 + 29.99 + 29.100 + 29.101 + 29.102 + 29.103 + 29.104 + 29.105 + 29.106 + 29.107 + 29.108 + 29.109 + 29.110 + 29.111 + 29.112 + 29.113 + 29.114 +(defn choose "Asks player to choose a member of the universe which matches all the given predicate; returns the chosen member." [player & preds] 29.115 + 29.116 + ) 29.117 + 29.118 + 29.119 +(defn get* "Returns the value of key for the object, default or nil if key is not present." 29.120 + ([obj key]) 29.121 + ([obj key default])) 29.122 + 29.123 + 29.124 + 29.125 + 29.126 + 29.127 + 29.128 + 29.129 + 29.130 + 29.131 + 29.132 + 29.133 + 29.134 + 29.135 +;; shuffle decks 29.136 +;; anyone may cut anyone else's deck 29.137 +;; deck => library 29.138 +;; decide who goes first 29.139 +;; players decide whether to mulligan in APNAP 29.140 +;; players mulligan simultaneously 29.141 +;; ... finish mulligans 29.142 +;; opening hand abilities 29.143 +;; beginning game abilities 29.144 +;; 2P game: first player skips draw phase of first turn 29.145 + 29.146 +;; pooled mana: produced-by, spendable-on 29.147 + 29.148 + 29.149 + 29.150 + 29.151 +;; VALUES WITH MODIFICATION HISTORY 29.152 +;(deftype trace[subject ]) 29.153 + 29.154 +;(defn trace [x]{:subject x :modifiers '()}) 29.155 +;(defn modifiers[tr] (get :modifiers tr '())) 29.156 +;(defn subject[tr] (:subject tr)) 29.157 + 29.158 +;(defn modify[tr f](assoc tr :modifiers (conj (modifiers tr) f))) 29.159 +;(defn compute[tr] (:modifiers tr)) 29.160 + 29.161 +;; players 29.162 +
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/mtg/frame.clj Fri Oct 28 00:03:05 2011 -0700 30.3 @@ -0,0 +1,50 @@ 30.4 +(ns mtg.frame) 30.5 + 30.6 +;; GENERALLY USEFUL FUNCTIONS 30.7 + 30.8 +(defn assay "Takes x and a series of pred-value pairs. Returns a list of vals for which the corresponding preds are true of x." [x & pred-vals] 30.9 + (reduce #(if ((first %2) x) (conj %1 (second %2))) '() pred-vals) 30.10 + ) 30.11 +(defn alter-val "Applies f to the current value associated with each key, associating each key with the value returned." [m f & keys] 30.12 + (map #(assoc m % (f (get m %))) keys)) 30.13 + 30.14 +(defn every-nth "Returns every nth member of coll. If n is not positive, returns an empty list." [n coll] 30.15 + (if (<= n 0) '() 30.16 + (take-while (comp not nil?) (map first (iterate #(nthnext % n) coll))))) 30.17 + 30.18 + 30.19 + 30.20 + 30.21 + 30.22 +;; FRAME MANIPULATION 30.23 + 30.24 +(defn conj-key "Adds the xs to the seq associated with the given key." [map key & xs] 30.25 + (assoc map key (apply conj (get map key []) xs))) 30.26 + 30.27 +(defn update "Takes a frame and a sequence of key-fn pairs. Applies f to the current value associated with key, updating the current value with the result. Frames generate and store a unique id for each call to update." 30.28 + [frame & kfs] 30.29 + (let [id (gensym "") 30.30 + keys (every-nth 2 kfs) 30.31 + fns (every-nth 2 (rest kfs))] 30.32 + 30.33 + ((reduce comp (map (fn[k f](fn[m](conj-key m k (list id f)))) keys fns)) 30.34 + (conj-key frame :*bindings* (map (fn [k f](list id k)) keys fns)) 30.35 + ) 30.36 +)) 30.37 + 30.38 +(defn rollback "Undo the update with the given id." [frame id] 30.39 + (let [affected-keys 30.40 + (conj (map second (filter #(=(first %) id) (:*bindings* frame))) :*bindings*)] 30.41 + (reduce (fn[frame key] 30.42 + (alter-val (partial filter #(=(first %) id)) key) 30.43 + ) frame affected-keys) 30.44 + )) 30.45 + 30.46 + 30.47 +(defn get-fn "Keys in a frame store lists of modifiers. Produces the end result of applying all the modifiers in order." [frame key] 30.48 + (reduce #(%2) (constantly nil) (list (constantly 1))) 30.49 +) 30.50 + 30.51 + 30.52 +(def *frame* (atom {:*bindings* '()})) 30.53 +
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/mtg/mtg_cards.txt Fri Oct 28 00:03:05 2011 -0700 31.3 @@ -0,0 +1,42 @@ 31.4 +:name "Mountain" 31.5 +:color 'R 31.6 +:type "Land" 31.7 +:supertype "Basic" 31.8 +:subtype "Mountain" 31.9 +:rarity 'C 31.10 + 31.11 +:name "Island" 31.12 +:color 'B 31.13 +:type "Land" 31.14 +:supertype "Basic" 31.15 +:subtype "Island" 31.16 +:rarity 'C 31.17 + 31.18 +:name "Forest" 31.19 +:color 'G 31.20 +:type "Land" 31.21 +:supertype "Basic" 31.22 +:subtype "Forest" 31.23 +:rarity 'C 31.24 + 31.25 +:name "Plains" 31.26 +:color 'W 31.27 +:type "Land" 31.28 +:supertype "Basic" 31.29 +:subtype "Plains" 31.30 +:rarity 'C 31.31 + 31.32 +:name "Swamp" 31.33 +:color 'B 31.34 +:type "Land" 31.35 +:supertype "Basic" 31.36 +:subtype "Swamp" 31.37 +:rarity 'C 31.38 + 31.39 +:name "Knight Errant" 31.40 +:color 'W 31.41 +:cost "1W" 31.42 +:type "Creature" 31.43 +:subtype "Human Knight" 31.44 +:p 2 31.45 +:t 2
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/org/science.org Fri Oct 28 00:03:05 2011 -0700 32.3 @@ -0,0 +1,44 @@ 32.4 +#+title: Science Minus Science 32.5 +#+author: Dylan Holmes 32.6 +#+email: ocsenave@gmail.com 32.7 +#+description: What's wrong with our current Science Education? 32.8 +#+SETUPFILE: ../../aurellem/org/setup.org 32.9 +#+INCLUDE: ../../aurellem/org/level-0.org 32.10 + 32.11 + 32.12 +From what I've seen, today's science classrooms are remarkably 32.13 +unscientific. Someone has decided that it is less important to teach 32.14 +the empirical mindset than to impart our accumulated scientific 32.15 +knowledge. Thus, because the field is so vast nowadays, teachers are 32.16 +obliged to be frugal with the facts: they must prune tangential 32.17 +subjects and pare whatever's left, watering down complicated results 32.18 +into simplified half-truths. Needs must when the devil drives, of 32.19 +course--but what is the end result? 32.20 + 32.21 +In modern science classrooms, we force-feed students a deluge of 32.22 +unfamiliar scientific dogma which they must swallow in time to 32.23 +regurgitate onto an exam. To accomplish this daunting task, they 32.24 +cannot possibly stop to consider various alternatives which scientists 32.25 +have methodically eliminated over the course of centuries; instead, 32.26 +they must simply trust that science has done what it purports to have 32.27 +done--or, faster, simply stamp out their conjectural, critical 32.28 +instincts. 32.29 + 32.30 +By the end of such a course, students might be able to recite the 32.31 +tenets of our current scientific creed and might employ those tenets 32.32 +when answering carefully formulated questions. But even if, by chance, 32.33 +our students get their facts straight, they will have acquired at most 32.34 +only our pre-processed truths, and nothing of the empirical machinery 32.35 +that produced them. In my opinion, such a lackluster result demands 32.36 +that we re-evaluate our priorities. Surely the shibboleth of the 32.37 +scientist is not his ability to recount the bleeding-edge depiction of 32.38 +reality--after all, theories are transient and revolutions expected--but 32.39 +rather his pervasive inquiries about the world and his methodical, 32.40 +empirical approach to answering them? Indeed, don't we recognize the 32.41 +scientist by his lack of allegiance to the status quo, by the way he 32.42 +scrutinizes even his own theories with utmost irreverence? 32.43 + 32.44 +In valuing data absorption over methodical reason, we give our 32.45 +students a fragmentary and moreover inexplicable impression of 32.46 +reality. We must ask ourselves: how much of science is left in that? 32.47 +
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/proof.org Fri Oct 28 00:03:05 2011 -0700 33.3 @@ -0,0 +1,151 @@ 33.4 +#+TITLE: WFF 'n Proof 33.5 +#+AUTHOR: Dylan Holmes 33.6 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js" 33.7 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 33.8 +#+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 33.9 +#+SETUPFILE: ../templates/level-0.org 33.10 +#+INCLUDE: ../templates/level-0.org 33.11 +#+BABEL: :noweb yes :results verbatim :cache yes 33.12 + 33.13 + 33.14 +* Introduction 33.15 +WFF 'n Proof is a competitive dice game designed to teach logic. The 33.16 +game is played with several dice whose faces are marked with logical 33.17 +symbols; the goal is to arrange the dice into /well-formed formulas/ (WFFs) \mdash{} 33.18 +expressions that are syntactically correct\mdash{}then to manipulate 33.19 +these formulas to form valid proofs. 33.20 + 33.21 +** About the dice 33.22 +WFF and Proof has small cubes and large cubes which you use like 33.23 +dice. The small cubes have lower-case letters =p=, =q=, =r=, =s=, =i=, 33.24 +and =o= inscribed on their faces, whereas the big cubes have 33.25 +upper-case letters =C=, =A=, =K=, =E=, =N= and =R= on their faces. The 33.26 +lower-case letters stand for /propositions/ that can be either true or 33.27 +false, whereas the 33.28 +upper-case letters stand for certain logical connectives: 33.29 + 33.30 + 33.31 +| Symbol | Meaning | 33.32 +|--------+---------| 33.33 +| =C= | Implies | 33.34 +| =A= | Or | 33.35 +| =K= | And | 33.36 +| =E= | Equals | 33.37 +|--------+---------| 33.38 +| =N= | Not | 33.39 + 33.40 +** Well-formed formulas 33.41 +An expression is a row of dice arranged left-to-right. An expression 33.42 +is a well-formed formula (WFF) if and only if 33.43 +- It is a =p=, =q=, =r=, or =s=; or 33.44 +- It is an =N= followed by a WFF; or 33.45 +- It is a =C=, =A=, =K=, or =E= followed by two WFFs. 33.46 + 33.47 +(Both the lower-case letters =i= and =o= and the upper-case letter =R= 33.48 +are special, and are not used in forming WFFs) 33.49 + 33.50 +* Games you can play with WFF 'n Proof 33.51 +** Shake a WFF 33.52 +Shake a WFF is the simplest game; it teaches you to build and to 33.53 +recognize well-formed formulas, skills that are fundamental to more advanced games. 33.54 + 33.55 +#This game is for two or three players. 33.56 +Each player starts the game with two small cubes and one big cube; 33.57 +these cubes constitute each player's hand. Divide the remaining cubes 33.58 +evenly among the players so that each player has a pile of unused 33.59 +cubes. Also allow space for completed WFFs. 33.60 + 33.61 +At the start of each turn, all of the players toss their dice 33.62 +simultaneously; each player races to build the longest WFF possible 33.63 +out of his own dice. As soon as a player is finished\mdash{}either he 33.64 +has constructed the longest WFF possible or has found that it is impossible to make a WFF\mdash{}he 33.65 +calls out \ldquo{}WFF!\rdquo{} or \ldquo{}No WFF!\rdquo{}. 33.66 + 33.67 +When a player calls out \ldquo{}WFF!\rdquo{} or \ldquo{}No 33.68 +WFF!\rdquo{}, the other players must stop to validate the caller's 33.69 +claim. When a player confirms that the claim is correct, that player 33.70 +calls out \ldquo{}Check!\rdquo{}. Now, either all the players believe 33.71 +that the claim is correct, or they do not. 33.72 + 33.73 + 33.74 +- If all the players confirm that the claim is correct, the caller 33.75 + puts his WFF in the area for completed WFFs, then replenishes his 33.76 + supply of cubes by replacing each of the cubes in his WFF with a 33.77 + cube from his unused-cubes pile (each big cube must be replaced with 33.78 + a big cube, and each small cube must be replaced with a small cube), 33.79 + then takes an additional cube from his pile and receives one 33.80 + point. The turn then ends. 33.81 + 33.82 +- If, when checking the caller's claim, a player believes that the 33.83 + claim was made in error, the player calls out 33.84 + \ldquo{}Challenge!\rdquo{}, then points out the mistake: 33.85 + - If the caller has presented an expression that is not a WFF, the 33.86 + challenger shows that it is not a WFF. 33.87 + - If the caller has presented a WFF that is not the longest possible, 33.88 + the challenger shows how to make a longer WFF from the caller's 33.89 + cubes. 33.90 + - If it is possible to make a WFF from the caller's cubes but the 33.91 + caller claims it is impossible, the challenger shows how to make a 33.92 + WFF from the caller's cubes. 33.93 + The other players verify this challenge. If the challenge was made 33.94 + correctly, the challenging player wins a point and gains an extra 33.95 + cube from his pile whereas the calling player must return a cube to his 33.96 + pile. If the challenge was made wrongly, the challenger must return a 33.97 + cube to his pile. In either case, the turn ends. 33.98 + 33.99 +After the turn ends, the player can play another turn. The game ends 33.100 +when a certain number of cubes are in the area for completed WFFs; 33.101 +this number can be decided before the game begins. 33.102 + 33.103 +One final note is the rule for cubes: 33.104 +#+begin_quote 33.105 +*Cube Rule:* A player's hand must have either the same number of big 33.106 + cubes and small cubes, or one more small cube than big cube. When 33.107 + taking cubes from or returning cubes to your unusued cubes pile, you 33.108 + must make sure to follow this rule. 33.109 +#+end_quote 33.110 + 33.111 + 33.112 + 33.113 + 33.114 + 33.115 + 33.116 +* Misc 33.117 + 33.118 +#+srcname: proof 33.119 +#+begin_src clojure 33.120 +(ns wff.proof) 33.121 + 33.122 +(defn arity[x] 33.123 + (first 33.124 + (keep-indexed 33.125 + (fn[i f](if (nil? (f x)) nil i)) 33.126 + [#{'p 'q 'r 's} 33.127 + #{'N} 33.128 + #{'C 'A 'K 'E}]))) 33.129 + 33.130 +(defn wff? 33.131 + [& symbols] 33.132 + ((fn[stack symbols] 33.133 + ;;(println stack symbols) 33.134 + (if (or(empty? symbols)(empty? stack)) 33.135 + (and(empty? symbols)(empty? stack)) 33.136 + (let [n (arity (first symbols))] 33.137 + (if (nil? n) 33.138 + false 33.139 + (recur (concat (rest stack) (repeat n '*)) (rest symbols)))))) 33.140 + '(*) symbols)) 33.141 + 33.142 +#+end_src 33.143 + 33.144 + 33.145 + 33.146 + 33.147 + 33.148 + 33.149 +* COMMENT tangle 33.150 + 33.151 +#+begin_src clojure :tangle ./proof.clj 33.152 +<<proof>> 33.153 +<<other-proof>> 33.154 +#+end_src
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/sicm/bk/utils.clj Fri Oct 28 00:03:05 2011 -0700 34.3 @@ -0,0 +1,196 @@ 34.4 + 34.5 +(ns sicm.utils) 34.6 + 34.7 + ;***** GENERIC ARITHMETIC 34.8 +(ns sicm.utils) 34.9 +(in-ns 'sicm.utils) 34.10 + 34.11 +(defprotocol Arithmetic 34.12 + (zero [this]) 34.13 + (one [this])) 34.14 + 34.15 + 34.16 +(extend-protocol Arithmetic 34.17 + java.lang.Number 34.18 + (zero [this] 0) 34.19 + (one [this] 1)) 34.20 + 34.21 +(extend-protocol Arithmetic 34.22 + clojure.lang.Seqable 34.23 + (zero [this] (map zero this)) 34.24 + (one [this] (map one this))) 34.25 + 34.26 + 34.27 + ;***** TUPLES AND MATRICES 34.28 +(in-ns 'sicm.utils) 34.29 + 34.30 +(defprotocol Spinning 34.31 + (up? [this]) 34.32 + (down? [this])) 34.33 + 34.34 +(defn spin 34.35 + "Returns the spin of the Spinning s, either :up or :down" 34.36 + [#^Spinning s] 34.37 + (cond (up? s) :up (down? s) :down)) 34.38 + 34.39 + 34.40 +(deftype Tuple 34.41 + [spin coll] 34.42 + clojure.lang.Seqable 34.43 + (seq [this] (seq (.coll this))) 34.44 + clojure.lang.Counted 34.45 + (count [this] (count (.coll this)))) 34.46 + 34.47 +(extend-type Tuple 34.48 + Spinning 34.49 + (up? [this] (= ::up (.spin this))) 34.50 + (down? [this] (= ::down (.spin this)))) 34.51 + 34.52 +(defmethod print-method Tuple 34.53 + [o w] 34.54 + (print-simple (str (if (up? o) 'u 'd) (.coll o)) w)) 34.55 + 34.56 + 34.57 + 34.58 +(defn up 34.59 + "Create a new up-tuple containing the contents of coll." 34.60 + [coll] 34.61 + (Tuple. ::up coll)) 34.62 + 34.63 +(defn down 34.64 + "Create a new down-tuple containing the contents of coll." 34.65 + [coll] 34.66 + (Tuple. ::down coll)) 34.67 + 34.68 + 34.69 +(in-ns 'sicm.utils) 34.70 + 34.71 +(defn numbers? 34.72 + "Returns true if all arguments are numbers, else false." 34.73 + [& xs] 34.74 + (every? number? xs)) 34.75 + 34.76 +(defn contractible? 34.77 + "Returns true if the tuples a and b are compatible for contraction, 34.78 + else false. Tuples are compatible if they have the same number of 34.79 + components, they have opposite spins, and their elements are 34.80 + pairwise-compatible." 34.81 + [a b] 34.82 + (and 34.83 + (isa? (type a) Tuple) 34.84 + (isa? (type b) Tuple) 34.85 + (= (count a) (count b)) 34.86 + (not= (spin a) (spin b)) 34.87 + 34.88 + (not-any? false? 34.89 + (map #(or 34.90 + (numbers? %1 %2) 34.91 + (contractible? %1 %2)) 34.92 + a b)))) 34.93 + 34.94 + 34.95 + 34.96 +(defn contract 34.97 + "Contracts two tuples, returning the sum of the 34.98 + products of the corresponding items. Contraction is recursive on 34.99 + nested tuples." 34.100 + [a b] 34.101 + (if (not (contractible? a b)) 34.102 + (throw 34.103 + (Exception. "Not compatible for contraction.")) 34.104 + (reduce + 34.105 + (map 34.106 + (fn [x y] 34.107 + (if (numbers? x y) 34.108 + (* x y) 34.109 + (contract x y))) 34.110 + a b)))) 34.111 + 34.112 + ;***** MATRICES 34.113 +(in-ns 'sicm.utils) 34.114 +(require 'incanter.core) ;; use incanter's fast matrices 34.115 + 34.116 +(defprotocol Matrix 34.117 + (rows [this]) 34.118 + (cols [this]) 34.119 + (diagonal [this]) 34.120 + (trace [this]) 34.121 + (determinant [this])) 34.122 + 34.123 +(extend-protocol Matrix 34.124 + incanter.Matrix 34.125 + (rows [this] (map down this))) 34.126 + 34.127 + 34.128 + 34.129 + 34.130 +(defn count-rows [matrix] 34.131 + ((comp count rows) matrix)) 34.132 + 34.133 +(defn count-cols [matrix] 34.134 + ((comp count cols) matrix)) 34.135 + 34.136 + 34.137 +(defn matrix-by-rows 34.138 + "Define a matrix by giving its rows." 34.139 + [& rows] 34.140 + (cond 34.141 + (not (all-equal? (map count rows))) 34.142 + (throw (Exception. "All rows in a matrix must have the same number of elements.")) 34.143 + :else 34.144 + (reify Matrix 34.145 + (rows [this] (map down rows)) 34.146 + (cols [this] (map up (apply map vector rows))) 34.147 + (diagonal [this] (map-indexed (fn [i row] (nth row i) rows))) 34.148 + (trace [this] 34.149 + (if (not= (count-rows this) (count-cols this)) 34.150 + (throw (Exception. 34.151 + "Cannot take the trace of a non-square matrix.")) 34.152 + (reduce + (diagonal this)))) 34.153 + 34.154 + (determinant [this] 34.155 + (if (not= (count-rows this) (count-cols this)) 34.156 + (throw (Exception. 34.157 + "Cannot take the determinant of a non-square matrix.")) 34.158 + (reduce * (diagonal this)))) 34.159 + ))) 34.160 + 34.161 + 34.162 +(defn matrix-by-cols 34.163 + "Define a matrix by giving its columns." 34.164 + [& cols] 34.165 + (cond 34.166 + (not (all-equal? (map count cols))) 34.167 + (throw (Exception. "All columns in a matrix must have the same number of elements.")) 34.168 + :else 34.169 + (reify Matrix 34.170 + (cols [this] (map up cols)) 34.171 + (rows [this] (map down (apply map vector cols))) 34.172 + (diagonal [this] (map-indexed (fn [i col] (nth col i) cols))) 34.173 + (trace [this] 34.174 + (if (not= (count-cols this) (count-rows this)) 34.175 + (throw (Exception. 34.176 + "Cannot take the trace of a non-square matrix.")) 34.177 + (reduce + (diagonal this)))) 34.178 + 34.179 + (determinant [this] 34.180 + (if (not= (count-cols this) (count-rows this)) 34.181 + (throw (Exception. 34.182 + "Cannot take the determinant of a non-square matrix.")) 34.183 + (reduce * (map-indexed (fn [i col] (nth col i)) cols)))) 34.184 + ))) 34.185 + 34.186 +(extend-protocol Matrix Tuple 34.187 + (rows [this] (if (down? this) 34.188 + (list this) 34.189 + (map (comp up vector) this))) 34.190 + 34.191 + (cols [this] (if (up? this) 34.192 + (list this) 34.193 + (map (comp down vector) this)))) 34.194 + 34.195 +(defn matrix-multiply [A B] 34.196 + (apply matrix-by-rows 34.197 + (for [a (rows A)] 34.198 + (for [b (cols B)] 34.199 + (contract a b)))))
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/sicm/bk/utils.html Fri Oct 28 00:03:05 2011 -0700 35.3 @@ -0,0 +1,1482 @@ 35.4 +<?xml version="1.0" encoding="utf-8"?> 35.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 35.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 35.7 +<html xmlns="http://www.w3.org/1999/xhtml" 35.8 +lang="en" xml:lang="en"> 35.9 +<head> 35.10 +<title>Building a Classical Mechanics Library in Clojure</title> 35.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 35.12 +<meta name="generator" content="Org-mode"/> 35.13 +<meta name="generated" content="2011-08-09 18:41:37 EDT"/> 35.14 +<meta name="author" content="Robert McIntyre & Dylan Holmes"/> 35.15 +<meta name="description" content=""/> 35.16 +<meta name="keywords" content=""/> 35.17 +<style type="text/css"> 35.18 + <!--/*--><![CDATA[/*><!--*/ 35.19 + html { font-family: Times, serif; font-size: 12pt; } 35.20 + .title { text-align: center; } 35.21 + .todo { color: red; } 35.22 + .done { color: green; } 35.23 + .tag { background-color: #add8e6; font-weight:normal } 35.24 + .target { } 35.25 + .timestamp { color: #bebebe; } 35.26 + .timestamp-kwd { color: #5f9ea0; } 35.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 35.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 35.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 35.30 + p.verse { margin-left: 3% } 35.31 + pre { 35.32 + border: 1pt solid #AEBDCC; 35.33 + background-color: #F3F5F7; 35.34 + padding: 5pt; 35.35 + font-family: courier, monospace; 35.36 + font-size: 90%; 35.37 + overflow:auto; 35.38 + } 35.39 + table { border-collapse: collapse; } 35.40 + td, th { vertical-align: top; } 35.41 + th.right { text-align:center; } 35.42 + th.left { text-align:center; } 35.43 + th.center { text-align:center; } 35.44 + td.right { text-align:right; } 35.45 + td.left { text-align:left; } 35.46 + td.center { text-align:center; } 35.47 + dt { font-weight: bold; } 35.48 + div.figure { padding: 0.5em; } 35.49 + div.figure p { text-align: center; } 35.50 + textarea { overflow-x: auto; } 35.51 + .linenr { font-size:smaller } 35.52 + .code-highlighted {background-color:#ffff00;} 35.53 + .org-info-js_info-navigation { border-style:none; } 35.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 35.55 + white-space:nowrap; } 35.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 35.57 + font-weight:bold; } 35.58 + /*]]>*/--> 35.59 +</style> 35.60 +<link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 35.61 +<script type="text/javascript"> 35.62 +<!--/*--><![CDATA[/*><!--*/ 35.63 + function CodeHighlightOn(elem, id) 35.64 + { 35.65 + var target = document.getElementById(id); 35.66 + if(null != target) { 35.67 + elem.cacheClassElem = elem.className; 35.68 + elem.cacheClassTarget = target.className; 35.69 + target.className = "code-highlighted"; 35.70 + elem.className = "code-highlighted"; 35.71 + } 35.72 + } 35.73 + function CodeHighlightOff(elem, id) 35.74 + { 35.75 + var target = document.getElementById(id); 35.76 + if(elem.cacheClassElem) 35.77 + elem.className = elem.cacheClassElem; 35.78 + if(elem.cacheClassTarget) 35.79 + target.className = elem.cacheClassTarget; 35.80 + } 35.81 +/*]]>*///--> 35.82 +</script> 35.83 +<script type="text/javascript" src="../MathJax/MathJax.js"> 35.84 +<!--/*--><![CDATA[/*><!--*/ 35.85 + MathJax.Hub.Config({ 35.86 + // Only one of the two following lines, depending on user settings 35.87 + // First allows browser-native MathML display, second forces HTML/CSS 35.88 + config: ["MMLorHTML.js"], jax: ["input/TeX"], 35.89 + // jax: ["input/TeX", "output/HTML-CSS"], 35.90 + extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js", 35.91 + "TeX/noUndefined.js"], 35.92 + tex2jax: { 35.93 + inlineMath: [ ["\\(","\\)"] ], 35.94 + displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ], 35.95 + skipTags: ["script","noscript","style","textarea","pre","code"], 35.96 + ignoreClass: "tex2jax_ignore", 35.97 + processEscapes: false, 35.98 + processEnvironments: true, 35.99 + preview: "TeX" 35.100 + }, 35.101 + showProcessingMessages: true, 35.102 + displayAlign: "left", 35.103 + displayIndent: "2em", 35.104 + 35.105 + "HTML-CSS": { 35.106 + scale: 100, 35.107 + availableFonts: ["STIX","TeX"], 35.108 + preferredFont: "TeX", 35.109 + webFont: "TeX", 35.110 + imageFont: "TeX", 35.111 + showMathMenu: true, 35.112 + }, 35.113 + MMLorHTML: { 35.114 + prefer: { 35.115 + MSIE: "MML", 35.116 + Firefox: "MML", 35.117 + Opera: "HTML", 35.118 + other: "HTML" 35.119 + } 35.120 + } 35.121 + }); 35.122 +/*]]>*///--> 35.123 +</script> 35.124 +</head> 35.125 +<body> 35.126 + 35.127 +<div id="content"> 35.128 + 35.129 + 35.130 + 35.131 +<div class="header"> 35.132 + <div class="float-right"> 35.133 + <!-- 35.134 + <form> 35.135 + <input type="text"/><input type="submit" value="search the blog »"/> 35.136 + </form> 35.137 + --> 35.138 + </div> 35.139 + 35.140 + <h1>aurellem <em>☉</em></h1> 35.141 + <ul class="nav"> 35.142 + <li><a href="/">read the blog »</a></li> 35.143 + <!-- li><a href="#">learn about us »</a></li--> 35.144 + </ul> 35.145 +</div> 35.146 + 35.147 +<h1 class="title">Building a Classical Mechanics Library in Clojure</h1> 35.148 + 35.149 + 35.150 + 35.151 + 35.152 + 35.153 + 35.154 + 35.155 +<div id="table-of-contents"> 35.156 +<h2>Table of Contents</h2> 35.157 +<div id="text-table-of-contents"> 35.158 +<ul> 35.159 +<li><a href="#sec-1">1 Generic Arithmetic </a></li> 35.160 +<li><a href="#sec-2">2 Useful Data Types </a> 35.161 +<ul> 35.162 +<li><a href="#sec-2-1">2.1 Complex Numbers </a></li> 35.163 +<li><a href="#sec-2-2">2.2 Tuples and Tensors </a> 35.164 +<ul> 35.165 +<li><a href="#sec-2-2-1">2.2.1 Contraction </a></li> 35.166 +<li><a href="#sec-2-2-2">2.2.2 Matrices </a></li> 35.167 +</ul> 35.168 +</li> 35.169 +<li><a href="#sec-2-3">2.3 Power Series </a></li> 35.170 +</ul> 35.171 +</li> 35.172 +<li><a href="#sec-3">3 Basic Utilities </a> 35.173 +<ul> 35.174 +<li><a href="#sec-3-1">3.1 Sequence manipulation </a></li> 35.175 +<li><a href="#sec-3-2">3.2 Ranges, Airity and Function Composition </a></li> 35.176 +</ul> 35.177 +</li> 35.178 +<li><a href="#sec-4">4 Numerical Methods </a></li> 35.179 +<li><a href="#sec-5">5 Differentiation </a></li> 35.180 +<li><a href="#sec-6">6 Symbolic Manipulation </a></li> 35.181 +</ul> 35.182 +</div> 35.183 +</div> 35.184 + 35.185 +<div id="outline-container-1" class="outline-2"> 35.186 +<h2 id="sec-1"><span class="section-number-2">1</span> Generic Arithmetic </h2> 35.187 +<div class="outline-text-2" id="text-1"> 35.188 + 35.189 + 35.190 + 35.191 + 35.192 + 35.193 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">ns</span> sicm.utils) 35.194 +(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.195 + 35.196 + 35.197 + 35.198 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">all-equal?</span> [coll] 35.199 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">empty?</span> (<span style="color: #8cd0d3;">rest</span> coll)) true 35.200 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">first</span> coll) (<span style="color: #8cd0d3;">second</span> coll)) 35.201 + (<span style="color: #f0dfaf; font-weight: bold;">recur</span> (<span style="color: #8cd0d3;">rest</span> coll))))) 35.202 + 35.203 + 35.204 +(<span style="color: #f0dfaf; font-weight: bold;">defprotocol</span> <span style="color: #f0dfaf;">Arithmetic</span> 35.205 + (zero [this]) 35.206 + (one [this]) 35.207 + (negate [this]) 35.208 + (invert [this]) 35.209 + (conjugate [this])) 35.210 + 35.211 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">zero?</span> [x] 35.212 + (<span style="color: #8cd0d3;">=</span> x (zero x))) 35.213 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">one?</span> [x] 35.214 + (<span style="color: #8cd0d3;">=</span> x (one x))) 35.215 + 35.216 + 35.217 + 35.218 +(<span style="color: #8cd0d3;">extend-protocol</span> Arithmetic 35.219 + java.lang.Number 35.220 + (zero [x] 0) 35.221 + (one [x] 1) 35.222 + (negate [x] (<span style="color: #8cd0d3;">-</span> x)) 35.223 + (invert [x] (<span style="color: #8cd0d3;">/</span> x)) 35.224 + ) 35.225 + 35.226 +(<span style="color: #8cd0d3;">extend-protocol</span> Arithmetic 35.227 + clojure.lang.IFn 35.228 + (one [f] identity) 35.229 + (negate [f] (<span style="color: #8cd0d3;">comp</span> negate f)) 35.230 + (invert [f] (<span style="color: #8cd0d3;">comp</span> invert f))) 35.231 + 35.232 + 35.233 +(<span style="color: #8cd0d3;">extend-protocol</span> Arithmetic 35.234 + clojure.lang.Seqable 35.235 + (zero [this] (<span style="color: #8cd0d3;">map</span> zero this)) 35.236 + (one [this] (<span style="color: #8cd0d3;">map</span> one this)) 35.237 + (invert [this] (<span style="color: #8cd0d3;">map</span> invert this)) 35.238 + (negate [this] (<span style="color: #8cd0d3;">map</span> negate this))) 35.239 + 35.240 + 35.241 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">ordered-like</span> 35.242 + <span style="color: #8fb28f;">"Create a comparator using the sorted collection as an</span> 35.243 +<span style="color: #8fb28f;"> example. Elements not in the sorted collection are sorted to the</span> 35.244 +<span style="color: #8fb28f;"> end."</span> 35.245 + [sorted-coll] 35.246 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [ 35.247 + sorted-coll? (<span style="color: #8cd0d3;">set</span> sorted-coll) 35.248 + ascending-pair? 35.249 + (<span style="color: #8cd0d3;">set</span>(<span style="color: #8cd0d3;">reduce</span> concat 35.250 + (map-indexed 35.251 + (<span style="color: #8cd0d3;">fn</span> [n x] 35.252 + (<span style="color: #8cd0d3;">map</span> #(<span style="color: #8cd0d3;">vector</span> x %) (<span style="color: #8cd0d3;">nthnext</span> sorted-coll n))) 35.253 + sorted-coll)))] 35.254 + (<span style="color: #8cd0d3;">fn</span> [x y] 35.255 + (<span style="color: #f0dfaf; font-weight: bold;">cond</span> 35.256 + (<span style="color: #8cd0d3;">=</span> x y) 0 35.257 + (ascending-pair? [x y]) -1 35.258 + (ascending-pair? [y x]) 1 35.259 + (sorted-coll? x) -1 35.260 + (sorted-coll? y) 1)))) 35.261 + 35.262 + 35.263 + 35.264 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">type-precedence</span> 35.265 + (ordered-like [incanter.Matrix])) 35.266 + 35.267 +(<span style="color: #f0dfaf; font-weight: bold;">defmulti</span> <span style="color: #f0dfaf;">add</span> 35.268 + (<span style="color: #8cd0d3;">fn</span> [x y] 35.269 + (<span style="color: #8cd0d3;">sort</span> type-precedence [(<span style="color: #8cd0d3;">type</span> x)(<span style="color: #8cd0d3;">type</span> y)]))) 35.270 + 35.271 +(<span style="color: #f0dfaf; font-weight: bold;">defmulti</span> <span style="color: #f0dfaf;">multiply</span> 35.272 + (<span style="color: #8cd0d3;">fn</span> [x y] 35.273 + (<span style="color: #8cd0d3;">sort</span> type-precedence [(<span style="color: #8cd0d3;">type</span> x) (<span style="color: #8cd0d3;">type</span> y)]))) 35.274 + 35.275 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">add</span> [java.lang.Number java.lang.Number] [x y] (<span style="color: #8cd0d3;">+</span> x y)) 35.276 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">multiply</span> [java.lang.Number java.lang.Number] [x y] (<span style="color: #8cd0d3;">*</span> x y)) 35.277 + 35.278 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">multiply</span> [incanter.Matrix java.lang.Integer] [x y] 35.279 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [args (<span style="color: #8cd0d3;">sort</span> #(type-precedence (<span style="color: #8cd0d3;">type</span> %1)(<span style="color: #8cd0d3;">type</span> %2)) [x y]) 35.280 + matrix (<span style="color: #8cd0d3;">first</span> args) 35.281 + scalar (<span style="color: #8cd0d3;">second</span> args)] 35.282 + (incanter.core/matrix (<span style="color: #8cd0d3;">map</span> (<span style="color: #8cd0d3;">partial</span> map (<span style="color: #8cd0d3;">partial</span> multiply scalar)) matrix)))) 35.283 + 35.284 +</pre> 35.285 + 35.286 + 35.287 + 35.288 + 35.289 + 35.290 +</div> 35.291 + 35.292 +</div> 35.293 + 35.294 +<div id="outline-container-2" class="outline-2"> 35.295 +<h2 id="sec-2"><span class="section-number-2">2</span> Useful Data Types </h2> 35.296 +<div class="outline-text-2" id="text-2"> 35.297 + 35.298 + 35.299 + 35.300 +</div> 35.301 + 35.302 +<div id="outline-container-2-1" class="outline-3"> 35.303 +<h3 id="sec-2-1"><span class="section-number-3">2.1</span> Complex Numbers </h3> 35.304 +<div class="outline-text-3" id="text-2-1"> 35.305 + 35.306 + 35.307 + 35.308 + 35.309 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.310 + 35.311 +(<span style="color: #f0dfaf; font-weight: bold;">defprotocol</span> <span style="color: #f0dfaf;">Complex</span> 35.312 + (real-part [z]) 35.313 + (imaginary-part [z]) 35.314 + (magnitude-squared [z]) 35.315 + (angle [z]) 35.316 + (conjugate [z]) 35.317 + (norm [z])) 35.318 + 35.319 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">complex-rectangular</span> 35.320 + <span style="color: #8fb28f;">"Define a complex number with the given real and imaginary</span> 35.321 +<span style="color: #8fb28f;"> components."</span> 35.322 + [re im] 35.323 + (<span style="color: #8cd0d3;">reify</span> Complex 35.324 + (real-part [z] re) 35.325 + (imaginary-part [z] im) 35.326 + (magnitude-squared [z] (<span style="color: #8cd0d3;">+</span> (<span style="color: #8cd0d3;">*</span> re re) (<span style="color: #8cd0d3;">*</span> im im))) 35.327 + (angle [z] (java.lang.Math/atan2 im re)) 35.328 + (conjugate [z] (complex-rectangular re (<span style="color: #8cd0d3;">-</span> im))) 35.329 + 35.330 + Arithmetic 35.331 + (zero [z] (complex-rectangular 0 0)) 35.332 + (one [z] (complex-rectangular 1 0)) 35.333 + (negate [z] (complex-rectangular (<span style="color: #8cd0d3;">-</span> re) (<span style="color: #8cd0d3;">-</span> im))) 35.334 + (invert [z] (complex-rectangular 35.335 + (<span style="color: #8cd0d3;">/</span> re (magnitude-squared z)) 35.336 + (<span style="color: #8cd0d3;">/</span> (<span style="color: #8cd0d3;">-</span> im) (magnitude-squared z)))) 35.337 + 35.338 + Object 35.339 + (toString [_] 35.340 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #f0dfaf; font-weight: bold;">and</span> (zero? re) (zero? im)) (<span style="color: #8cd0d3;">str</span> 0) 35.341 + (<span style="color: #8cd0d3;">str</span> 35.342 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not</span>(zero? re)) 35.343 + re) 35.344 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #8cd0d3;">comp</span> not zero?) im) 35.345 + (<span style="color: #8cd0d3;">str</span> 35.346 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">neg?</span> im) <span style="color: #cc9393;">"-"</span> <span style="color: #cc9393;">"+"</span>) 35.347 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #8cd0d3;">comp</span> not one?) (java.lang.Math/abs im)) 35.348 + (java.lang.Math/abs im)) 35.349 + <span style="color: #cc9393;">"i"</span>))))))) 35.350 + 35.351 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">complex-polar</span> 35.352 + <span style="color: #8fb28f;">"Define a complex number with the given magnitude and angle."</span> 35.353 + [mag ang] 35.354 + (<span style="color: #8cd0d3;">reify</span> Complex 35.355 + (magnitude-squared [z] (<span style="color: #8cd0d3;">*</span> mag mag)) 35.356 + (angle [z] angle) 35.357 + (real-part [z] (<span style="color: #8cd0d3;">*</span> mag (java.lang.Math/cos ang))) 35.358 + (imaginary-part [z] (<span style="color: #8cd0d3;">*</span> mag (java.lang.Math/sin ang))) 35.359 + (conjugate [z] (complex-polar mag (<span style="color: #8cd0d3;">-</span> ang))) 35.360 + 35.361 + Arithmetic 35.362 + (zero [z] (complex-polar 0 0)) 35.363 + (one [z] (complex-polar 1 0)) 35.364 + (negate [z] (complex-polar (<span style="color: #8cd0d3;">-</span> mag) ang)) 35.365 + (invert [z] (complex-polar (<span style="color: #8cd0d3;">/</span> mag) (<span style="color: #8cd0d3;">-</span> ang))) 35.366 + 35.367 + Object 35.368 + (toString [_] (<span style="color: #8cd0d3;">str</span> mag <span style="color: #cc9393;">" * e^(i"</span> ang<span style="color: #cc9393;">")"</span>)) 35.369 + )) 35.370 + 35.371 + 35.372 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">Numbers are complex quantities</span> 35.373 + 35.374 +(<span style="color: #8cd0d3;">extend-protocol</span> Complex 35.375 + java.lang.Number 35.376 + (real-part [x] x) 35.377 + (imaginary-part [x] 0) 35.378 + (magnitude [x] x) 35.379 + (angle [x] 0) 35.380 + (conjugate [x] x)) 35.381 + 35.382 + 35.383 +</pre> 35.384 + 35.385 + 35.386 + 35.387 + 35.388 + 35.389 + 35.390 +</div> 35.391 + 35.392 +</div> 35.393 + 35.394 +<div id="outline-container-2-2" class="outline-3"> 35.395 +<h3 id="sec-2-2"><span class="section-number-3">2.2</span> Tuples and Tensors </h3> 35.396 +<div class="outline-text-3" id="text-2-2"> 35.397 + 35.398 + 35.399 +<p> 35.400 +A tuple is a vector which is spinable—it can be either <i>spin up</i> or <i>spin down</i>. (Covariant, contravariant; dual vectors) 35.401 +</p> 35.402 + 35.403 + 35.404 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.405 + 35.406 +(<span style="color: #f0dfaf; font-weight: bold;">defprotocol</span> <span style="color: #f0dfaf;">Spinning</span> 35.407 + (up? [this]) 35.408 + (down? [this])) 35.409 + 35.410 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">spin</span> 35.411 + <span style="color: #8fb28f;">"Returns the spin of the Spinning s, either :up or :down"</span> 35.412 + [<span style="color: #dfdfbf; font-weight: bold;">#^Spinning</span> s] 35.413 + (<span style="color: #f0dfaf; font-weight: bold;">cond</span> (up? s) <span style="color: #8cd0d3;">:up</span> (down? s) <span style="color: #8cd0d3;">:down</span>)) 35.414 + 35.415 + 35.416 +(<span style="color: #f0dfaf; font-weight: bold;">deftype</span> <span style="color: #f0dfaf;">Tuple</span> 35.417 + [spin coll] 35.418 + clojure.lang.Seqable 35.419 + (<span style="color: #8cd0d3;">seq</span> [this] (<span style="color: #8cd0d3;">seq</span> (.coll this))) 35.420 + clojure.lang.Counted 35.421 + (<span style="color: #8cd0d3;">count</span> [this] (<span style="color: #8cd0d3;">count</span> (.coll this)))) 35.422 + 35.423 +(<span style="color: #8cd0d3;">extend-type</span> Tuple 35.424 + Spinning 35.425 + (up? [this] (<span style="color: #8cd0d3;">=</span> <span style="color: #8cd0d3;">::up</span> (.spin this))) 35.426 + (down? [this] (<span style="color: #8cd0d3;">=</span> <span style="color: #8cd0d3;">::down</span> (.spin this)))) 35.427 + 35.428 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">print-method</span> Tuple 35.429 + [o w] 35.430 + (<span style="color: #8cd0d3;">print-simple</span> (<span style="color: #8cd0d3;">str</span> (<span style="color: #f0dfaf; font-weight: bold;">if</span> (up? o) 'u 'd) (.coll o)) w)) 35.431 + 35.432 + 35.433 + 35.434 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">up</span> 35.435 + <span style="color: #8fb28f;">"Create a new up-tuple containing the contents of coll."</span> 35.436 + [coll] 35.437 + (Tuple. <span style="color: #8cd0d3;">::up</span> coll)) 35.438 + 35.439 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">down</span> 35.440 + <span style="color: #8fb28f;">"Create a new down-tuple containing the contents of coll."</span> 35.441 + [coll] 35.442 + (Tuple. <span style="color: #8cd0d3;">::down</span> coll)) 35.443 + 35.444 + 35.445 +</pre> 35.446 + 35.447 + 35.448 + 35.449 + 35.450 + 35.451 +</div> 35.452 + 35.453 +<div id="outline-container-2-2-1" class="outline-4"> 35.454 +<h4 id="sec-2-2-1"><span class="section-number-4">2.2.1</span> Contraction </h4> 35.455 +<div class="outline-text-4" id="text-2-2-1"> 35.456 + 35.457 +<p>Contraction is a binary operation that you can apply to compatible 35.458 + tuples. Tuples are compatible for contraction if they have the same 35.459 + length and opposite spins, and if the corresponding items in each 35.460 + tuple are both numbers or both compatible tuples. 35.461 +</p> 35.462 + 35.463 + 35.464 + 35.465 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.466 + 35.467 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">numbers?</span> 35.468 + <span style="color: #8fb28f;">"Returns true if all arguments are numbers, else false."</span> 35.469 + [& xs] 35.470 + (<span style="color: #8cd0d3;">every?</span> number? xs)) 35.471 + 35.472 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">contractible?</span> 35.473 + <span style="color: #8fb28f;">"Returns true if the tuples a and b are compatible for contraction,</span> 35.474 +<span style="color: #8fb28f;"> else false. Tuples are compatible if they have the same number of</span> 35.475 +<span style="color: #8fb28f;"> components, they have opposite spins, and their elements are</span> 35.476 +<span style="color: #8fb28f;"> pairwise-compatible."</span> 35.477 + [a b] 35.478 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> 35.479 + (<span style="color: #8cd0d3;">isa?</span> (<span style="color: #8cd0d3;">type</span> a) Tuple) 35.480 + (<span style="color: #8cd0d3;">isa?</span> (<span style="color: #8cd0d3;">type</span> b) Tuple) 35.481 + (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">count</span> a) (<span style="color: #8cd0d3;">count</span> b)) 35.482 + (<span style="color: #8cd0d3;">not=</span> (spin a) (spin b)) 35.483 + 35.484 + (<span style="color: #8cd0d3;">not-any?</span> false? 35.485 + (<span style="color: #8cd0d3;">map</span> #(<span style="color: #f0dfaf; font-weight: bold;">or</span> 35.486 + (numbers? %1 %2) 35.487 + (contractible? %1 %2)) 35.488 + a b)))) 35.489 + 35.490 + 35.491 + 35.492 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">contract</span> 35.493 + <span style="color: #8fb28f;">"Contracts two tuples, returning the sum of the</span> 35.494 +<span style="color: #8fb28f;"> products of the corresponding items. Contraction is recursive on</span> 35.495 +<span style="color: #8fb28f;"> nested tuples."</span> 35.496 + [a b] 35.497 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not</span> (contractible? a b)) 35.498 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> 35.499 + (Exception. <span style="color: #cc9393;">"Not compatible for contraction."</span>)) 35.500 + (<span style="color: #8cd0d3;">reduce</span> + 35.501 + (<span style="color: #8cd0d3;">map</span> 35.502 + (<span style="color: #8cd0d3;">fn</span> [x y] 35.503 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (numbers? x y) 35.504 + (<span style="color: #8cd0d3;">*</span> x y) 35.505 + (contract x y))) 35.506 + a b)))) 35.507 + 35.508 +</pre> 35.509 + 35.510 + 35.511 + 35.512 + 35.513 +</div> 35.514 + 35.515 +</div> 35.516 + 35.517 +<div id="outline-container-2-2-2" class="outline-4"> 35.518 +<h4 id="sec-2-2-2"><span class="section-number-4">2.2.2</span> Matrices </h4> 35.519 +<div class="outline-text-4" id="text-2-2-2"> 35.520 + 35.521 + 35.522 + 35.523 + 35.524 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.525 +(<span style="color: #8cd0d3;">require</span> 'incanter.core) <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">use incanter's fast matrices</span> 35.526 + 35.527 +(<span style="color: #f0dfaf; font-weight: bold;">defprotocol</span> <span style="color: #f0dfaf;">Matrix</span> 35.528 + (rows [matrix]) 35.529 + (cols [matrix]) 35.530 + (diagonal [matrix]) 35.531 + (trace [matrix]) 35.532 + (determinant [matrix]) 35.533 + (transpose [matrix]) 35.534 + (conjugate [matrix]) 35.535 +) 35.536 + 35.537 +(<span style="color: #8cd0d3;">extend-protocol</span> Matrix 35.538 + incanter.Matrix 35.539 + (rows [rs] (<span style="color: #8cd0d3;">map</span> down (<span style="color: #8cd0d3;">apply</span> map vector (<span style="color: #8cd0d3;">apply</span> map vector rs)))) 35.540 + (cols [rs] (<span style="color: #8cd0d3;">map</span> up (<span style="color: #8cd0d3;">apply</span> map vector rs))) 35.541 + (diagonal [matrix] (incanter.core/diag matrix) ) 35.542 + (determinant [matrix] (incanter.core/det matrix)) 35.543 + (trace [matrix] (incanter.core/trace matrix)) 35.544 + (transpose [matrix] (incanter.core/trans matrix)) 35.545 + ) 35.546 + 35.547 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">count-rows</span> [matrix] 35.548 + ((<span style="color: #8cd0d3;">comp</span> count rows) matrix)) 35.549 + 35.550 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">count-cols</span> [matrix] 35.551 + ((<span style="color: #8cd0d3;">comp</span> count cols) matrix)) 35.552 + 35.553 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">square?</span> [matrix] 35.554 + (<span style="color: #8cd0d3;">=</span> (count-rows matrix) (count-cols matrix))) 35.555 + 35.556 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">identity-matrix</span> 35.557 + <span style="color: #8fb28f;">"Define a square matrix of size n-by-n with 1s along the diagonal and</span> 35.558 +<span style="color: #8fb28f;"> 0s everywhere else."</span> 35.559 + [n] 35.560 + (incanter.core/identity-matrix n)) 35.561 + 35.562 + 35.563 + 35.564 + 35.565 + 35.566 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">matrix-by-rows</span> 35.567 + <span style="color: #8fb28f;">"Define a matrix by giving its rows."</span> 35.568 + [& rows] 35.569 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> 35.570 + (<span style="color: #8cd0d3;">not</span> (all-equal? (<span style="color: #8cd0d3;">map</span> count rows))) 35.571 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"All rows in a matrix must have the same number of elements."</span>)) 35.572 + (incanter.core/matrix (<span style="color: #8cd0d3;">vec</span> rows)))) 35.573 + 35.574 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">matrix-by-cols</span> 35.575 + <span style="color: #8fb28f;">"Define a matrix by giving its columns"</span> 35.576 + [& cols] 35.577 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not</span> (all-equal? (<span style="color: #8cd0d3;">map</span> count cols))) 35.578 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"All columns in a matrix must have the same number of elements."</span>)) 35.579 + (incanter.core/matrix (<span style="color: #8cd0d3;">vec</span> (<span style="color: #8cd0d3;">apply</span> map vector cols))))) 35.580 + 35.581 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">identity-matrix</span> 35.582 + <span style="color: #8fb28f;">"Define a square matrix of size n-by-n with 1s along the diagonal and</span> 35.583 +<span style="color: #8fb28f;"> 0s everywhere else."</span> 35.584 + [n] 35.585 + (incanter.core/identity-matrix n)) 35.586 + 35.587 + 35.588 + 35.589 +(<span style="color: #8cd0d3;">extend-protocol</span> Arithmetic 35.590 + incanter.Matrix 35.591 + (one [matrix] 35.592 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (square? matrix) 35.593 + (identity-matrix (count-rows matrix)) 35.594 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"Non-square matrices have no multiplicative unit."</span>)))) 35.595 + (zero [matrix] 35.596 + (<span style="color: #8cd0d3;">apply</span> matrix-by-rows (<span style="color: #8cd0d3;">map</span> zero (rows matrix)))) 35.597 + (negate [matrix] 35.598 + (<span style="color: #8cd0d3;">apply</span> matrix-by-rows (<span style="color: #8cd0d3;">map</span> negate (rows matrix)))) 35.599 + (invert [matrix] 35.600 + (incanter.core/solve matrix))) 35.601 + 35.602 + 35.603 + 35.604 +(<span style="color: #f0dfaf; font-weight: bold;">defmulti</span> <span style="color: #f0dfaf;">coerce-to-matrix</span> 35.605 + <span style="color: #8fb28f;">"Converts x into a matrix, if possible."</span> 35.606 + type) 35.607 + 35.608 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">coerce-to-matrix</span> incanter.Matrix [x] x) 35.609 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">coerce-to-matrix</span> Tuple [x] 35.610 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">apply</span> numbers? (<span style="color: #8cd0d3;">seq</span> x)) 35.611 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (up? x) 35.612 + (matrix-by-cols (<span style="color: #8cd0d3;">seq</span> x)) 35.613 + (matrix-by-rows (<span style="color: #8cd0d3;">seq</span> x))) 35.614 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"Non-numerical tuple cannot be converted into a matrix."</span>)))) 35.615 + 35.616 + 35.617 + 35.618 + 35.619 + 35.620 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(defn matrix-by-cols</span> 35.621 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">"Define a matrix by giving its columns."</span> 35.622 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">[& cols]</span> 35.623 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(cond</span> 35.624 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(not (all-equal? (map count cols)))</span> 35.625 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(throw (Exception. "All columns in a matrix must have the same number of elements."))</span> 35.626 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">:else</span> 35.627 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(reify Matrix</span> 35.628 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(cols [this] (map up cols))</span> 35.629 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(rows [this] (map down (apply map vector cols)))</span> 35.630 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(diagonal [this] (map-indexed (fn [i col] (nth col i) cols)))</span> 35.631 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(trace [this]</span> 35.632 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(if (not= (count-cols this) (count-rows this))</span> 35.633 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(throw (Exception.</span> 35.634 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">"Cannot take the trace of a non-square matrix."))</span> 35.635 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(reduce + (diagonal this))))</span> 35.636 + 35.637 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(determinant [this]</span> 35.638 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(if (not= (count-cols this) (count-rows this))</span> 35.639 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(throw (Exception.</span> 35.640 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">"Cannot take the determinant of a non-square matrix."))</span> 35.641 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(reduce * (map-indexed (fn [i col] (nth col i)) cols))))</span> 35.642 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">)))</span> 35.643 + 35.644 +(<span style="color: #8cd0d3;">extend-protocol</span> Matrix Tuple 35.645 + (rows [this] (<span style="color: #f0dfaf; font-weight: bold;">if</span> (down? this) 35.646 + (<span style="color: #8cd0d3;">list</span> this) 35.647 + (<span style="color: #8cd0d3;">map</span> (<span style="color: #8cd0d3;">comp</span> up vector) this))) 35.648 + 35.649 + (cols [this] (<span style="color: #f0dfaf; font-weight: bold;">if</span> (up? this) 35.650 + (<span style="color: #8cd0d3;">list</span> this) 35.651 + (<span style="color: #8cd0d3;">map</span> (<span style="color: #8cd0d3;">comp</span> down vector) this)) 35.652 + )) 35.653 + 35.654 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">matrix-multiply</span> 35.655 + <span style="color: #8fb28f;">"Returns the matrix resulting from the matrix multiplication of the given arguments."</span> 35.656 + ([A] (coerce-to-matrix A)) 35.657 + ([A B] (incanter.core/mmult (coerce-to-matrix A) (coerce-to-matrix B))) 35.658 + ([M1 M2 & Ms] (<span style="color: #8cd0d3;">reduce</span> matrix-multiply (matrix-multiply M1 M2) Ms))) 35.659 + 35.660 +</pre> 35.661 + 35.662 + 35.663 + 35.664 + 35.665 + 35.666 +</div> 35.667 +</div> 35.668 + 35.669 +</div> 35.670 + 35.671 +<div id="outline-container-2-3" class="outline-3"> 35.672 +<h3 id="sec-2-3"><span class="section-number-3">2.3</span> Power Series </h3> 35.673 +<div class="outline-text-3" id="text-2-3"> 35.674 + 35.675 + 35.676 + 35.677 + 35.678 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.679 +(<span style="color: #8cd0d3;">use</span> 'clojure.contrib.def) 35.680 + 35.681 + 35.682 + 35.683 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">series-fn</span> 35.684 + <span style="color: #8fb28f;">"The function corresponding to the given power series."</span> 35.685 + [series] 35.686 + (<span style="color: #8cd0d3;">fn</span> [x] 35.687 + (<span style="color: #8cd0d3;">reduce</span> + 35.688 + (map-indexed (<span style="color: #8cd0d3;">fn</span>[n x] (<span style="color: #8cd0d3;">*</span> (<span style="color: #8cd0d3;">float</span> (<span style="color: #8cd0d3;">nth</span> series n)) (<span style="color: #8cd0d3;">float</span>(java.lang.Math/pow (<span style="color: #8cd0d3;">float</span> x) n)) )) 35.689 + (<span style="color: #8cd0d3;">range</span> 20))))) 35.690 + 35.691 +(<span style="color: #f0dfaf; font-weight: bold;">deftype</span> <span style="color: #f0dfaf;">PowerSeries</span> 35.692 + [coll] 35.693 + clojure.lang.Seqable 35.694 + (<span style="color: #8cd0d3;">seq</span> [this] (<span style="color: #8cd0d3;">seq</span> (.coll this))) 35.695 + 35.696 + clojure.lang.Indexed 35.697 + (<span style="color: #8cd0d3;">nth</span> [this n] (<span style="color: #8cd0d3;">nth</span> (.coll this) n 0)) 35.698 + (<span style="color: #8cd0d3;">nth</span> [this n not-found] (<span style="color: #8cd0d3;">nth</span> (.coll this) n not-found)) 35.699 + 35.700 + <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">clojure.lang.IFn</span> 35.701 + <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(call [this] (throw(Exception.)))</span> 35.702 + <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(invoke [this & args] args</span> 35.703 + <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(let [f </span> 35.704 + <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">)</span> 35.705 + <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(run [this] (throw(Exception.)))</span> 35.706 + ) 35.707 + 35.708 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">power-series</span> 35.709 + <span style="color: #8fb28f;">"Returns a power series with the items of the coll as its</span> 35.710 +<span style="color: #8fb28f;"> coefficients. Trailing zeros are added to the end of coll."</span> 35.711 + [coeffs] 35.712 + (PowerSeries. coeffs)) 35.713 + 35.714 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">power-series-indexed</span> 35.715 + <span style="color: #8fb28f;">"Returns a power series consisting of the result of mapping f to the non-negative integers."</span> 35.716 + [f] 35.717 + (PowerSeries. (<span style="color: #8cd0d3;">map</span> f (<span style="color: #8cd0d3;">range</span>)))) 35.718 + 35.719 + 35.720 +(<span style="color: #f0dfaf; font-weight: bold;">defn-memo</span> <span style="color: #f0dfaf;">nth-partial-sum</span> 35.721 + ([series n] 35.722 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (zero? n) (<span style="color: #8cd0d3;">first</span> series) 35.723 + (<span style="color: #8cd0d3;">+</span> (<span style="color: #8cd0d3;">nth</span> series n) 35.724 + (nth-partial-sum series (<span style="color: #8cd0d3;">dec</span> n)))))) 35.725 + 35.726 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">partial-sums</span> [series] 35.727 + (<span style="color: #8cd0d3;">lazy-seq</span> (<span style="color: #8cd0d3;">map</span> nth-partial-sum (<span style="color: #8cd0d3;">range</span>)))) 35.728 + 35.729 + 35.730 + 35.731 + 35.732 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">cos-series</span> 35.733 + (power-series-indexed 35.734 + (<span style="color: #8cd0d3;">fn</span>[n] 35.735 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">odd?</span> n) 0 35.736 + (<span style="color: #8cd0d3;">/</span> 35.737 + (<span style="color: #8cd0d3;">reduce</span> * 35.738 + (<span style="color: #8cd0d3;">reduce</span> * (<span style="color: #8cd0d3;">repeat</span> (<span style="color: #8cd0d3;">/</span> n 2) -1)) 35.739 + (<span style="color: #8cd0d3;">range</span> 1 (<span style="color: #8cd0d3;">inc</span> n))) 35.740 + ))))) 35.741 + 35.742 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">sin-series</span> 35.743 + (power-series-indexed 35.744 + (<span style="color: #8cd0d3;">fn</span>[n] 35.745 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">even?</span> n) 0 35.746 + (<span style="color: #8cd0d3;">/</span> 35.747 + (<span style="color: #8cd0d3;">reduce</span> * 35.748 + (<span style="color: #8cd0d3;">reduce</span> * (<span style="color: #8cd0d3;">repeat</span> (<span style="color: #8cd0d3;">/</span> (<span style="color: #8cd0d3;">dec</span> n) 2) -1)) 35.749 + (<span style="color: #8cd0d3;">range</span> 1 (<span style="color: #8cd0d3;">inc</span> n))) 35.750 + ))))) 35.751 + 35.752 +</pre> 35.753 + 35.754 + 35.755 + 35.756 + 35.757 + 35.758 +</div> 35.759 +</div> 35.760 + 35.761 +</div> 35.762 + 35.763 +<div id="outline-container-3" class="outline-2"> 35.764 +<h2 id="sec-3"><span class="section-number-2">3</span> Basic Utilities </h2> 35.765 +<div class="outline-text-2" id="text-3"> 35.766 + 35.767 + 35.768 + 35.769 +</div> 35.770 + 35.771 +<div id="outline-container-3-1" class="outline-3"> 35.772 +<h3 id="sec-3-1"><span class="section-number-3">3.1</span> Sequence manipulation </h3> 35.773 +<div class="outline-text-3" id="text-3-1"> 35.774 + 35.775 + 35.776 + 35.777 + 35.778 + 35.779 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">ns</span> sicm.utils) 35.780 + 35.781 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">do-up</span> 35.782 + <span style="color: #8fb28f;">"Apply f to each number from low to high, presumably for</span> 35.783 +<span style="color: #8fb28f;"> side-effects."</span> 35.784 + [f low high] 35.785 + (<span style="color: #f0dfaf; font-weight: bold;">doseq</span> [i (<span style="color: #8cd0d3;">range</span> low high)] (f i))) 35.786 + 35.787 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">do-down</span> 35.788 + <span style="color: #8fb28f;">"Apply f to each number from high to low, presumably for</span> 35.789 +<span style="color: #8fb28f;"> side-effects."</span> 35.790 + [f high low] 35.791 + (<span style="color: #f0dfaf; font-weight: bold;">doseq</span> [i (<span style="color: #8cd0d3;">range</span> high low -1)] (f i))) 35.792 + 35.793 + 35.794 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">all-equal?</span> [coll] 35.795 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">empty?</span> (<span style="color: #8cd0d3;">rest</span> coll)) true 35.796 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">first</span> coll) (<span style="color: #8cd0d3;">second</span> coll)) 35.797 + (<span style="color: #f0dfaf; font-weight: bold;">recur</span> (<span style="color: #8cd0d3;">rest</span> coll)))))) 35.798 + 35.799 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">multiplier</span> 35.800 + <span style="color: #8fb28f;">"Returns a function that 'multiplies' the members of a collection,</span> 35.801 +<span style="color: #8fb28f;">returning unit if called on an empty collection."</span> 35.802 + [multiply unit] 35.803 + (<span style="color: #8cd0d3;">fn</span> [coll] ((<span style="color: #8cd0d3;">partial</span> reduce multiply unit) coll))) 35.804 + 35.805 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">divider</span> 35.806 + <span style="color: #8fb28f;">"Returns a function that 'divides' the first element of a collection</span> 35.807 +<span style="color: #8fb28f;">by the 'product' of the rest of the collection."</span> 35.808 + [divide multiply invert unit] 35.809 + (<span style="color: #8cd0d3;">fn</span> [coll] 35.810 + (<span style="color: #8cd0d3;">apply</span> 35.811 + (<span style="color: #8cd0d3;">fn</span> 35.812 + ([] unit) 35.813 + ([x] (invert x)) 35.814 + ([x y] (divide x y)) 35.815 + ([x y & zs] (divide x (<span style="color: #8cd0d3;">reduce</span> multiply y zs)))) 35.816 + coll))) 35.817 + 35.818 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">left-circular-shift</span> 35.819 + <span style="color: #8fb28f;">"Remove the first element of coll, adding it to the end of coll."</span> 35.820 + [coll] 35.821 + (<span style="color: #8cd0d3;">concat</span> (<span style="color: #8cd0d3;">rest</span> coll) (<span style="color: #8cd0d3;">take</span> 1 coll))) 35.822 + 35.823 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">right-circular-shift</span> 35.824 + <span style="color: #8fb28f;">"Remove the last element of coll, adding it to the front of coll."</span> 35.825 + [coll] 35.826 + (<span style="color: #8cd0d3;">cons</span> (<span style="color: #8cd0d3;">last</span> coll) (<span style="color: #8cd0d3;">butlast</span> coll))) 35.827 +</pre> 35.828 + 35.829 + 35.830 + 35.831 + 35.832 + 35.833 + 35.834 + 35.835 +</div> 35.836 + 35.837 +</div> 35.838 + 35.839 +<div id="outline-container-3-2" class="outline-3"> 35.840 +<h3 id="sec-3-2"><span class="section-number-3">3.2</span> Ranges, Airity and Function Composition </h3> 35.841 +<div class="outline-text-3" id="text-3-2"> 35.842 + 35.843 + 35.844 + 35.845 + 35.846 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.847 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">infinity</span> Double/POSITIVE_INFINITY) 35.848 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">infinite?</span> [x] (Double/isInfinite x)) 35.849 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">finite?</span> (<span style="color: #8cd0d3;">comp</span> not infinite?)) 35.850 + 35.851 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">arity-min</span> 35.852 + <span style="color: #8fb28f;">"Returns the smallest number of arguments f can take."</span> 35.853 + [f] 35.854 + (<span style="color: #8cd0d3;">apply</span> 35.855 + min 35.856 + (<span style="color: #8cd0d3;">map</span> (<span style="color: #8cd0d3;">comp</span> alength #(.getParameterTypes %)) 35.857 + (<span style="color: #8cd0d3;">filter</span> (<span style="color: #8cd0d3;">comp</span> (<span style="color: #8cd0d3;">partial</span> = <span style="color: #cc9393;">"invoke"</span>) #(.getName %)) 35.858 + (.getDeclaredMethods (<span style="color: #8cd0d3;">class</span> f)))))) 35.859 + 35.860 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">arity-max</span> 35.861 + <span style="color: #8fb28f;">"Returns the largest number of arguments f can take, possibly</span> 35.862 +<span style="color: #8fb28f;"> Infinity."</span> 35.863 + [f] 35.864 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [methods (.getDeclaredMethods (<span style="color: #8cd0d3;">class</span> f))] 35.865 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not-any?</span> (<span style="color: #8cd0d3;">partial</span> = <span style="color: #cc9393;">"doInvoke"</span>) (<span style="color: #8cd0d3;">map</span> #(.getName %) methods)) 35.866 + (<span style="color: #8cd0d3;">apply</span> max 35.867 + (<span style="color: #8cd0d3;">map</span> (<span style="color: #8cd0d3;">comp</span> alength #(.getParameterTypes %)) 35.868 + (<span style="color: #8cd0d3;">filter</span> (<span style="color: #8cd0d3;">comp</span> (<span style="color: #8cd0d3;">partial</span> = <span style="color: #cc9393;">"invoke"</span>) #(.getName %)) methods))) 35.869 + infinity))) 35.870 + 35.871 + 35.872 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">^</span>{<span style="color: #8cd0d3;">:arglists</span> '([f]) 35.873 + <span style="color: #8cd0d3;">:doc</span> <span style="color: #cc9393;">"Returns a two-element list containing the minimum and</span> 35.874 +<span style="color: #cc9393;"> maximum number of args that f can take."</span>} 35.875 + arity-interval 35.876 + (<span style="color: #8cd0d3;">juxt</span> arity-min arity-max)) 35.877 + 35.878 + 35.879 + 35.880 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">--- intervals</span> 35.881 + 35.882 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">intersect</span> 35.883 + <span style="color: #8fb28f;">"Returns the interval of overlap between interval-1 and interval-2"</span> 35.884 + [interval-1 interval-2] 35.885 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #f0dfaf; font-weight: bold;">or</span> (<span style="color: #8cd0d3;">empty?</span> interval-1) (<span style="color: #8cd0d3;">empty?</span> interval-2)) [] 35.886 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [left (<span style="color: #8cd0d3;">max</span> (<span style="color: #8cd0d3;">first</span> interval-1) (<span style="color: #8cd0d3;">first</span> interval-2)) 35.887 + right (<span style="color: #8cd0d3;">min</span> (<span style="color: #8cd0d3;">second</span> interval-1) (<span style="color: #8cd0d3;">second</span> interval-2))] 35.888 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">></span> left right) [] 35.889 + [left right])))) 35.890 + 35.891 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">same-endpoints?</span> 35.892 + <span style="color: #8fb28f;">"Returns true if the left endpoint is the same as the right</span> 35.893 +<span style="color: #8fb28f;"> endpoint."</span> 35.894 + [interval] 35.895 + (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">first</span> interval) (<span style="color: #8cd0d3;">second</span> interval))) 35.896 + 35.897 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">naturals?</span> 35.898 + <span style="color: #8fb28f;">"Returns true if the left endpoint is 0 and the right endpoint is</span> 35.899 +<span style="color: #8fb28f;">infinite."</span> 35.900 + [interval] 35.901 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> (zero? (<span style="color: #8cd0d3;">first</span> interval)) 35.902 + (infinite? (<span style="color: #8cd0d3;">second</span> interval)))) 35.903 + 35.904 + 35.905 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">fan-in</span> 35.906 + <span style="color: #8fb28f;">"Returns a function that pipes its input to each of the gs, then</span> 35.907 +<span style="color: #8fb28f;"> applies f to the list of results. Consequently, f must be able to</span> 35.908 +<span style="color: #8fb28f;"> take a number of arguments equal to the number of gs."</span> 35.909 + [f & gs] 35.910 + (<span style="color: #8cd0d3;">fn</span> [& args] 35.911 + (<span style="color: #8cd0d3;">apply</span> f (<span style="color: #8cd0d3;">apply</span> (<span style="color: #8cd0d3;">apply</span> juxt gs) args)))) 35.912 + 35.913 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">fan-in</span> 35.914 + <span style="color: #8fb28f;">"Returns a function that pipes its input to each of the gs, then applies f to the list of results. The resulting function takes any number of arguments, but will fail if given arguments that are incompatible with any of the gs."</span> 35.915 + [f & gs] 35.916 + (<span style="color: #8cd0d3;">comp</span> (<span style="color: #8cd0d3;">partial</span> apply f) (<span style="color: #8cd0d3;">apply</span> juxt gs))) 35.917 + 35.918 + 35.919 + 35.920 +(<span style="color: #f0dfaf; font-weight: bold;">defmacro</span> <span style="color: #f0dfaf;">airty-blah-sad</span> [f n more?] 35.921 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [syms (<span style="color: #8cd0d3;">vec</span> (<span style="color: #8cd0d3;">map</span> (<span style="color: #8cd0d3;">comp</span> gensym (<span style="color: #8cd0d3;">partial</span> str <span style="color: #cc9393;">"x"</span>)) (<span style="color: #8cd0d3;">range</span> n))) 35.922 + optional (<span style="color: #8cd0d3;">gensym</span> <span style="color: #cc9393;">"xs"</span>)] 35.923 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> more? 35.924 + `(<span style="color: #8cd0d3;">fn</span> <span style="color: #f0dfaf;">~</span>(<span style="color: #8cd0d3;">conj</span> syms '& optional) 35.925 + (<span style="color: #8cd0d3;">apply</span> ~f ~@syms ~optional)) 35.926 + `(<span style="color: #8cd0d3;">fn</span> <span style="color: #f0dfaf;">~syms</span> (~f ~@syms))))) 35.927 + 35.928 +(<span style="color: #f0dfaf; font-weight: bold;">defmacro</span> <span style="color: #f0dfaf;">airt-whaa*</span> [f n more?] 35.929 + `(airty-blah-sad ~f ~n ~more?)) 35.930 + 35.931 + 35.932 + 35.933 + 35.934 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">fan-in*</span> 35.935 + <span style="color: #8fb28f;">"Returns a function that pipes its input to each of the gs, then</span> 35.936 +<span style="color: #8fb28f;"> applies f to the list of results. Unlike fan-in, fan-in* strictly</span> 35.937 +<span style="color: #8fb28f;"> enforces arity: it will fail if the gs do not have compatible</span> 35.938 +<span style="color: #8fb28f;"> arities."</span> 35.939 + [f & gs] 35.940 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [arity-in (<span style="color: #8cd0d3;">reduce</span> intersect (<span style="color: #8cd0d3;">map</span> arity-interval gs)) 35.941 + left (<span style="color: #8cd0d3;">first</span> arity-in) 35.942 + right (<span style="color: #8cd0d3;">second</span> arity-in) 35.943 + composite (fan-in f gs) 35.944 + ] 35.945 + (<span style="color: #f0dfaf; font-weight: bold;">cond</span> 35.946 + (<span style="color: #8cd0d3;">empty?</span> arity-in) 35.947 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"Cannot compose functions with incompatible arities."</span>)) 35.948 + 35.949 + (<span style="color: #8cd0d3;">not</span> 35.950 + (<span style="color: #f0dfaf; font-weight: bold;">or</span> (<span style="color: #8cd0d3;">=</span> left right) 35.951 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> (finite? left) 35.952 + (<span style="color: #8cd0d3;">=</span> right infinity)))) 35.953 + 35.954 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. 35.955 + <span style="color: #cc9393;">"Compose can only handle arities of the form [n n] or [n infinity]"</span>)) 35.956 + <span style="color: #8cd0d3;">:else</span> 35.957 + (airty-blah-sad composite left (<span style="color: #8cd0d3;">=</span> right infinity))))) 35.958 + 35.959 + 35.960 + 35.961 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">compose-n</span> <span style="color: #8fb28f;">"Compose any number of functions together."</span> 35.962 + ([] identity) 35.963 + ([f] f) 35.964 + ([f & fs] 35.965 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [fns (<span style="color: #8cd0d3;">cons</span> f fs)] 35.966 + (compose-bin (<span style="color: #8cd0d3;">reduce</span> fan-in (<span style="color: #8cd0d3;">butlast</span> fs)) (<span style="color: #8cd0d3;">last</span> fs)))) 35.967 +) 35.968 + 35.969 + 35.970 + 35.971 + 35.972 + 35.973 + 35.974 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">iterated</span> 35.975 + ([f n id] (<span style="color: #8cd0d3;">reduce</span> comp id (<span style="color: #8cd0d3;">repeat</span> n f))) 35.976 + ([f n] (<span style="color: #8cd0d3;">reduce</span> comp identity (<span style="color: #8cd0d3;">repeat</span> n f)))) 35.977 + 35.978 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">iterate-until-stable</span> 35.979 + <span style="color: #8fb28f;">"Repeatedly applies f to x, returning the first result that is close</span> 35.980 +<span style="color: #8fb28f;">enough to its predecessor."</span> 35.981 + [f close-enough? x] 35.982 + (<span style="color: #8cd0d3;">second</span> (swank.util/find-first 35.983 + (<span style="color: #8cd0d3;">partial</span> apply close-enough?) 35.984 + (<span style="color: #8cd0d3;">partition</span> 2 1 (<span style="color: #8cd0d3;">iterate</span> f x))))) 35.985 + 35.986 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">lexical<</span> [x y] 35.987 + (<span style="color: #8cd0d3;">neg?</span> (<span style="color: #8cd0d3;">compare</span> (<span style="color: #8cd0d3;">str</span> x) (<span style="color: #8cd0d3;">str</span> y)))) 35.988 + 35.989 + 35.990 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">do-up</span> 35.991 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">do-down</span> 35.992 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">make-pairwise-test</span> comparator) 35.993 +<span style="color: #708070;">;;</span><span style="color: #7f9f7f;">all-equal?</span> 35.994 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">accumulation</span> multiplier) 35.995 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">inverse-accumulation</span> divider) 35.996 +<span style="color: #708070;">;;</span><span style="color: #7f9f7f;">left-circular-shift</span> 35.997 +<span style="color: #708070;">;;</span><span style="color: #7f9f7f;">right-circular-shift</span> 35.998 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">exactly-n?</span> same-endpoints?) 35.999 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">any-number?</span> naturals?) 35.1000 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">TODO compose</span> 35.1001 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">TODO compose-n</span> 35.1002 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">identity</span> 35.1003 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">compose-2</span> fan-in) 35.1004 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">compose-bin</span> fan-in*) 35.1005 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">any?</span> (<span style="color: #8cd0d3;">constantly</span> true)) 35.1006 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">none?</span> (<span style="color: #8cd0d3;">constantly</span> false)) 35.1007 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">constant</span> constantly) 35.1008 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">joint-arity</span> intersect) 35.1009 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">a-reduce</span> reduce) 35.1010 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">filter</span> 35.1011 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">make-map</span> (<span style="color: #8cd0d3;">partial</span> partial map) ) 35.1012 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">bracket</span> juxt) 35.1013 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">TODO apply-to-all</span> 35.1014 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">TODO nary-combine</span> 35.1015 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">TODO binary-combine</span> 35.1016 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">TODO unary-combine</span> 35.1017 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">iterated</span> 35.1018 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">iterate-until-stable</span> 35.1019 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">make-function-of-vector</span> (<span style="color: #8cd0d3;">partial</span> partial map)) 35.1020 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">make-function-of-arguments</span> (<span style="color: #8cd0d3;">fn</span> [f] (<span style="color: #8cd0d3;">fn</span> [& args] (f args)))) 35.1021 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">alphaless</span> lexical<) 35.1022 + 35.1023 +</pre> 35.1024 + 35.1025 + 35.1026 + 35.1027 + 35.1028 + 35.1029 + 35.1030 + 35.1031 + 35.1032 + 35.1033 + 35.1034 + 35.1035 + 35.1036 +</div> 35.1037 +</div> 35.1038 + 35.1039 +</div> 35.1040 + 35.1041 +<div id="outline-container-4" class="outline-2"> 35.1042 +<h2 id="sec-4"><span class="section-number-2">4</span> Numerical Methods </h2> 35.1043 +<div class="outline-text-2" id="text-4"> 35.1044 + 35.1045 + 35.1046 + 35.1047 + 35.1048 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.1049 +(<span style="color: #f0dfaf; font-weight: bold;">import</span> java.lang.Math) 35.1050 +(<span style="color: #8cd0d3;">use</span> 'clojure.contrib.def) 35.1051 + 35.1052 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">---- USEFUL CONSTANTS</span> 35.1053 + 35.1054 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">machine-epsilon</span> 35.1055 + <span style="color: #8fb28f;">"Smallest value representable on your machine, as determined by</span> 35.1056 +<span style="color: #8fb28f;">successively dividing a number in half until consecutive results are</span> 35.1057 +<span style="color: #8fb28f;">indistinguishable."</span> 35.1058 + [] 35.1059 + (<span style="color: #8cd0d3;">ffirst</span> 35.1060 + (<span style="color: #8cd0d3;">drop-while</span> 35.1061 + (<span style="color: #8cd0d3;">comp</span> not zero? second) 35.1062 + (<span style="color: #8cd0d3;">partition</span> 2 1 35.1063 + (<span style="color: #8cd0d3;">iterate</span> (<span style="color: #8cd0d3;">partial</span> * 0.5) 1))))) 35.1064 + 35.1065 + 35.1066 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">pi</span> (Math/PI)) 35.1067 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">two-pi</span> (<span style="color: #8cd0d3;">*</span> 2 pi)) 35.1068 + 35.1069 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">eulers-gamma</span> 0.5772156649015328606065) 35.1070 + 35.1071 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">phi</span> (<span style="color: #8cd0d3;">/</span> (<span style="color: #8cd0d3;">inc</span> (Math/sqrt 5)) 2)) 35.1072 + 35.1073 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">ln2</span> (Math/log 2)) 35.1074 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">ln10</span> (Math/log 10)) 35.1075 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">exp10</span> #(Math/pow 10 %)) 35.1076 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">exp2</span> #(Math/pow 2 %)) 35.1077 + 35.1078 + 35.1079 +<span style="color: #708070;">;;</span> 35.1080 + 35.1081 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">---- ANGLES AND TRIGONOMETRY</span> 35.1082 + 35.1083 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">angle-restrictor</span> 35.1084 + <span style="color: #8fb28f;">"Returns a function that ensures that angles lie in the specified interval of length two-pi."</span> 35.1085 + [max-angle] 35.1086 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [min-angle (<span style="color: #8cd0d3;">-</span> max-angle two-pi)] 35.1087 + (<span style="color: #8cd0d3;">fn</span> [x] 35.1088 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #f0dfaf; font-weight: bold;">and</span> 35.1089 + (<span style="color: #8cd0d3;"><=</span> min-angle x) 35.1090 + (<span style="color: #8cd0d3;"><</span> x max-angle)) 35.1091 + x 35.1092 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [corrected-x (<span style="color: #8cd0d3;">-</span> x (<span style="color: #8cd0d3;">*</span> two-pi (Math/floor (<span style="color: #8cd0d3;">/</span> x two-pi))))] 35.1093 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;"><</span> corrected-x max-angle) 35.1094 + corrected-x 35.1095 + (<span style="color: #8cd0d3;">-</span> corrected-x two-pi))))))) 35.1096 + 35.1097 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">angle-restrict-pi</span> 35.1098 + <span style="color: #8fb28f;">"Coerces angles to lie in the interval from -pi to pi."</span> 35.1099 + [angle] 35.1100 + ((angle-restrictor pi) angle)) 35.1101 + 35.1102 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">angle-restrict-two-pi</span> 35.1103 + <span style="color: #8fb28f;">"Coerces angles to lie in the interval from zero to two-pi"</span> 35.1104 + [angle] 35.1105 + ((angle-restrictor two-pi) angle)) 35.1106 + 35.1107 + 35.1108 + 35.1109 + 35.1110 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">invert</span> [x] (<span style="color: #8cd0d3;">/</span> x)) 35.1111 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">negate</span> [x] (<span style="color: #8cd0d3;">-</span> x)) 35.1112 + 35.1113 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">exp</span> [x] (Math/exp x)) 35.1114 + 35.1115 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">sin</span> [x] (Math/sin x)) 35.1116 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">cos</span> [x] (Math/cos x)) 35.1117 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">tan</span> [x] (Math/tan x)) 35.1118 + 35.1119 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">sec</span> (<span style="color: #8cd0d3;">comp</span> invert cos)) 35.1120 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">csc</span> (<span style="color: #8cd0d3;">comp</span> invert sin)) 35.1121 + 35.1122 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">sinh</span> [x] (Math/sinh x)) 35.1123 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">cosh</span> [x] (Math/cosh x)) 35.1124 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">tanh</span> [x] (Math/tanh x)) 35.1125 + 35.1126 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">sech</span> (<span style="color: #8cd0d3;">comp</span> invert cosh)) 35.1127 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">csch</span> (<span style="color: #8cd0d3;">comp</span> invert sinh)) 35.1128 + 35.1129 + 35.1130 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">------------</span> 35.1131 + 35.1132 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">factorial</span> 35.1133 + <span style="color: #8fb28f;">"Computes the factorial of the nonnegative integer n."</span> 35.1134 + [n] 35.1135 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">neg?</span> n) 35.1136 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"Cannot compute the factorial of a negative number."</span>)) 35.1137 + (<span style="color: #8cd0d3;">reduce</span> * 1 (<span style="color: #8cd0d3;">range</span> 1 (<span style="color: #8cd0d3;">inc</span> n))))) 35.1138 + 35.1139 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">exact-quotient</span> [n d] (<span style="color: #8cd0d3;">/</span> n d)) 35.1140 + 35.1141 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">binomial-coefficient</span> 35.1142 + <span style="color: #8fb28f;">"Computes the number of different ways to choose m elements from n."</span> 35.1143 + [n m] 35.1144 + (<span style="color: #8cd0d3;">assert</span> (<span style="color: #8cd0d3;"><=</span> 0 m n)) 35.1145 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [difference (<span style="color: #8cd0d3;">-</span> n m)] 35.1146 + (exact-quotient 35.1147 + (<span style="color: #8cd0d3;">reduce</span> * (<span style="color: #8cd0d3;">range</span> n (<span style="color: #8cd0d3;">max</span> difference m) -1 )) 35.1148 + (factorial (<span style="color: #8cd0d3;">min</span> difference m))))) 35.1149 + 35.1150 +(<span style="color: #f0dfaf; font-weight: bold;">defn-memo</span> <span style="color: #f0dfaf;">stirling-1</span> 35.1151 + <span style="color: #cc9393;">"Stirling numbers of the first kind: the number of permutations of n</span> 35.1152 +<span style="color: #cc9393;"> elements with exactly m permutation cycles. "</span> 35.1153 + [n k] 35.1154 + <span style="color: #708070;">;</span><span style="color: #7f9f7f;">(assert (<= 1 k n))</span> 35.1155 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (zero? n) 35.1156 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (zero? k) 1 0) 35.1157 + (<span style="color: #8cd0d3;">+</span> (stirling-1 (<span style="color: #8cd0d3;">dec</span> n) (<span style="color: #8cd0d3;">dec</span> k)) 35.1158 + (<span style="color: #8cd0d3;">*</span> (<span style="color: #8cd0d3;">dec</span> n) (stirling-1 (<span style="color: #8cd0d3;">dec</span> n) k))))) 35.1159 + 35.1160 +(<span style="color: #f0dfaf; font-weight: bold;">defn-memo</span> <span style="color: #f0dfaf;">stirling-2</span> <span style="color: #708070;">;;</span><span style="color: #7f9f7f;">count-partitions</span> 35.1161 + <span style="color: #cc9393;">"Stirling numbers of the second kind: the number of ways to partition a set of n elements into k subsets."</span> 35.1162 + [n k] 35.1163 + (<span style="color: #f0dfaf; font-weight: bold;">cond</span> 35.1164 + (<span style="color: #8cd0d3;">=</span> k 1) 1 35.1165 + (<span style="color: #8cd0d3;">=</span> k n) 1 35.1166 + <span style="color: #8cd0d3;">:else</span> (<span style="color: #8cd0d3;">+</span> (stirling-2 (<span style="color: #8cd0d3;">dec</span> n) (<span style="color: #8cd0d3;">dec</span> k)) 35.1167 + (<span style="color: #8cd0d3;">*</span> k (stirling-2 (<span style="color: #8cd0d3;">dec</span> n) k))))) 35.1168 + 35.1169 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">harmonic-number</span> [n] 35.1170 + (<span style="color: #8cd0d3;">/</span> (stirling-1 (<span style="color: #8cd0d3;">inc</span> n) 2) 35.1171 + (factorial n))) 35.1172 + 35.1173 + 35.1174 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">sum</span> 35.1175 + [f low high] 35.1176 + (<span style="color: #8cd0d3;">reduce</span> + (<span style="color: #8cd0d3;">map</span> f (<span style="color: #8cd0d3;">range</span> low (<span style="color: #8cd0d3;">inc</span> high))))) 35.1177 + 35.1178 +</pre> 35.1179 + 35.1180 + 35.1181 + 35.1182 + 35.1183 + 35.1184 + 35.1185 + 35.1186 + 35.1187 + 35.1188 + 35.1189 + 35.1190 + 35.1191 + 35.1192 + 35.1193 + 35.1194 +</div> 35.1195 + 35.1196 +</div> 35.1197 + 35.1198 +<div id="outline-container-5" class="outline-2"> 35.1199 +<h2 id="sec-5"><span class="section-number-2">5</span> Differentiation </h2> 35.1200 +<div class="outline-text-2" id="text-5"> 35.1201 + 35.1202 + 35.1203 +<p> 35.1204 +We compute derivatives by passing special <b>differential objects</b> \([x, 35.1205 +dx]\) through functions. Roughly speaking, applying a function \(f\) to a 35.1206 +differential object \([x, dx]\) should produce a new differential 35.1207 +object \([f(x),\,Df(x)\cdot dx]\). 35.1208 +</p> 35.1209 + 35.1210 + 35.1211 +\([x,\,dx]\xrightarrow{\quad f \quad}[f(x),\,Df(x)\cdot dx]\) 35.1212 +<p> 35.1213 +Notice that you can obtain the derivative of \(f\) from this 35.1214 +differential object, as it is the coefficient of the \(dx\) term. Also, 35.1215 +as you apply successive functions using this rule, you get the 35.1216 +chain-rule answer you expect: 35.1217 +</p> 35.1218 + 35.1219 + 35.1220 +\([f(x),\,Df(x)\cdot dx]\xrightarrow{\quad g\quad} [gf(x),\, 35.1221 +Dgf(x)\cdot Df(x) \cdot dx ]\) 35.1222 + 35.1223 +<p> 35.1224 +In order to generalize to multiple variables and multiple derivatives, 35.1225 +we use a <b>power series of differentials</b>, a sortred infinite sequence which 35.1226 +contains all terms like \(dx\cdot dy\), \(dx^2\cdot dy\), etc. 35.1227 +</p> 35.1228 + 35.1229 + 35.1230 + 35.1231 + 35.1232 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.1233 + 35.1234 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">differential-seq</span> 35.1235 + <span style="color: #8fb28f;">"Constructs a sequence of differential terms from a numerical</span> 35.1236 +<span style="color: #8fb28f;">coefficient and a list of keys for variables. If no coefficient is supplied, uses 1."</span> 35.1237 + ([variables] (differential-seq* 1 variables)) 35.1238 + ([coefficient variables & cvs] 35.1239 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">number?</span> coefficient) 35.1240 + (<span style="color: #8cd0d3;">conj</span> (<span style="color: #8cd0d3;">assoc</span> {} (<span style="color: #8cd0d3;">apply</span> sorted-set variables) coefficient) 35.1241 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">empty?</span> cvs) 35.1242 + nil 35.1243 + (<span style="color: #8cd0d3;">apply</span> differential-seq* cvs))) 35.1244 + (<span style="color: #8cd0d3;">apply</span> differential-seq* 1 coefficient 1 variables cvs) 35.1245 + ))) 35.1246 + 35.1247 + 35.1248 + 35.1249 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">differential-add</span> 35.1250 + <span style="color: #8fb28f;">"Add two differential sequences by combining like terms."</span> 35.1251 + [dseq1 dseq2] 35.1252 + (<span style="color: #8cd0d3;">merge-with</span> + dseq1 dseq2)) 35.1253 + 35.1254 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">differential-multiply</span> 35.1255 + <span style="color: #8fb28f;">"Multiply two differential sequences. The square of any differential variable is zero since differential variables are infinitesimally small."</span> 35.1256 + [dseq1 dseq2] 35.1257 + (<span style="color: #8cd0d3;">reduce</span> 35.1258 + (<span style="color: #8cd0d3;">fn</span> [m [[vars1 coeff1] [vars2 coeff2]]] 35.1259 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">empty?</span> (clojure.set/<span style="color: #dfdfbf; font-weight: bold;">intersection</span> vars1 vars2)) 35.1260 + (<span style="color: #8cd0d3;">assoc</span> m (clojure.set/<span style="color: #dfdfbf; font-weight: bold;">union</span> vars1 vars2) (<span style="color: #8cd0d3;">*</span> coeff1 coeff2)) 35.1261 + m)) 35.1262 + {} 35.1263 + (clojure.contrib.combinatorics/cartesian-product 35.1264 + dseq1 35.1265 + dseq2))) 35.1266 + 35.1267 + 35.1268 + 35.1269 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">big-part</span> 35.1270 + <span style="color: #8fb28f;">"Returns the 'finite' part of the differential sequence."</span> 35.1271 + [dseq] 35.1272 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> 35.1273 + [keys (<span style="color: #8cd0d3;">sort-by</span> count (<span style="color: #8cd0d3;">keys</span> dseq)) 35.1274 + pivot-key (<span style="color: #8cd0d3;">first</span> (<span style="color: #8cd0d3;">last</span> keys))] 35.1275 + 35.1276 + (<span style="color: #8cd0d3;">apply</span> hash-map 35.1277 + (<span style="color: #8cd0d3;">reduce</span> concat 35.1278 + (<span style="color: #8cd0d3;">filter</span> (<span style="color: #8cd0d3;">comp</span> pivot-key first) dseq) 35.1279 + )))) 35.1280 + 35.1281 + 35.1282 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">small-part</span> 35.1283 + <span style="color: #8fb28f;">"Returns the 'infinitesimal' part of the differential sequence."</span> 35.1284 + [dseq] 35.1285 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> 35.1286 + [keys (<span style="color: #8cd0d3;">sort-by</span> count (<span style="color: #8cd0d3;">keys</span> dseq)) 35.1287 + pivot-key (<span style="color: #8cd0d3;">first</span> (<span style="color: #8cd0d3;">last</span> keys))] 35.1288 + 35.1289 + (<span style="color: #8cd0d3;">apply</span> hash-map 35.1290 + (<span style="color: #8cd0d3;">reduce</span> concat 35.1291 + (<span style="color: #8cd0d3;">remove</span> (<span style="color: #8cd0d3;">comp</span> pivot-key first) dseq) 35.1292 + )))) 35.1293 + 35.1294 + 35.1295 + 35.1296 + 35.1297 + 35.1298 + 35.1299 + 35.1300 + 35.1301 + 35.1302 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">;; A differential term consists of a numerical coefficient and a</span> 35.1303 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">;; sorted </span> 35.1304 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(defrecord DifferentialTerm [coefficient variables])</span> 35.1305 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(defmethod print-method DifferentialTerm</span> 35.1306 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">[o w]</span> 35.1307 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(print-simple</span> 35.1308 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(apply str (.coefficient o)(map (comp (partial str "d") name) (.variables o)))</span> 35.1309 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">w))</span> 35.1310 + 35.1311 + 35.1312 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(defn differential-seq</span> 35.1313 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">"Constructs a sequence of differential terms from a numerical</span> 35.1314 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">coefficient and a list of keywords for variables. If no coefficient is</span> 35.1315 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">supplied, uses 1."</span> 35.1316 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">([variables] (differential-seq 1 variables))</span> 35.1317 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">([coefficient variables]</span> 35.1318 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(list</span> 35.1319 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(DifferentialTerm. coefficient (apply sorted-set variables))))</span> 35.1320 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">([coefficient variables & cvs]</span> 35.1321 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(sort-by</span> 35.1322 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">#(vec(.variables %))</span> 35.1323 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">(concat (differential-seq coefficient variables) (apply differential-seq cvs)))))</span> 35.1324 + 35.1325 +</pre> 35.1326 + 35.1327 + 35.1328 + 35.1329 + 35.1330 + 35.1331 + 35.1332 + 35.1333 + 35.1334 + 35.1335 + 35.1336 + 35.1337 + 35.1338 + 35.1339 + 35.1340 + 35.1341 + 35.1342 +</div> 35.1343 + 35.1344 +</div> 35.1345 + 35.1346 +<div id="outline-container-6" class="outline-2"> 35.1347 +<h2 id="sec-6"><span class="section-number-2">6</span> Symbolic Manipulation </h2> 35.1348 +<div class="outline-text-2" id="text-6"> 35.1349 + 35.1350 + 35.1351 + 35.1352 + 35.1353 + 35.1354 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 35.1355 + 35.1356 +(<span style="color: #f0dfaf; font-weight: bold;">deftype</span> <span style="color: #f0dfaf;">Symbolic</span> [type expression] 35.1357 + Object 35.1358 + (equals [this that] 35.1359 + (<span style="color: #f0dfaf; font-weight: bold;">cond</span> 35.1360 + (<span style="color: #8cd0d3;">=</span> (.expression this) (.expression that)) true 35.1361 + <span style="color: #8cd0d3;">:else</span> 35.1362 + (Symbolic. 35.1363 + java.lang.Boolean 35.1364 + (<span style="color: #8cd0d3;">list</span> '= (.expression this) (.expression that))) 35.1365 + ))) 35.1366 + 35.1367 + 35.1368 + 35.1369 + 35.1370 +(<span style="color: #f0dfaf; font-weight: bold;">deftype</span> <span style="color: #f0dfaf;">AbstractSet</span> [glyph membership-test]) 35.1371 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">member?</span> [abstract-set x] 35.1372 + ((.membership-test abstract-set) x)) 35.1373 + 35.1374 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">------------ Some important AbstractSets</span> 35.1375 + 35.1376 + 35.1377 +(<span style="color: #f0dfaf; font-weight: bold;">def</span> <span style="color: #f0dfaf;">Real</span> 35.1378 + (AbstractSet. 35.1379 + 'R 35.1380 + (<span style="color: #8cd0d3;">fn</span>[x](<span style="color: #8cd0d3;">number?</span> x)))) 35.1381 + 35.1382 + 35.1383 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">------------ Create new AbstractSets from existing ones</span> 35.1384 + 35.1385 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">abstract-product</span> 35.1386 + <span style="color: #8fb28f;">"Gives the cartesian product of abstract sets."</span> 35.1387 + ([sets] 35.1388 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">count</span> sets) 1) (<span style="color: #8cd0d3;">first</span> sets) 35.1389 + (AbstractSet. 35.1390 + (<span style="color: #8cd0d3;">symbol</span> 35.1391 + (<span style="color: #8cd0d3;">apply</span> str 35.1392 + (<span style="color: #8cd0d3;">interpose</span> 'x (<span style="color: #8cd0d3;">map</span> #(.glyph %) sets)))) 35.1393 + (<span style="color: #8cd0d3;">fn</span> [x] 35.1394 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> 35.1395 + (<span style="color: #8cd0d3;">coll?</span> x) 35.1396 + (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">count</span> sets) (<span style="color: #8cd0d3;">count</span> x)) 35.1397 + (<span style="color: #8cd0d3;">reduce</span> #(<span style="color: #f0dfaf; font-weight: bold;">and</span> %1 %2) 35.1398 + true 35.1399 + (<span style="color: #8cd0d3;">map</span> #(member? %1 %2) sets x))))))) 35.1400 + ([abstract-set n] 35.1401 + (abstract-product (<span style="color: #8cd0d3;">repeat</span> n abstract-set)))) 35.1402 + 35.1403 + 35.1404 + 35.1405 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">abstract-up</span> 35.1406 + <span style="color: #8fb28f;">"Returns the abstract set of all up-tuples whose items belong to the</span> 35.1407 +<span style="color: #8fb28f;"> corresponding abstract sets in coll."</span> 35.1408 + ([coll] 35.1409 + (AbstractSet. 35.1410 + (<span style="color: #8cd0d3;">symbol</span> (<span style="color: #8cd0d3;">str</span> <span style="color: #cc9393;">"u["</span> 35.1411 + (<span style="color: #8cd0d3;">apply</span> str 35.1412 + (<span style="color: #8cd0d3;">interpose</span> <span style="color: #cc9393;">" "</span> 35.1413 + (<span style="color: #8cd0d3;">map</span> #(.glyph %) coll))) 35.1414 + <span style="color: #cc9393;">"]"</span>)) 35.1415 + (<span style="color: #8cd0d3;">fn</span> [x] 35.1416 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> 35.1417 + (<span style="color: #8cd0d3;">satisfies?</span> Spinning x) 35.1418 + (up? x) 35.1419 + (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">count</span> coll) (<span style="color: #8cd0d3;">count</span> x)) 35.1420 + (<span style="color: #8cd0d3;">reduce</span> 35.1421 + #(<span style="color: #f0dfaf; font-weight: bold;">and</span> %1 %2) 35.1422 + true 35.1423 + (<span style="color: #8cd0d3;">map</span> #(member? %1 %2) coll x)))))) 35.1424 + ([abstract-set n] 35.1425 + (abstract-up (<span style="color: #8cd0d3;">repeat</span> n abstract-set)))) 35.1426 + 35.1427 + 35.1428 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">abstract-down</span> 35.1429 + <span style="color: #8fb28f;">"Returns the abstract set of all down-tuples whose items belong to the</span> 35.1430 +<span style="color: #8fb28f;"> corresponding abstract sets in coll."</span> 35.1431 + ([coll] 35.1432 + (AbstractSet. 35.1433 + (<span style="color: #8cd0d3;">symbol</span> (<span style="color: #8cd0d3;">str</span> <span style="color: #cc9393;">"d["</span> 35.1434 + (<span style="color: #8cd0d3;">apply</span> str 35.1435 + (<span style="color: #8cd0d3;">interpose</span> <span style="color: #cc9393;">" "</span> 35.1436 + (<span style="color: #8cd0d3;">map</span> #(.glyph %) coll))) 35.1437 + <span style="color: #cc9393;">"]"</span>)) 35.1438 + (<span style="color: #8cd0d3;">fn</span> [x] 35.1439 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> 35.1440 + (<span style="color: #8cd0d3;">satisfies?</span> Spinning x) 35.1441 + (down? x) 35.1442 + (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">count</span> coll) (<span style="color: #8cd0d3;">count</span> x)) 35.1443 + (<span style="color: #8cd0d3;">reduce</span> 35.1444 + #(<span style="color: #f0dfaf; font-weight: bold;">and</span> %1 %2) 35.1445 + true 35.1446 + (<span style="color: #8cd0d3;">map</span> #(member? %1 %2) coll x)))))) 35.1447 + ([abstract-set n] 35.1448 + (abstract-down (<span style="color: #8cd0d3;">repeat</span> n abstract-set)))) 35.1449 + 35.1450 + 35.1451 + 35.1452 + 35.1453 + 35.1454 + <span style="color: #708070;">;</span><span style="color: #7f9f7f;">-------ABSTRACT FUNCTIONS</span> 35.1455 +(<span style="color: #f0dfaf; font-weight: bold;">defrecord</span> <span style="color: #f0dfaf;">AbstractFn</span> 35.1456 + [<span style="color: #dfdfbf; font-weight: bold;">#^AbstractSet</span> domain <span style="color: #dfdfbf; font-weight: bold;">#^AbstractSet</span> codomain]) 35.1457 + 35.1458 + 35.1459 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">print-method</span> AbstractFn 35.1460 + [o w] 35.1461 + (<span style="color: #8cd0d3;">print-simple</span> 35.1462 + (<span style="color: #8cd0d3;">str</span> 35.1463 + <span style="color: #cc9393;">"f:"</span> 35.1464 + (.glyph (<span style="color: #8cd0d3;">:domain</span> o)) 35.1465 + <span style="color: #cc9393;">"-->"</span> 35.1466 + (.glyph (<span style="color: #8cd0d3;">:codomain</span> o))) w)) 35.1467 +</pre> 35.1468 + 35.1469 + 35.1470 + 35.1471 + 35.1472 + 35.1473 + 35.1474 + 35.1475 +</div> 35.1476 +</div> 35.1477 +<div id="postamble"> 35.1478 +<p class="date">Date: 2011-08-09 18:41:37 EDT</p> 35.1479 +<p class="author">Author: Robert McIntyre & Dylan Holmes</p> 35.1480 +<p class="creator">Org version 7.6 with Emacs version 23</p> 35.1481 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 35.1482 +</div> 35.1483 +</div> 35.1484 +</body> 35.1485 +</html>
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/sicm/bk/utils.org Fri Oct 28 00:03:05 2011 -0700 36.3 @@ -0,0 +1,1262 @@ 36.4 +#+TITLE:Building a Classical Mechanics Library in Clojure 36.5 +#+author: Robert McIntyre & Dylan Holmes 36.6 +#+EMAIL: rlm@mit.edu 36.7 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js" 36.8 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 36.9 +#+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 36.10 +#+SETUPFILE: ../templates/level-0.org 36.11 +#+INCLUDE: ../templates/level-0.org 36.12 +#+BABEL: :noweb yes :results silent 36.13 + 36.14 +* Generic Arithmetic 36.15 + 36.16 +#+srcname: generic-arithmetic 36.17 +#+begin_src clojure 36.18 +(ns sicm.utils) 36.19 +(in-ns 'sicm.utils) 36.20 + 36.21 + 36.22 + 36.23 +(defn all-equal? [coll] 36.24 + (if (empty? (rest coll)) true 36.25 + (and (= (first coll) (second coll)) 36.26 + (recur (rest coll))))) 36.27 + 36.28 + 36.29 +(defprotocol Arithmetic 36.30 + (zero [this]) 36.31 + (one [this]) 36.32 + (negate [this]) 36.33 + (invert [this]) 36.34 + (conjugate [this])) 36.35 + 36.36 +(defn zero? [x] 36.37 + (= x (zero x))) 36.38 +(defn one? [x] 36.39 + (= x (one x))) 36.40 + 36.41 + 36.42 + 36.43 +(extend-protocol Arithmetic 36.44 + java.lang.Number 36.45 + (zero [x] 0) 36.46 + (one [x] 1) 36.47 + (negate [x] (- x)) 36.48 + (invert [x] (/ x)) 36.49 + ) 36.50 + 36.51 +(extend-protocol Arithmetic 36.52 + clojure.lang.IFn 36.53 + (one [f] identity) 36.54 + (negate [f] (comp negate f)) 36.55 + (invert [f] (comp invert f))) 36.56 + 36.57 + 36.58 +(extend-protocol Arithmetic 36.59 + clojure.lang.Seqable 36.60 + (zero [this] (map zero this)) 36.61 + (one [this] (map one this)) 36.62 + (invert [this] (map invert this)) 36.63 + (negate [this] (map negate this))) 36.64 + 36.65 + 36.66 +(defn ordered-like 36.67 + "Create a comparator using the sorted collection as an 36.68 + example. Elements not in the sorted collection are sorted to the 36.69 + end." 36.70 + [sorted-coll] 36.71 + (let [ 36.72 + sorted-coll? (set sorted-coll) 36.73 + ascending-pair? 36.74 + (set(reduce concat 36.75 + (map-indexed 36.76 + (fn [n x] 36.77 + (map #(vector x %) (nthnext sorted-coll n))) 36.78 + sorted-coll)))] 36.79 + (fn [x y] 36.80 + (cond 36.81 + (= x y) 0 36.82 + (ascending-pair? [x y]) -1 36.83 + (ascending-pair? [y x]) 1 36.84 + (sorted-coll? x) -1 36.85 + (sorted-coll? y) 1)))) 36.86 + 36.87 + 36.88 + 36.89 +(def type-precedence 36.90 + (ordered-like [incanter.Matrix])) 36.91 + 36.92 +(defmulti add 36.93 + (fn [x y] 36.94 + (sort type-precedence [(type x)(type y)]))) 36.95 + 36.96 +(defmulti multiply 36.97 + (fn [x y] 36.98 + (sort type-precedence [(type x) (type y)]))) 36.99 + 36.100 +(defmethod add [java.lang.Number java.lang.Number] [x y] (+ x y)) 36.101 +(defmethod multiply [java.lang.Number java.lang.Number] [x y] (* x y)) 36.102 + 36.103 +(defmethod multiply [incanter.Matrix java.lang.Integer] [x y] 36.104 + (let [args (sort #(type-precedence (type %1)(type %2)) [x y]) 36.105 + matrix (first args) 36.106 + scalar (second args)] 36.107 + (incanter.core/matrix (map (partial map (partial multiply scalar)) matrix)))) 36.108 + 36.109 +#+end_src 36.110 + 36.111 + 36.112 +* Useful Data Types 36.113 + 36.114 +** Complex Numbers 36.115 +#+srcname: complex-numbers 36.116 +#+begin_src clojure 36.117 +(in-ns 'sicm.utils) 36.118 + 36.119 +(defprotocol Complex 36.120 + (real-part [z]) 36.121 + (imaginary-part [z]) 36.122 + (magnitude-squared [z]) 36.123 + (angle [z]) 36.124 + (conjugate [z]) 36.125 + (norm [z])) 36.126 + 36.127 +(defn complex-rectangular 36.128 + "Define a complex number with the given real and imaginary 36.129 + components." 36.130 + [re im] 36.131 + (reify Complex 36.132 + (real-part [z] re) 36.133 + (imaginary-part [z] im) 36.134 + (magnitude-squared [z] (+ (* re re) (* im im))) 36.135 + (angle [z] (java.lang.Math/atan2 im re)) 36.136 + (conjugate [z] (complex-rectangular re (- im))) 36.137 + 36.138 + Arithmetic 36.139 + (zero [z] (complex-rectangular 0 0)) 36.140 + (one [z] (complex-rectangular 1 0)) 36.141 + (negate [z] (complex-rectangular (- re) (- im))) 36.142 + (invert [z] (complex-rectangular 36.143 + (/ re (magnitude-squared z)) 36.144 + (/ (- im) (magnitude-squared z)))) 36.145 + 36.146 + Object 36.147 + (toString [_] 36.148 + (if (and (zero? re) (zero? im)) (str 0) 36.149 + (str 36.150 + (if (not(zero? re)) 36.151 + re) 36.152 + (if ((comp not zero?) im) 36.153 + (str 36.154 + (if (neg? im) "-" "+") 36.155 + (if ((comp not one?) (java.lang.Math/abs im)) 36.156 + (java.lang.Math/abs im)) 36.157 + "i"))))))) 36.158 + 36.159 +(defn complex-polar 36.160 + "Define a complex number with the given magnitude and angle." 36.161 + [mag ang] 36.162 + (reify Complex 36.163 + (magnitude-squared [z] (* mag mag)) 36.164 + (angle [z] angle) 36.165 + (real-part [z] (* mag (java.lang.Math/cos ang))) 36.166 + (imaginary-part [z] (* mag (java.lang.Math/sin ang))) 36.167 + (conjugate [z] (complex-polar mag (- ang))) 36.168 + 36.169 + Arithmetic 36.170 + (zero [z] (complex-polar 0 0)) 36.171 + (one [z] (complex-polar 1 0)) 36.172 + (negate [z] (complex-polar (- mag) ang)) 36.173 + (invert [z] (complex-polar (/ mag) (- ang))) 36.174 + 36.175 + Object 36.176 + (toString [_] (str mag " * e^(i" ang")")) 36.177 + )) 36.178 + 36.179 + 36.180 +;; Numbers are complex quantities 36.181 + 36.182 +(extend-protocol Complex 36.183 + java.lang.Number 36.184 + (real-part [x] x) 36.185 + (imaginary-part [x] 0) 36.186 + (magnitude [x] x) 36.187 + (angle [x] 0) 36.188 + (conjugate [x] x)) 36.189 + 36.190 + 36.191 +#+end_src 36.192 + 36.193 + 36.194 + 36.195 +** Tuples and Tensors 36.196 + 36.197 +A tuple is a vector which is spinable\mdash{}it can be either /spin 36.198 +up/ or /spin down/. (Covariant, contravariant; dual vectors) 36.199 +#+srcname: tuples 36.200 +#+begin_src clojure 36.201 +(in-ns 'sicm.utils) 36.202 + 36.203 +(defprotocol Spinning 36.204 + (up? [this]) 36.205 + (down? [this])) 36.206 + 36.207 +(defn spin 36.208 + "Returns the spin of the Spinning s, either :up or :down" 36.209 + [#^Spinning s] 36.210 + (cond (up? s) :up (down? s) :down)) 36.211 + 36.212 + 36.213 +(deftype Tuple 36.214 + [spin coll] 36.215 + clojure.lang.Seqable 36.216 + (seq [this] (seq (.coll this))) 36.217 + clojure.lang.Counted 36.218 + (count [this] (count (.coll this)))) 36.219 + 36.220 +(extend-type Tuple 36.221 + Spinning 36.222 + (up? [this] (= ::up (.spin this))) 36.223 + (down? [this] (= ::down (.spin this)))) 36.224 + 36.225 +(defmethod print-method Tuple 36.226 + [o w] 36.227 + (print-simple (str (if (up? o) 'u 'd) (.coll o)) w)) 36.228 + 36.229 + 36.230 + 36.231 +(defn up 36.232 + "Create a new up-tuple containing the contents of coll." 36.233 + [coll] 36.234 + (Tuple. ::up coll)) 36.235 + 36.236 +(defn down 36.237 + "Create a new down-tuple containing the contents of coll." 36.238 + [coll] 36.239 + (Tuple. ::down coll)) 36.240 + 36.241 + 36.242 +#+end_src 36.243 + 36.244 +*** Contraction 36.245 +Contraction is a binary operation that you can apply to compatible 36.246 + tuples. Tuples are compatible for contraction if they have the same 36.247 + length and opposite spins, and if the corresponding items in each 36.248 + tuple are both numbers or both compatible tuples. 36.249 + 36.250 +#+srcname: tuples-2 36.251 +#+begin_src clojure 36.252 +(in-ns 'sicm.utils) 36.253 + 36.254 +(defn numbers? 36.255 + "Returns true if all arguments are numbers, else false." 36.256 + [& xs] 36.257 + (every? number? xs)) 36.258 + 36.259 +(defn contractible? 36.260 + "Returns true if the tuples a and b are compatible for contraction, 36.261 + else false. Tuples are compatible if they have the same number of 36.262 + components, they have opposite spins, and their elements are 36.263 + pairwise-compatible." 36.264 + [a b] 36.265 + (and 36.266 + (isa? (type a) Tuple) 36.267 + (isa? (type b) Tuple) 36.268 + (= (count a) (count b)) 36.269 + (not= (spin a) (spin b)) 36.270 + 36.271 + (not-any? false? 36.272 + (map #(or 36.273 + (numbers? %1 %2) 36.274 + (contractible? %1 %2)) 36.275 + a b)))) 36.276 + 36.277 + 36.278 + 36.279 +(defn contract 36.280 + "Contracts two tuples, returning the sum of the 36.281 + products of the corresponding items. Contraction is recursive on 36.282 + nested tuples." 36.283 + [a b] 36.284 + (if (not (contractible? a b)) 36.285 + (throw 36.286 + (Exception. "Not compatible for contraction.")) 36.287 + (reduce + 36.288 + (map 36.289 + (fn [x y] 36.290 + (if (numbers? x y) 36.291 + (* x y) 36.292 + (contract x y))) 36.293 + a b)))) 36.294 + 36.295 +#+end_src 36.296 + 36.297 +*** Matrices 36.298 +#+srcname: matrices 36.299 +#+begin_src clojure 36.300 +(in-ns 'sicm.utils) 36.301 +(require 'incanter.core) ;; use incanter's fast matrices 36.302 + 36.303 +(defprotocol Matrix 36.304 + (rows [matrix]) 36.305 + (cols [matrix]) 36.306 + (diagonal [matrix]) 36.307 + (trace [matrix]) 36.308 + (determinant [matrix]) 36.309 + (transpose [matrix]) 36.310 + (conjugate [matrix]) 36.311 +) 36.312 + 36.313 +(extend-protocol Matrix 36.314 + incanter.Matrix 36.315 + (rows [rs] (map down (apply map vector (apply map vector rs)))) 36.316 + (cols [rs] (map up (apply map vector rs))) 36.317 + (diagonal [matrix] (incanter.core/diag matrix) ) 36.318 + (determinant [matrix] (incanter.core/det matrix)) 36.319 + (trace [matrix] (incanter.core/trace matrix)) 36.320 + (transpose [matrix] (incanter.core/trans matrix)) 36.321 + ) 36.322 + 36.323 +(defn count-rows [matrix] 36.324 + ((comp count rows) matrix)) 36.325 + 36.326 +(defn count-cols [matrix] 36.327 + ((comp count cols) matrix)) 36.328 + 36.329 +(defn square? [matrix] 36.330 + (= (count-rows matrix) (count-cols matrix))) 36.331 + 36.332 +(defn identity-matrix 36.333 + "Define a square matrix of size n-by-n with 1s along the diagonal and 36.334 + 0s everywhere else." 36.335 + [n] 36.336 + (incanter.core/identity-matrix n)) 36.337 + 36.338 + 36.339 + 36.340 + 36.341 + 36.342 +(defn matrix-by-rows 36.343 + "Define a matrix by giving its rows." 36.344 + [& rows] 36.345 + (if 36.346 + (not (all-equal? (map count rows))) 36.347 + (throw (Exception. "All rows in a matrix must have the same number of elements.")) 36.348 + (incanter.core/matrix (vec rows)))) 36.349 + 36.350 +(defn matrix-by-cols 36.351 + "Define a matrix by giving its columns" 36.352 + [& cols] 36.353 + (if (not (all-equal? (map count cols))) 36.354 + (throw (Exception. "All columns in a matrix must have the same number of elements.")) 36.355 + (incanter.core/matrix (vec (apply map vector cols))))) 36.356 + 36.357 +(defn identity-matrix 36.358 + "Define a square matrix of size n-by-n with 1s along the diagonal and 36.359 + 0s everywhere else." 36.360 + [n] 36.361 + (incanter.core/identity-matrix n)) 36.362 + 36.363 + 36.364 + 36.365 +(extend-protocol Arithmetic 36.366 + incanter.Matrix 36.367 + (one [matrix] 36.368 + (if (square? matrix) 36.369 + (identity-matrix (count-rows matrix)) 36.370 + (throw (Exception. "Non-square matrices have no multiplicative unit.")))) 36.371 + (zero [matrix] 36.372 + (apply matrix-by-rows (map zero (rows matrix)))) 36.373 + (negate [matrix] 36.374 + (apply matrix-by-rows (map negate (rows matrix)))) 36.375 + (invert [matrix] 36.376 + (incanter.core/solve matrix))) 36.377 + 36.378 + 36.379 + 36.380 +(defmulti coerce-to-matrix 36.381 + "Converts x into a matrix, if possible." 36.382 + type) 36.383 + 36.384 +(defmethod coerce-to-matrix incanter.Matrix [x] x) 36.385 +(defmethod coerce-to-matrix Tuple [x] 36.386 + (if (apply numbers? (seq x)) 36.387 + (if (up? x) 36.388 + (matrix-by-cols (seq x)) 36.389 + (matrix-by-rows (seq x))) 36.390 + (throw (Exception. "Non-numerical tuple cannot be converted into a matrix.")))) 36.391 + 36.392 + 36.393 + 36.394 + 36.395 + 36.396 +;; (defn matrix-by-cols 36.397 +;; "Define a matrix by giving its columns." 36.398 +;; [& cols] 36.399 +;; (cond 36.400 +;; (not (all-equal? (map count cols))) 36.401 +;; (throw (Exception. "All columns in a matrix must have the same number of elements.")) 36.402 +;; :else 36.403 +;; (reify Matrix 36.404 +;; (cols [this] (map up cols)) 36.405 +;; (rows [this] (map down (apply map vector cols))) 36.406 +;; (diagonal [this] (map-indexed (fn [i col] (nth col i) cols))) 36.407 +;; (trace [this] 36.408 +;; (if (not= (count-cols this) (count-rows this)) 36.409 +;; (throw (Exception. 36.410 +;; "Cannot take the trace of a non-square matrix.")) 36.411 +;; (reduce + (diagonal this)))) 36.412 + 36.413 +;; (determinant [this] 36.414 +;; (if (not= (count-cols this) (count-rows this)) 36.415 +;; (throw (Exception. 36.416 +;; "Cannot take the determinant of a non-square matrix.")) 36.417 +;; (reduce * (map-indexed (fn [i col] (nth col i)) cols)))) 36.418 +;; ))) 36.419 + 36.420 +(extend-protocol Matrix Tuple 36.421 + (rows [this] (if (down? this) 36.422 + (list this) 36.423 + (map (comp up vector) this))) 36.424 + 36.425 + (cols [this] (if (up? this) 36.426 + (list this) 36.427 + (map (comp down vector) this)) 36.428 + )) 36.429 + 36.430 +(defn matrix-multiply 36.431 + "Returns the matrix resulting from the matrix multiplication of the given arguments." 36.432 + ([A] (coerce-to-matrix A)) 36.433 + ([A B] (incanter.core/mmult (coerce-to-matrix A) (coerce-to-matrix B))) 36.434 + ([M1 M2 & Ms] (reduce matrix-multiply (matrix-multiply M1 M2) Ms))) 36.435 + 36.436 +#+end_src 36.437 + 36.438 + 36.439 +** Power Series 36.440 +#+srcname power-series 36.441 +#+begin_src clojure 36.442 +(in-ns 'sicm.utils) 36.443 +(use 'clojure.contrib.def) 36.444 + 36.445 + 36.446 + 36.447 +(defn series-fn 36.448 + "The function corresponding to the given power series." 36.449 + [series] 36.450 + (fn [x] 36.451 + (reduce + 36.452 + (map-indexed (fn[n x] (* (float (nth series n)) (float(java.lang.Math/pow (float x) n)) )) 36.453 + (range 20))))) 36.454 + 36.455 +(deftype PowerSeries 36.456 + [coll] 36.457 + clojure.lang.Seqable 36.458 + (seq [this] (seq (.coll this))) 36.459 + 36.460 + clojure.lang.Indexed 36.461 + (nth [this n] (nth (.coll this) n 0)) 36.462 + (nth [this n not-found] (nth (.coll this) n not-found)) 36.463 + 36.464 + ;; clojure.lang.IFn 36.465 + ;; (call [this] (throw(Exception.))) 36.466 + ;; (invoke [this & args] args 36.467 + ;; (let [f 36.468 + ;; ) 36.469 + ;; (run [this] (throw(Exception.))) 36.470 + ) 36.471 + 36.472 +(defn power-series 36.473 + "Returns a power series with the items of the coll as its 36.474 + coefficients. Trailing zeros are added to the end of coll." 36.475 + [coeffs] 36.476 + (PowerSeries. coeffs)) 36.477 + 36.478 +(defn power-series-indexed 36.479 + "Returns a power series consisting of the result of mapping f to the non-negative integers." 36.480 + [f] 36.481 + (PowerSeries. (map f (range)))) 36.482 + 36.483 + 36.484 +(defn-memo nth-partial-sum 36.485 + ([series n] 36.486 + (if (zero? n) (first series) 36.487 + (+ (nth series n) 36.488 + (nth-partial-sum series (dec n)))))) 36.489 + 36.490 +(defn partial-sums [series] 36.491 + (lazy-seq (map nth-partial-sum (range)))) 36.492 + 36.493 + 36.494 + 36.495 + 36.496 +(def cos-series 36.497 + (power-series-indexed 36.498 + (fn[n] 36.499 + (if (odd? n) 0 36.500 + (/ 36.501 + (reduce * 36.502 + (reduce * (repeat (/ n 2) -1)) 36.503 + (range 1 (inc n))) 36.504 + ))))) 36.505 + 36.506 +(def sin-series 36.507 + (power-series-indexed 36.508 + (fn[n] 36.509 + (if (even? n) 0 36.510 + (/ 36.511 + (reduce * 36.512 + (reduce * (repeat (/ (dec n) 2) -1)) 36.513 + (range 1 (inc n))) 36.514 + ))))) 36.515 + 36.516 +#+end_src 36.517 + 36.518 + 36.519 +* Basic Utilities 36.520 + 36.521 +** Sequence manipulation 36.522 + 36.523 +#+srcname: seq-manipulation 36.524 +#+begin_src clojure 36.525 +(ns sicm.utils) 36.526 + 36.527 +(defn do-up 36.528 + "Apply f to each number from low to high, presumably for 36.529 + side-effects." 36.530 + [f low high] 36.531 + (doseq [i (range low high)] (f i))) 36.532 + 36.533 +(defn do-down 36.534 + "Apply f to each number from high to low, presumably for 36.535 + side-effects." 36.536 + [f high low] 36.537 + (doseq [i (range high low -1)] (f i))) 36.538 + 36.539 + 36.540 +(defn all-equal? [coll] 36.541 + (if (empty? (rest coll)) true 36.542 + (and (= (first coll) (second coll)) 36.543 + (recur (rest coll)))))) 36.544 + 36.545 +(defn multiplier 36.546 + "Returns a function that 'multiplies' the members of a collection, 36.547 +returning unit if called on an empty collection." 36.548 + [multiply unit] 36.549 + (fn [coll] ((partial reduce multiply unit) coll))) 36.550 + 36.551 +(defn divider 36.552 + "Returns a function that 'divides' the first element of a collection 36.553 +by the 'product' of the rest of the collection." 36.554 + [divide multiply invert unit] 36.555 + (fn [coll] 36.556 + (apply 36.557 + (fn 36.558 + ([] unit) 36.559 + ([x] (invert x)) 36.560 + ([x y] (divide x y)) 36.561 + ([x y & zs] (divide x (reduce multiply y zs)))) 36.562 + coll))) 36.563 + 36.564 +(defn left-circular-shift 36.565 + "Remove the first element of coll, adding it to the end of coll." 36.566 + [coll] 36.567 + (concat (rest coll) (take 1 coll))) 36.568 + 36.569 +(defn right-circular-shift 36.570 + "Remove the last element of coll, adding it to the front of coll." 36.571 + [coll] 36.572 + (cons (last coll) (butlast coll))) 36.573 +#+end_src 36.574 + 36.575 + 36.576 + 36.577 + 36.578 +** Ranges, Airity and Function Composition 36.579 +#+srcname: arity 36.580 +#+begin_src clojure 36.581 +(in-ns 'sicm.utils) 36.582 +(def infinity Double/POSITIVE_INFINITY) 36.583 +(defn infinite? [x] (Double/isInfinite x)) 36.584 +(def finite? (comp not infinite?)) 36.585 + 36.586 +(defn arity-min 36.587 + "Returns the smallest number of arguments f can take." 36.588 + [f] 36.589 + (apply 36.590 + min 36.591 + (map (comp alength #(.getParameterTypes %)) 36.592 + (filter (comp (partial = "invoke") #(.getName %)) 36.593 + (.getDeclaredMethods (class f)))))) 36.594 + 36.595 +(defn arity-max 36.596 + "Returns the largest number of arguments f can take, possibly 36.597 + Infinity." 36.598 + [f] 36.599 + (let [methods (.getDeclaredMethods (class f))] 36.600 + (if (not-any? (partial = "doInvoke") (map #(.getName %) methods)) 36.601 + (apply max 36.602 + (map (comp alength #(.getParameterTypes %)) 36.603 + (filter (comp (partial = "invoke") #(.getName %)) methods))) 36.604 + infinity))) 36.605 + 36.606 + 36.607 +(def ^{:arglists '([f]) 36.608 + :doc "Returns a two-element list containing the minimum and 36.609 + maximum number of args that f can take."} 36.610 + arity-interval 36.611 + (juxt arity-min arity-max)) 36.612 + 36.613 + 36.614 + 36.615 +;; --- intervals 36.616 + 36.617 +(defn intersect 36.618 + "Returns the interval of overlap between interval-1 and interval-2" 36.619 + [interval-1 interval-2] 36.620 + (if (or (empty? interval-1) (empty? interval-2)) [] 36.621 + (let [left (max (first interval-1) (first interval-2)) 36.622 + right (min (second interval-1) (second interval-2))] 36.623 + (if (> left right) [] 36.624 + [left right])))) 36.625 + 36.626 +(defn same-endpoints? 36.627 + "Returns true if the left endpoint is the same as the right 36.628 + endpoint." 36.629 + [interval] 36.630 + (= (first interval) (second interval))) 36.631 + 36.632 +(defn naturals? 36.633 + "Returns true if the left endpoint is 0 and the right endpoint is 36.634 +infinite." 36.635 + [interval] 36.636 + (and (zero? (first interval)) 36.637 + (infinite? (second interval)))) 36.638 + 36.639 + 36.640 +(defn fan-in 36.641 + "Returns a function that pipes its input to each of the gs, then 36.642 + applies f to the list of results. Consequently, f must be able to 36.643 + take a number of arguments equal to the number of gs." 36.644 + [f & gs] 36.645 + (fn [& args] 36.646 + (apply f (apply (apply juxt gs) args)))) 36.647 + 36.648 +(defn fan-in 36.649 + "Returns a function that pipes its input to each of the gs, then applies f to the list of results. The resulting function takes any number of arguments, but will fail if given arguments that are incompatible with any of the gs." 36.650 + [f & gs] 36.651 + (comp (partial apply f) (apply juxt gs))) 36.652 + 36.653 + 36.654 + 36.655 +(defmacro airty-blah-sad [f n more?] 36.656 + (let [syms (vec (map (comp gensym (partial str "x")) (range n))) 36.657 + optional (gensym "xs")] 36.658 + (if more? 36.659 + `(fn ~(conj syms '& optional) 36.660 + (apply ~f ~@syms ~optional)) 36.661 + `(fn ~syms (~f ~@syms))))) 36.662 + 36.663 +(defmacro airt-whaa* [f n more?] 36.664 + `(airty-blah-sad ~f ~n ~more?)) 36.665 + 36.666 + 36.667 + 36.668 + 36.669 +(defn fan-in* 36.670 + "Returns a function that pipes its input to each of the gs, then 36.671 + applies f to the list of results. Unlike fan-in, fan-in* strictly 36.672 + enforces arity: it will fail if the gs do not have compatible 36.673 + arities." 36.674 + [f & gs] 36.675 + (let [arity-in (reduce intersect (map arity-interval gs)) 36.676 + left (first arity-in) 36.677 + right (second arity-in) 36.678 + composite (fan-in f gs) 36.679 + ] 36.680 + (cond 36.681 + (empty? arity-in) 36.682 + (throw (Exception. "Cannot compose functions with incompatible arities.")) 36.683 + 36.684 + (not 36.685 + (or (= left right) 36.686 + (and (finite? left) 36.687 + (= right infinity)))) 36.688 + 36.689 + (throw (Exception. 36.690 + "Compose can only handle arities of the form [n n] or [n infinity]")) 36.691 + :else 36.692 + (airty-blah-sad composite left (= right infinity))))) 36.693 + 36.694 + 36.695 + 36.696 +(defn compose-n "Compose any number of functions together." 36.697 + ([] identity) 36.698 + ([f] f) 36.699 + ([f & fs] 36.700 + (let [fns (cons f fs)] 36.701 + (compose-bin (reduce fan-in (butlast fs)) (last fs)))) 36.702 +) 36.703 + 36.704 + 36.705 + 36.706 + 36.707 + 36.708 + 36.709 +(defn iterated 36.710 + ([f n id] (reduce comp id (repeat n f))) 36.711 + ([f n] (reduce comp identity (repeat n f)))) 36.712 + 36.713 +(defn iterate-until-stable 36.714 + "Repeatedly applies f to x, returning the first result that is close 36.715 +enough to its predecessor." 36.716 + [f close-enough? x] 36.717 + (second (swank.util/find-first 36.718 + (partial apply close-enough?) 36.719 + (partition 2 1 (iterate f x))))) 36.720 + 36.721 +(defn lexical< [x y] 36.722 + (neg? (compare (str x) (str y)))) 36.723 + 36.724 + 36.725 +;; do-up 36.726 +;; do-down 36.727 +(def make-pairwise-test comparator) 36.728 +;;all-equal? 36.729 +(def accumulation multiplier) 36.730 +(def inverse-accumulation divider) 36.731 +;;left-circular-shift 36.732 +;;right-circular-shift 36.733 +(def exactly-n? same-endpoints?) 36.734 +(def any-number? naturals?) 36.735 +;; TODO compose 36.736 +;; TODO compose-n 36.737 +;; identity 36.738 +(def compose-2 fan-in) 36.739 +(def compose-bin fan-in*) 36.740 +(def any? (constantly true)) 36.741 +(def none? (constantly false)) 36.742 +(def constant constantly) 36.743 +(def joint-arity intersect) 36.744 +(def a-reduce reduce) 36.745 +;; filter 36.746 +(def make-map (partial partial map) ) 36.747 +(def bracket juxt) 36.748 +;; TODO apply-to-all 36.749 +;; TODO nary-combine 36.750 +;; TODO binary-combine 36.751 +;; TODO unary-combine 36.752 +;; iterated 36.753 +;; iterate-until-stable 36.754 +(def make-function-of-vector (partial partial map)) 36.755 +(def make-function-of-arguments (fn [f] (fn [& args] (f args)))) 36.756 +(def alphaless lexical<) 36.757 + 36.758 +#+end_src 36.759 + 36.760 + 36.761 + 36.762 + 36.763 + 36.764 + 36.765 + 36.766 +: 36.767 + 36.768 +* Numerical Methods 36.769 +#+srcname: numerical-methods 36.770 +#+begin_src clojure 36.771 +(in-ns 'sicm.utils) 36.772 +(import java.lang.Math) 36.773 +(use 'clojure.contrib.def) 36.774 + 36.775 +;; ---- USEFUL CONSTANTS 36.776 + 36.777 +(defn machine-epsilon 36.778 + "Smallest value representable on your machine, as determined by 36.779 +successively dividing a number in half until consecutive results are 36.780 +indistinguishable." 36.781 + [] 36.782 + (ffirst 36.783 + (drop-while 36.784 + (comp not zero? second) 36.785 + (partition 2 1 36.786 + (iterate (partial * 0.5) 1))))) 36.787 + 36.788 + 36.789 +(def pi (Math/PI)) 36.790 +(def two-pi (* 2 pi)) 36.791 + 36.792 +(def eulers-gamma 0.5772156649015328606065) 36.793 + 36.794 +(def phi (/ (inc (Math/sqrt 5)) 2)) 36.795 + 36.796 +(def ln2 (Math/log 2)) 36.797 +(def ln10 (Math/log 10)) 36.798 +(def exp10 #(Math/pow 10 %)) 36.799 +(def exp2 #(Math/pow 2 %)) 36.800 + 36.801 + 36.802 +;; 36.803 + 36.804 +;; ---- ANGLES AND TRIGONOMETRY 36.805 + 36.806 +(defn angle-restrictor 36.807 + "Returns a function that ensures that angles lie in the specified interval of length two-pi." 36.808 + [max-angle] 36.809 + (let [min-angle (- max-angle two-pi)] 36.810 + (fn [x] 36.811 + (if (and 36.812 + (<= min-angle x) 36.813 + (< x max-angle)) 36.814 + x 36.815 + (let [corrected-x (- x (* two-pi (Math/floor (/ x two-pi))))] 36.816 + (if (< corrected-x max-angle) 36.817 + corrected-x 36.818 + (- corrected-x two-pi))))))) 36.819 + 36.820 +(defn angle-restrict-pi 36.821 + "Coerces angles to lie in the interval from -pi to pi." 36.822 + [angle] 36.823 + ((angle-restrictor pi) angle)) 36.824 + 36.825 +(defn angle-restrict-two-pi 36.826 + "Coerces angles to lie in the interval from zero to two-pi" 36.827 + [angle] 36.828 + ((angle-restrictor two-pi) angle)) 36.829 + 36.830 + 36.831 + 36.832 + 36.833 +(defn invert [x] (/ x)) 36.834 +(defn negate [x] (- x)) 36.835 + 36.836 +(defn exp [x] (Math/exp x)) 36.837 + 36.838 +(defn sin [x] (Math/sin x)) 36.839 +(defn cos [x] (Math/cos x)) 36.840 +(defn tan [x] (Math/tan x)) 36.841 + 36.842 +(def sec (comp invert cos)) 36.843 +(def csc (comp invert sin)) 36.844 + 36.845 +(defn sinh [x] (Math/sinh x)) 36.846 +(defn cosh [x] (Math/cosh x)) 36.847 +(defn tanh [x] (Math/tanh x)) 36.848 + 36.849 +(def sech (comp invert cosh)) 36.850 +(def csch (comp invert sinh)) 36.851 + 36.852 + 36.853 +;; ------------ 36.854 + 36.855 +(defn factorial 36.856 + "Computes the factorial of the nonnegative integer n." 36.857 + [n] 36.858 + (if (neg? n) 36.859 + (throw (Exception. "Cannot compute the factorial of a negative number.")) 36.860 + (reduce * 1 (range 1 (inc n))))) 36.861 + 36.862 +(defn exact-quotient [n d] (/ n d)) 36.863 + 36.864 +(defn binomial-coefficient 36.865 + "Computes the number of different ways to choose m elements from n." 36.866 + [n m] 36.867 + (assert (<= 0 m n)) 36.868 + (let [difference (- n m)] 36.869 + (exact-quotient 36.870 + (reduce * (range n (max difference m) -1 )) 36.871 + (factorial (min difference m))))) 36.872 + 36.873 +(defn-memo stirling-1 36.874 + "Stirling numbers of the first kind: the number of permutations of n 36.875 + elements with exactly m permutation cycles. " 36.876 + [n k] 36.877 + ;(assert (<= 1 k n)) 36.878 + (if (zero? n) 36.879 + (if (zero? k) 1 0) 36.880 + (+ (stirling-1 (dec n) (dec k)) 36.881 + (* (dec n) (stirling-1 (dec n) k))))) 36.882 + 36.883 +(defn-memo stirling-2 ;;count-partitions 36.884 + "Stirling numbers of the second kind: the number of ways to partition a set of n elements into k subsets." 36.885 + [n k] 36.886 + (cond 36.887 + (= k 1) 1 36.888 + (= k n) 1 36.889 + :else (+ (stirling-2 (dec n) (dec k)) 36.890 + (* k (stirling-2 (dec n) k))))) 36.891 + 36.892 +(defn harmonic-number [n] 36.893 + (/ (stirling-1 (inc n) 2) 36.894 + (factorial n))) 36.895 + 36.896 + 36.897 +(defn sum 36.898 + [f low high] 36.899 + (reduce + (map f (range low (inc high))))) 36.900 + 36.901 +#+end_src 36.902 + 36.903 + 36.904 + 36.905 + 36.906 + 36.907 + 36.908 + 36.909 + 36.910 + 36.911 + 36.912 + 36.913 + 36.914 +* Differentiation 36.915 + 36.916 +We compute derivatives by passing special *differential objects* $[x, 36.917 +dx]$ through functions. Roughly speaking, applying a function $f$ to a 36.918 +differential object \([x, dx]\) should produce a new differential 36.919 +object $[f(x),\,Df(x)\cdot dx]$. 36.920 + 36.921 +\([x,\,dx]\xrightarrow{\quad f \quad}[f(x),\,Df(x)\cdot dx]\) 36.922 +Notice that you can obtain the derivative of $f$ from this 36.923 +differential object, as it is the coefficient of the $dx$ term. Also, 36.924 +as you apply successive functions using this rule, you get the 36.925 +chain-rule answer you expect: 36.926 + 36.927 +\([f(x),\,Df(x)\cdot dx]\xrightarrow{\quad g\quad} [gf(x),\, 36.928 +Dgf(x)\cdot Df(x) \cdot dx ]\) 36.929 + 36.930 +In order to generalize to multiple variables and multiple derivatives, 36.931 +we use a *power series of differentials*, a sortred infinite sequence which 36.932 +contains all terms like $dx\cdot dy$, $dx^2\cdot dy$, etc. 36.933 + 36.934 + 36.935 +#+srcname:differential 36.936 +#+begin_src clojure 36.937 +(in-ns 'sicm.utils) 36.938 +(use 'clojure.contrib.combinatorics) 36.939 +(use 'clojure.contrib.generic.arithmetic) 36.940 + 36.941 +(defprotocol DifferentialTerm 36.942 + "Protocol for an infinitesimal quantity." 36.943 + (coefficient [this]) 36.944 + (partials [this])) 36.945 + 36.946 +(extend-protocol DifferentialTerm 36.947 + java.lang.Number 36.948 + (coefficient [this] this) 36.949 + (partials [this] [])) 36.950 + 36.951 +(deftype DifferentialSeq 36.952 + [terms] 36.953 + clojure.lang.IPersistentCollection 36.954 + (cons [this x] 36.955 + (throw (Exception. x)) 36.956 + (DifferentialSeq. (cons x terms))) 36.957 + ;; (seq [this] (seq terms)) 36.958 + (count [this] (count terms)) 36.959 + (empty [this] (empty? terms))) 36.960 + 36.961 + 36.962 + 36.963 + 36.964 + 36.965 + 36.966 + 36.967 + 36.968 + 36.969 + 36.970 + 36.971 +(defn coerce-to-differential-seq [x] 36.972 + (cond 36.973 + (= (type x) DifferentialSeq) x 36.974 + (satisfies? DifferentialTerm x) (DifferentialSeq. x))) 36.975 + 36.976 + 36.977 +(defn differential-term 36.978 + "Returns a differential term with the given coefficient and 36.979 + partials. Coefficient may be any arithmetic object; partials must 36.980 + be a list of non-negative integers." 36.981 + [coefficient partials] 36.982 + (reify DifferentialTerm 36.983 + (partials [_] (set partials)) 36.984 + (coefficient [_] coefficient))) 36.985 + 36.986 + 36.987 + 36.988 +(defn differential-seq* 36.989 + ([coefficient partials] 36.990 + (DifferentialSeq. [(differential-term coefficient partials)])) 36.991 + ([coefficient partials & cps] 36.992 + (if cps 36.993 + 36.994 + 36.995 + 36.996 + 36.997 +(defn differential-seq 36.998 + "Constructs a sequence of differential terms from a numerical 36.999 +coefficient and a list of keys for variables. If no coefficient is supplied, uses 1." 36.1000 + ([variables] (differential-seq 1 variables)) 36.1001 + ([coefficient variables & cvs] 36.1002 + (if (number? coefficient) 36.1003 + (conj (assoc {} (apply sorted-set variables) coefficient) 36.1004 + (if (empty? cvs) 36.1005 + nil 36.1006 + (apply differential-seq cvs))) 36.1007 + (apply differential-seq 1 coefficient 1 variables cvs) 36.1008 + ))) 36.1009 + 36.1010 + 36.1011 +(defn differential-add 36.1012 + "Add two differential sequences by combining like terms." 36.1013 + [dseq1 dseq2] 36.1014 + (merge-with + dseq1 dseq2)) 36.1015 + 36.1016 +(defn differential-multiply 36.1017 + "Multiply two differential sequences. The square of any differential variable is zero since differential variables are infinitesimally small." 36.1018 + [dseq1 dseq2] 36.1019 + (reduce 36.1020 + (fn [m [[vars1 coeff1] [vars2 coeff2]]] 36.1021 + (if (empty? (clojure.set/intersection vars1 vars2)) 36.1022 + (assoc m (clojure.set/union vars1 vars2) (* coeff1 coeff2)) 36.1023 + m)) 36.1024 + {} 36.1025 + (clojure.contrib.combinatorics/cartesian-product 36.1026 + dseq1 36.1027 + dseq2))) 36.1028 + 36.1029 + 36.1030 +(defn big-part 36.1031 + "Returns the part of the differential sequence that is finite, 36.1032 + i.e. not infinitely small." 36.1033 + [dseq] 36.1034 + (let 36.1035 + [keys (sort-by count (keys dseq)) 36.1036 + smallest-var (last(last keys))] 36.1037 + (apply hash-map 36.1038 + (reduce concat 36.1039 + (remove (comp smallest-var first) dseq))))) 36.1040 + 36.1041 +(defn small-part 36.1042 + "Returns the part of the differential sequence that is 36.1043 + infinitesimal." 36.1044 + [dseq] 36.1045 + (let 36.1046 + [keys (sort-by count (keys dseq)) 36.1047 + smallest-var (last(last keys))] 36.1048 + (apply hash-map 36.1049 + (reduce concat 36.1050 + (filter (comp smallest-var first) dseq))))) 36.1051 + 36.1052 +(defn big-part 36.1053 + "Returns the 'finite' part of the differential sequence." 36.1054 + [dseq] 36.1055 + (let 36.1056 + [keys (sort-by count (keys dseq)) 36.1057 + smallest-var (last (last keys))] 36.1058 + (apply hash-map 36.1059 + (reduce concat 36.1060 + (filter (remove smallest-var first) dseq) 36.1061 + )))) 36.1062 + 36.1063 + 36.1064 +(defn small-part 36.1065 + "Returns the 'infinitesimal' part of the differential sequence." 36.1066 + [dseq] 36.1067 + (let 36.1068 + [keys (sort-by count (keys dseq)) 36.1069 + smallest-var (last (last keys))] 36.1070 + 36.1071 + (apply hash-map 36.1072 + (reduce concat 36.1073 + (filter (comp smallest-var first) dseq) 36.1074 + )))) 36.1075 + 36.1076 +(defn linear-approximator 36.1077 + "Returns the function that corresponds to unary-fn but which accepts and returns differential objects." 36.1078 + ([unary-f dfdx] 36.1079 + (fn F [dseq] 36.1080 + (differential-add 36.1081 + (unary-f (big-part dseq)) 36.1082 + (differential-multiply 36.1083 + (dfdx (big-part dseq)) 36.1084 + (small-part dseq)))))) 36.1085 + 36.1086 + 36.1087 + 36.1088 + 36.1089 + 36.1090 + 36.1091 +;; ;; A differential term consists of a numerical coefficient and a 36.1092 +;; ;; sorted 36.1093 +;; (defrecord DifferentialTerm [coefficient variables]) 36.1094 +;; (defmethod print-method DifferentialTerm 36.1095 +;; [o w] 36.1096 +;; (print-simple 36.1097 +;; (apply str (.coefficient o)(map (comp (partial str "d") name) (.variables o))) 36.1098 +;; w)) 36.1099 + 36.1100 + 36.1101 +;; (defn differential-seq 36.1102 +;; "Constructs a sequence of differential terms from a numerical 36.1103 +;; coefficient and a list of keywords for variables. If no coefficient is 36.1104 +;; supplied, uses 1." 36.1105 +;; ([variables] (differential-seq 1 variables)) 36.1106 +;; ([coefficient variables] 36.1107 +;; (list 36.1108 +;; (DifferentialTerm. coefficient (apply sorted-set variables)))) 36.1109 +;; ([coefficient variables & cvs] 36.1110 +;; (sort-by 36.1111 +;; #(vec(.variables %)) 36.1112 +;; (concat (differential-seq coefficient variables) (apply differential-seq cvs))))) 36.1113 + 36.1114 +#+end_src 36.1115 + 36.1116 + 36.1117 + 36.1118 + 36.1119 + 36.1120 + 36.1121 + 36.1122 + 36.1123 + 36.1124 + 36.1125 + 36.1126 + 36.1127 + 36.1128 +* Symbolic Manipulation 36.1129 + 36.1130 +#+srcname:symbolic 36.1131 +#+begin_src clojure 36.1132 +(in-ns 'sicm.utils) 36.1133 + 36.1134 +(deftype Symbolic [type expression] 36.1135 + Object 36.1136 + (equals [this that] 36.1137 + (cond 36.1138 + (= (.expression this) (.expression that)) true 36.1139 + :else 36.1140 + (Symbolic. 36.1141 + java.lang.Boolean 36.1142 + (list '= (.expression this) (.expression that))) 36.1143 + ))) 36.1144 + 36.1145 + 36.1146 + 36.1147 + 36.1148 +(deftype AbstractSet [glyph membership-test]) 36.1149 +(defn member? [abstract-set x] 36.1150 + ((.membership-test abstract-set) x)) 36.1151 + 36.1152 +;; ------------ Some important AbstractSets 36.1153 + 36.1154 + 36.1155 +(def Real 36.1156 + (AbstractSet. 36.1157 + 'R 36.1158 + (fn[x](number? x)))) 36.1159 + 36.1160 + 36.1161 +;; ------------ Create new AbstractSets from existing ones 36.1162 + 36.1163 +(defn abstract-product 36.1164 + "Gives the cartesian product of abstract sets." 36.1165 + ([sets] 36.1166 + (if (= (count sets) 1) (first sets) 36.1167 + (AbstractSet. 36.1168 + (symbol 36.1169 + (apply str 36.1170 + (interpose 'x (map #(.glyph %) sets)))) 36.1171 + (fn [x] 36.1172 + (and 36.1173 + (coll? x) 36.1174 + (= (count sets) (count x)) 36.1175 + (reduce #(and %1 %2) 36.1176 + true 36.1177 + (map #(member? %1 %2) sets x))))))) 36.1178 + ([abstract-set n] 36.1179 + (abstract-product (repeat n abstract-set)))) 36.1180 + 36.1181 + 36.1182 + 36.1183 +(defn abstract-up 36.1184 + "Returns the abstract set of all up-tuples whose items belong to the 36.1185 + corresponding abstract sets in coll." 36.1186 + ([coll] 36.1187 + (AbstractSet. 36.1188 + (symbol (str "u[" 36.1189 + (apply str 36.1190 + (interpose " " 36.1191 + (map #(.glyph %) coll))) 36.1192 + "]")) 36.1193 + (fn [x] 36.1194 + (and 36.1195 + (satisfies? Spinning x) 36.1196 + (up? x) 36.1197 + (= (count coll) (count x)) 36.1198 + (reduce 36.1199 + #(and %1 %2) 36.1200 + true 36.1201 + (map #(member? %1 %2) coll x)))))) 36.1202 + ([abstract-set n] 36.1203 + (abstract-up (repeat n abstract-set)))) 36.1204 + 36.1205 + 36.1206 +(defn abstract-down 36.1207 + "Returns the abstract set of all down-tuples whose items belong to the 36.1208 + corresponding abstract sets in coll." 36.1209 + ([coll] 36.1210 + (AbstractSet. 36.1211 + (symbol (str "d[" 36.1212 + (apply str 36.1213 + (interpose " " 36.1214 + (map #(.glyph %) coll))) 36.1215 + "]")) 36.1216 + (fn [x] 36.1217 + (and 36.1218 + (satisfies? Spinning x) 36.1219 + (down? x) 36.1220 + (= (count coll) (count x)) 36.1221 + (reduce 36.1222 + #(and %1 %2) 36.1223 + true 36.1224 + (map #(member? %1 %2) coll x)))))) 36.1225 + ([abstract-set n] 36.1226 + (abstract-down (repeat n abstract-set)))) 36.1227 + 36.1228 + 36.1229 + 36.1230 + 36.1231 + 36.1232 + ;-------ABSTRACT FUNCTIONS 36.1233 +(defrecord AbstractFn 36.1234 + [#^AbstractSet domain #^AbstractSet codomain]) 36.1235 + 36.1236 + 36.1237 +(defmethod print-method AbstractFn 36.1238 + [o w] 36.1239 + (print-simple 36.1240 + (str 36.1241 + "f:" 36.1242 + (.glyph (:domain o)) 36.1243 + "-->" 36.1244 + (.glyph (:codomain o))) w)) 36.1245 +#+end_src 36.1246 + 36.1247 + 36.1248 +* COMMENT 36.1249 +#+begin_src clojure :tangle utils.clj 36.1250 +(ns sicm.utils) 36.1251 + 36.1252 + ;***** GENERIC ARITHMETIC 36.1253 +<<generic-arithmetic>> 36.1254 + 36.1255 + 36.1256 + ;***** TUPLES AND MATRICES 36.1257 +<<tuples>> 36.1258 +<<tuples-2>> 36.1259 + ;***** MATRICES 36.1260 +<<matrices>> 36.1261 + 36.1262 +#+end_src 36.1263 + 36.1264 + 36.1265 +
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/sicm/deriv.html Fri Oct 28 00:03:05 2011 -0700 37.3 @@ -0,0 +1,240 @@ 37.4 +<?xml version="1.0" encoding="utf-8"?> 37.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 37.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 37.7 +<html xmlns="http://www.w3.org/1999/xhtml" 37.8 +lang="en" xml:lang="en"> 37.9 +<head> 37.10 +<title>An Unambiguous Notation for Derivatives</title> 37.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 37.12 +<meta name="generator" content="Org-mode"/> 37.13 +<meta name="generated" content="2011-08-08 02:49:24 EDT"/> 37.14 +<meta name="author" content="Dylan Holmes"/> 37.15 +<meta name="description" content=""/> 37.16 +<meta name="keywords" content=""/> 37.17 +<style type="text/css"> 37.18 + <!--/*--><![CDATA[/*><!--*/ 37.19 + html { font-family: Times, serif; font-size: 12pt; } 37.20 + .title { text-align: center; } 37.21 + .todo { color: red; } 37.22 + .done { color: green; } 37.23 + .tag { background-color: #add8e6; font-weight:normal } 37.24 + .target { } 37.25 + .timestamp { color: #bebebe; } 37.26 + .timestamp-kwd { color: #5f9ea0; } 37.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 37.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 37.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 37.30 + p.verse { margin-left: 3% } 37.31 + pre { 37.32 + border: 1pt solid #AEBDCC; 37.33 + background-color: #F3F5F7; 37.34 + padding: 5pt; 37.35 + font-family: courier, monospace; 37.36 + font-size: 90%; 37.37 + overflow:auto; 37.38 + } 37.39 + table { border-collapse: collapse; } 37.40 + td, th { vertical-align: top; } 37.41 + th.right { text-align:center; } 37.42 + th.left { text-align:center; } 37.43 + th.center { text-align:center; } 37.44 + td.right { text-align:right; } 37.45 + td.left { text-align:left; } 37.46 + td.center { text-align:center; } 37.47 + dt { font-weight: bold; } 37.48 + div.figure { padding: 0.5em; } 37.49 + div.figure p { text-align: center; } 37.50 + textarea { overflow-x: auto; } 37.51 + .linenr { font-size:smaller } 37.52 + .code-highlighted {background-color:#ffff00;} 37.53 + .org-info-js_info-navigation { border-style:none; } 37.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 37.55 + white-space:nowrap; } 37.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 37.57 + font-weight:bold; } 37.58 + /*]]>*/--> 37.59 +</style> 37.60 +<link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 37.61 +<script type="text/javascript"> 37.62 +<!--/*--><![CDATA[/*><!--*/ 37.63 + function CodeHighlightOn(elem, id) 37.64 + { 37.65 + var target = document.getElementById(id); 37.66 + if(null != target) { 37.67 + elem.cacheClassElem = elem.className; 37.68 + elem.cacheClassTarget = target.className; 37.69 + target.className = "code-highlighted"; 37.70 + elem.className = "code-highlighted"; 37.71 + } 37.72 + } 37.73 + function CodeHighlightOff(elem, id) 37.74 + { 37.75 + var target = document.getElementById(id); 37.76 + if(elem.cacheClassElem) 37.77 + elem.className = elem.cacheClassElem; 37.78 + if(elem.cacheClassTarget) 37.79 + target.className = elem.cacheClassTarget; 37.80 + } 37.81 +/*]]>*///--> 37.82 +</script> 37.83 +<script type="text/javascript" src="../MathJax/MathJax.js"> 37.84 +<!--/*--><![CDATA[/*><!--*/ 37.85 + MathJax.Hub.Config({ 37.86 + // Only one of the two following lines, depending on user settings 37.87 + // First allows browser-native MathML display, second forces HTML/CSS 37.88 + config: ["MMLorHTML.js"], jax: ["input/TeX"], 37.89 + // jax: ["input/TeX", "output/HTML-CSS"], 37.90 + extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js", 37.91 + "TeX/noUndefined.js"], 37.92 + tex2jax: { 37.93 + inlineMath: [ ["\\(","\\)"] ], 37.94 + displayMath: [ ['$$','$$'], ["\\[","\\]"], ["\\begin{displaymath}","\\end{displaymath}"] ], 37.95 + skipTags: ["script","noscript","style","textarea","pre","code"], 37.96 + ignoreClass: "tex2jax_ignore", 37.97 + processEscapes: false, 37.98 + processEnvironments: true, 37.99 + preview: "TeX" 37.100 + }, 37.101 + showProcessingMessages: true, 37.102 + displayAlign: "left", 37.103 + displayIndent: "2em", 37.104 + 37.105 + "HTML-CSS": { 37.106 + scale: 100, 37.107 + availableFonts: ["STIX","TeX"], 37.108 + preferredFont: "TeX", 37.109 + webFont: "TeX", 37.110 + imageFont: "TeX", 37.111 + showMathMenu: true, 37.112 + }, 37.113 + MMLorHTML: { 37.114 + prefer: { 37.115 + MSIE: "MML", 37.116 + Firefox: "MML", 37.117 + Opera: "HTML", 37.118 + other: "HTML" 37.119 + } 37.120 + } 37.121 + }); 37.122 +/*]]>*///--> 37.123 +</script> 37.124 +</head> 37.125 +<body> 37.126 + 37.127 +<div id="content"> 37.128 + 37.129 + 37.130 + 37.131 +<div class="header"> 37.132 + <div class="float-right"> 37.133 + <!-- 37.134 + <form> 37.135 + <input type="text"/><input type="submit" value="search the blog »"/> 37.136 + </form> 37.137 + --> 37.138 + </div> 37.139 + 37.140 + <h1>aurellem <em>☉</em></h1> 37.141 + <ul class="nav"> 37.142 + <li><a href="/">read the blog »</a></li> 37.143 + <!-- li><a href="#">learn about us »</a></li--> 37.144 + </ul> 37.145 +</div> 37.146 + 37.147 +<h1 class="title">An Unambiguous Notation for Derivatives</h1> 37.148 + 37.149 + 37.150 + 37.151 + 37.152 + 37.153 + 37.154 + 37.155 +<div id="table-of-contents"> 37.156 +<h2>Table of Contents</h2> 37.157 +<div id="text-table-of-contents"> 37.158 +<ul> 37.159 +<li><a href="#sec-1">1 Calculus of Infinitesimals </a> 37.160 +<ul> 37.161 +<li><a href="#sec-1-1">1.1 Differential Objects </a></li> 37.162 +<li><a href="#sec-1-2">1.2 Interactions obey the chain rule </a></li> 37.163 +</ul> 37.164 +</li> 37.165 +</ul> 37.166 +</div> 37.167 +</div> 37.168 + 37.169 +<div id="outline-container-1" class="outline-2"> 37.170 +<h2 id="sec-1"><span class="section-number-2">1</span> Calculus of Infinitesimals </h2> 37.171 +<div class="outline-text-2" id="text-1"> 37.172 + 37.173 + 37.174 +</div> 37.175 + 37.176 +<div id="outline-container-1-1" class="outline-3"> 37.177 +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> Differential Objects </h3> 37.178 +<div class="outline-text-3" id="text-1-1"> 37.179 + 37.180 + 37.181 +<p> 37.182 +A <b>differential object</b> is a pair \([x,\,dx]\) consisting of a variable 37.183 +and an infinitely small increment of it. Differential objects can 37.184 +interact with functions, producing a new differential object as a 37.185 +result; this interaction is for calculating derivatives of functions. 37.186 +</p> 37.187 +<p> 37.188 +Differential objects are for 37.189 +calculating derivatives of functions: the derivative of \(f\) with 37.190 +respect to \(x\) 37.191 +</p> 37.192 +<p> 37.193 +You can “apply” 37.194 +functions to differential objects; the result is: 37.195 +</p> 37.196 + 37.197 + 37.198 +\([x,dx]\xrightarrow{\quad f \quad}[f(x), Df(x)\cdot dx].\) 37.199 + 37.200 +<p> 37.201 +Loosely speaking, the interaction of \(f\) and a differential object 37.202 +of \(x\) is a differential object of \(f\). 37.203 +</p> 37.204 + 37.205 +</div> 37.206 + 37.207 +</div> 37.208 + 37.209 +<div id="outline-container-1-2" class="outline-3"> 37.210 +<h3 id="sec-1-2"><span class="section-number-3">1.2</span> Interactions obey the chain rule </h3> 37.211 +<div class="outline-text-3" id="text-1-2"> 37.212 + 37.213 + 37.214 +<p> 37.215 +The interaction of \(f\) and the differential object \([x, dx]\) is 37.216 +a differential object \([f(x), Df(x)\cdot dx]\). Because of the rule for 37.217 +interactions, if you apply another function \(g\), you get the 37.218 +chain-rule answer you expect: 37.219 +</p> 37.220 + 37.221 + 37.222 +\([f(x), Df(x)\cdot dx]\xrightarrow{\quad g\quad}\left[g(f(x)),\, 37.223 +Dg(f(x))\cdot Df(x)\cdot dx\right]\) 37.224 + 37.225 + 37.226 + 37.227 + 37.228 + 37.229 + 37.230 + 37.231 + 37.232 +</div> 37.233 +</div> 37.234 +</div> 37.235 +<div id="postamble"> 37.236 +<p class="date">Date: 2011-08-08 02:49:24 EDT</p> 37.237 +<p class="author">Author: Dylan Holmes</p> 37.238 +<p class="creator">Org version 7.6 with Emacs version 23</p> 37.239 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 37.240 +</div> 37.241 +</div> 37.242 +</body> 37.243 +</html>
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/sicm/deriv.org Fri Oct 28 00:03:05 2011 -0700 38.3 @@ -0,0 +1,53 @@ 38.4 +#+TITLE:An Unambiguous Notation for Derivatives 38.5 +#+author: Dylan Holmes 38.6 +#+EMAIL: rlm@mit.edu 38.7 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js" 38.8 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 38.9 +#+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 38.10 +#+SETUPFILE: ../templates/level-0.org 38.11 +#+INCLUDE: ../templates/level-0.org 38.12 +#+BABEL: :noweb yes 38.13 + 38.14 +* Calculus of Infinitesimals 38.15 +** Differential Objects 38.16 + 38.17 +A *differential object* is a pair $[x,\,dx]$ consisting of a variable 38.18 +and an infinitely small increment of it. We want differential objects 38.19 +to enable us to compute derivatives of functions. 38.20 + 38.21 +Differential objects are for 38.22 +calculating derivatives of functions: the derivative of $f$ with 38.23 +respect to $x$ 38.24 + 38.25 +You can \ldquo{}apply\rdquo{} 38.26 +functions to differential objects; the result is: 38.27 + 38.28 +\([x,dx]\xrightarrow{\quad f \quad}[f(x), Df(x)\cdot dx].\) 38.29 + 38.30 +Loosely speaking, the interaction of $f$ and a differential object 38.31 +of $x$ is a differential object of $f$. 38.32 + 38.33 +#As a linguistic convention, we'll call this interaction /applying f 38.34 +#to the differential object/. This is not to be confused with the 38.35 +#=apply= function in Clojure. 38.36 + 38.37 +** Interactions obey the chain rule 38.38 + 38.39 +The interaction of $f$ and the differential object $[x, dx]$ is 38.40 +a differential object $[f(x), Df(x)\cdot dx]$. Because of the rule for 38.41 +interactions, if you apply another function $g$, you get the 38.42 +chain-rule answer you expect: 38.43 + 38.44 +\([f(x), Df(x)\cdot dx]\xrightarrow{\quad g\quad}\left[g(f(x)),\, 38.45 +Dg(f(x))\cdot Df(x)\cdot dx\right]\) 38.46 + 38.47 + 38.48 +#+begin_src clojure :tangle deriv.clj 38.49 + 38.50 +#+end_src 38.51 + 38.52 +#+results: 38.53 +: nil 38.54 + 38.55 + 38.56 +
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/sicm/notes.html Fri Oct 28 00:03:05 2011 -0700 39.3 @@ -0,0 +1,141 @@ 39.4 +<?xml version="1.0" encoding="utf-8"?> 39.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 39.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 39.7 +<html xmlns="http://www.w3.org/1999/xhtml" 39.8 +lang="en" xml:lang="en"> 39.9 +<head> 39.10 +<title>Notes for SICM</title> 39.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 39.12 +<meta name="generator" content="Org-mode"/> 39.13 +<meta name="generated" content="2011-08-10 14:07:53 EDT"/> 39.14 +<meta name="author" content="Robert McIntyre"/> 39.15 +<meta name="description" content=""/> 39.16 +<meta name="keywords" content=""/> 39.17 +<style type="text/css"> 39.18 + <!--/*--><![CDATA[/*><!--*/ 39.19 + html { font-family: Times, serif; font-size: 12pt; } 39.20 + .title { text-align: center; } 39.21 + .todo { color: red; } 39.22 + .done { color: green; } 39.23 + .tag { background-color: #add8e6; font-weight:normal } 39.24 + .target { } 39.25 + .timestamp { color: #bebebe; } 39.26 + .timestamp-kwd { color: #5f9ea0; } 39.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 39.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 39.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 39.30 + p.verse { margin-left: 3% } 39.31 + pre { 39.32 + border: 1pt solid #AEBDCC; 39.33 + background-color: #F3F5F7; 39.34 + padding: 5pt; 39.35 + font-family: courier, monospace; 39.36 + font-size: 90%; 39.37 + overflow:auto; 39.38 + } 39.39 + table { border-collapse: collapse; } 39.40 + td, th { vertical-align: top; } 39.41 + th.right { text-align:center; } 39.42 + th.left { text-align:center; } 39.43 + th.center { text-align:center; } 39.44 + td.right { text-align:right; } 39.45 + td.left { text-align:left; } 39.46 + td.center { text-align:center; } 39.47 + dt { font-weight: bold; } 39.48 + div.figure { padding: 0.5em; } 39.49 + div.figure p { text-align: center; } 39.50 + textarea { overflow-x: auto; } 39.51 + .linenr { font-size:smaller } 39.52 + .code-highlighted {background-color:#ffff00;} 39.53 + .org-info-js_info-navigation { border-style:none; } 39.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 39.55 + white-space:nowrap; } 39.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 39.57 + font-weight:bold; } 39.58 + /*]]>*/--> 39.59 +</style> 39.60 +<script type="text/javascript"> 39.61 +<!--/*--><![CDATA[/*><!--*/ 39.62 + function CodeHighlightOn(elem, id) 39.63 + { 39.64 + var target = document.getElementById(id); 39.65 + if(null != target) { 39.66 + elem.cacheClassElem = elem.className; 39.67 + elem.cacheClassTarget = target.className; 39.68 + target.className = "code-highlighted"; 39.69 + elem.className = "code-highlighted"; 39.70 + } 39.71 + } 39.72 + function CodeHighlightOff(elem, id) 39.73 + { 39.74 + var target = document.getElementById(id); 39.75 + if(elem.cacheClassElem) 39.76 + elem.className = elem.cacheClassElem; 39.77 + if(elem.cacheClassTarget) 39.78 + target.className = elem.cacheClassTarget; 39.79 + } 39.80 +/*]]>*///--> 39.81 +</script> 39.82 + 39.83 +</head> 39.84 +<body> 39.85 + 39.86 +<div id="content"> 39.87 + 39.88 + 39.89 + 39.90 +<div id="table-of-contents"> 39.91 +<h2>Table of Contents</h2> 39.92 +<div id="text-table-of-contents"> 39.93 +<ul> 39.94 +<li><a href="#sec-1">1 Tuples </a></li> 39.95 +<li><a href="#sec-2">2 Generic arithmetic </a></li> 39.96 +</ul> 39.97 +</div> 39.98 +</div> 39.99 + 39.100 +<div id="outline-container-1" class="outline-2"> 39.101 +<h2 id="sec-1"><span class="section-number-2">1</span> Tuples </h2> 39.102 +<div class="outline-text-2" id="text-1"> 39.103 + 39.104 +<ul> 39.105 +<li>Tuples are a new data type: sequences with <i>spin</i>. A tuple can be either spin-up or spin-down. 39.106 +</li> 39.107 +<li>A pair of compatible tuples can be <b>contracted</b> into a single number. 39.108 +<ul> 39.109 +<li>Tuples are compatible if they have the same length and opposite 39.110 + spin, and if their corresponding pairs of items are either both 39.111 + numbers or both compatible tuples. 39.112 +</li> 39.113 +<li>To contract tuples, take the sum of the products of corresponding 39.114 + pairs of items. (To take the product of compatible tuples, 39.115 + contract them.) 39.116 +</li> 39.117 +</ul> 39.118 + 39.119 +</li> 39.120 +<li> 39.121 +</li> 39.122 +</ul> 39.123 + 39.124 + 39.125 +</div> 39.126 + 39.127 +</div> 39.128 + 39.129 +<div id="outline-container-2" class="outline-2"> 39.130 +<h2 id="sec-2"><span class="section-number-2">2</span> Generic arithmetic </h2> 39.131 +<div class="outline-text-2" id="text-2"> 39.132 + 39.133 + 39.134 +</div> 39.135 +</div> 39.136 +<div id="postamble"> 39.137 +<p class="date">Date: 2011-08-10 14:07:53 EDT</p> 39.138 +<p class="author">Author: Robert McIntyre</p> 39.139 +<p class="creator">Org version 7.6 with Emacs version 23</p> 39.140 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 39.141 +</div> 39.142 +</div> 39.143 +</body> 39.144 +</html>
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/sicm/notes.org Fri Oct 28 00:03:05 2011 -0700 40.3 @@ -0,0 +1,25 @@ 40.4 +#+TITLE: Notes for SICM 40.5 + 40.6 +* Complex numbers 40.7 + 40.8 + 40.9 +* Multidimensional Structures 40.10 +** Tuples 40.11 +- Tuples are a new data type: sequences with /spin/. A tuple can be either spin-up or spin-down. 40.12 +- A pair of compatible tuples can be *contracted* into a single number. 40.13 + - Tuples are compatible if they have the same length and opposite 40.14 + spin, and if their corresponding pairs of items are either both 40.15 + numbers or both compatible tuples. 40.16 + - To contract tuples, take the sum of the products of corresponding 40.17 + pairs of items. (To take the product of compatible tuples, 40.18 + contract them.) 40.19 + 40.20 +*Generic Arithmetic:* To multiply two tuples, check to see if they are 40.21 + compatible. If they are, contract them. If they aren't, multiply each 40.22 + item of the second tuple by the first tuple. 40.23 + 40.24 +To multiply a tuple by a number, multiply each element of the tuple by 40.25 +the number. 40.26 + 40.27 +** Matrices 40.28 +Uses incanter matrices.
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/sicm/utils.clj Fri Oct 28 00:03:05 2011 -0700 41.3 @@ -0,0 +1,496 @@ 41.4 + 41.5 +(ns sicm.utils) 41.6 + 41.7 +(in-ns 'sicm.utils) 41.8 + 41.9 +;; Let some objects have spin 41.10 + 41.11 +(defprotocol Spinning 41.12 + (up? [this]) 41.13 + (down? [this])) 41.14 + 41.15 +(defn spin 41.16 + "Returns the spin of the Spinning s, either :up or :down" 41.17 + [#^Spinning s] 41.18 + (cond (up? s) :up (down? s) :down)) 41.19 + 41.20 + 41.21 +;; DEFINITION: A tuple is a sequence with spin 41.22 + 41.23 +(deftype Tuple 41.24 + [spin coll] 41.25 + 41.26 + clojure.lang.Seqable 41.27 + (seq [this] (seq (.coll this))) 41.28 + 41.29 + clojure.lang.Counted 41.30 + (count [this] (count (.coll this))) 41.31 + 41.32 + Spinning 41.33 + (up? [this] (= ::up (.spin this))) 41.34 + (down? [this] (= ::down (.spin this)))) 41.35 + 41.36 +(defmethod print-method Tuple 41.37 + [o w] 41.38 + (print-simple 41.39 + (if (up? o) 41.40 + (str "u" (.coll o)) 41.41 + (str "d" (vec(.coll o)))) 41.42 + w)) 41.43 + 41.44 +(def tuple? #(= (type %) Tuple)) 41.45 + 41.46 +;; CONSTRUCTORS 41.47 + 41.48 +(defn up 41.49 + "Create a new up-tuple containing the contents of coll." 41.50 + [coll] 41.51 + (Tuple. ::up coll)) 41.52 + 41.53 +(defn down 41.54 + "Create a new down-tuple containing the contents of coll." 41.55 + [coll] 41.56 + (Tuple. ::down coll)) 41.57 + 41.58 +(defn same-spin 41.59 + "Creates a tuple which has the same spin as tuple and which contains 41.60 +the contents of coll." 41.61 + [tuple coll] 41.62 + (if (up? tuple) 41.63 + (up coll) 41.64 + (down coll))) 41.65 + 41.66 +(defn opposite-spin 41.67 + "Create a tuple which has opposite spin to tuple and which contains 41.68 +the contents of coll." 41.69 + [tuple coll] 41.70 + (if (up? tuple) 41.71 + (down coll) 41.72 + (up coll))) 41.73 +(in-ns 'sicm.utils) 41.74 +(require 'incanter.core) ;; use incanter's fast matrices 41.75 + 41.76 + 41.77 +(defn all-equal? [coll] 41.78 + (if (empty? (rest coll)) true 41.79 + (and (= (first coll) (second coll)) 41.80 + (recur (rest coll))))) 41.81 + 41.82 + 41.83 +(defprotocol Matrix 41.84 + (rows [matrix]) 41.85 + (cols [matrix]) 41.86 + (diagonal [matrix]) 41.87 + (trace [matrix]) 41.88 + (determinant [matrix]) 41.89 + (transpose [matrix]) 41.90 + (conjugate [matrix]) 41.91 +) 41.92 + 41.93 +(extend-protocol Matrix incanter.Matrix 41.94 + (rows [rs] (map down (apply map vector (apply map vector rs)))) 41.95 + (cols [rs] (map up (apply map vector rs))) 41.96 + (diagonal [matrix] (incanter.core/diag matrix) ) 41.97 + (determinant [matrix] (incanter.core/det matrix)) 41.98 + (trace [matrix] (incanter.core/trace matrix)) 41.99 + (transpose [matrix] (incanter.core/trans matrix))) 41.100 + 41.101 +(defn count-rows [matrix] 41.102 + ((comp count rows) matrix)) 41.103 + 41.104 +(defn count-cols [matrix] 41.105 + ((comp count cols) matrix)) 41.106 + 41.107 +(defn square? [matrix] 41.108 + (= (count-rows matrix) (count-cols matrix))) 41.109 + 41.110 +(defn identity-matrix 41.111 + "Define a square matrix of size n-by-n with 1s along the diagonal and 41.112 + 0s everywhere else." 41.113 + [n] 41.114 + (incanter.core/identity-matrix n)) 41.115 + 41.116 + 41.117 +(defn matrix-by-rows 41.118 + "Define a matrix by giving its rows." 41.119 + [& rows] 41.120 + (if 41.121 + (not (all-equal? (map count rows))) 41.122 + (throw (Exception. "All rows in a matrix must have the same number of elements.")) 41.123 + (incanter.core/matrix (vec rows)))) 41.124 + 41.125 +(defn matrix-by-cols 41.126 + "Define a matrix by giving its columns" 41.127 + [& cols] 41.128 + (if (not (all-equal? (map count cols))) 41.129 + (throw (Exception. "All columns in a matrix must have the same number of elements.")) 41.130 + (incanter.core/matrix (vec (apply map vector cols))))) 41.131 + 41.132 +(defn identity-matrix 41.133 + "Define a square matrix of size n-by-n with 1s along the diagonal and 41.134 + 0s everywhere else." 41.135 + [n] 41.136 + (incanter.core/identity-matrix n)) 41.137 + 41.138 +(in-ns 'sicm.utils) 41.139 +(use 'clojure.contrib.generic.arithmetic 41.140 + 'clojure.contrib.generic.collection 41.141 + 'clojure.contrib.generic.functor 41.142 + 'clojure.contrib.generic.math-functions) 41.143 + 41.144 +(defn numbers? 41.145 + "Returns true if all arguments are numbers, else false." 41.146 + [& xs] 41.147 + (every? number? xs)) 41.148 + 41.149 +(defn tuple-surgery 41.150 + "Applies the function f to the items of tuple and the additional 41.151 + arguments, if any. Returns a Tuple of the same type as tuple." 41.152 + [tuple f & xs] 41.153 + ((if (up? tuple) up down) 41.154 + (apply f (seq tuple) xs))) 41.155 + 41.156 + 41.157 + 41.158 +;;; CONTRACTION collapses two compatible tuples into a number. 41.159 + 41.160 +(defn contractible? 41.161 + "Returns true if the tuples a and b are compatible for contraction, 41.162 + else false. Tuples are compatible if they have the same number of 41.163 + components, they have opposite spins, and their elements are 41.164 + pairwise-compatible." 41.165 + [a b] 41.166 + (and 41.167 + (isa? (type a) Tuple) 41.168 + (isa? (type b) Tuple) 41.169 + (= (count a) (count b)) 41.170 + (not= (spin a) (spin b)) 41.171 + 41.172 + (not-any? false? 41.173 + (map #(or 41.174 + (numbers? %1 %2) 41.175 + (contractible? %1 %2)) 41.176 + a b)))) 41.177 + 41.178 +(defn contract 41.179 + "Contracts two tuples, returning the sum of the 41.180 + products of the corresponding items. Contraction is recursive on 41.181 + nested tuples." 41.182 + [a b] 41.183 + (if (not (contractible? a b)) 41.184 + (throw 41.185 + (Exception. "Not compatible for contraction.")) 41.186 + (reduce + 41.187 + (map 41.188 + (fn [x y] 41.189 + (if (numbers? x y) 41.190 + (* x y) 41.191 + (contract x y))) 41.192 + a b)))) 41.193 + 41.194 + 41.195 + 41.196 + 41.197 + 41.198 +(defmethod conj Tuple 41.199 + [tuple & xs] 41.200 + (tuple-surgery tuple #(apply conj % xs))) 41.201 + 41.202 +(defmethod fmap Tuple 41.203 + [f tuple] 41.204 + (tuple-surgery tuple (partial map f))) 41.205 + 41.206 + 41.207 + 41.208 +;; TODO: define Scalar, and add it to the hierarchy above Number and Complex 41.209 + 41.210 + 41.211 +(defmethod * [Tuple Tuple] ; tuple*tuple 41.212 + [a b] 41.213 + (if (contractible? a b) 41.214 + (contract a b) 41.215 + (map (partial * a) b))) 41.216 + 41.217 + 41.218 +(defmethod * [java.lang.Number Tuple] ;; scalar * tuple 41.219 + [a x] (fmap (partial * a) x)) 41.220 + 41.221 +(defmethod * [Tuple java.lang.Number] 41.222 + [x a] (* a x)) 41.223 + 41.224 +(defmethod * [java.lang.Number incanter.Matrix] ;; scalar * matrix 41.225 + [x M] (incanter.core/mult x M)) 41.226 + 41.227 +(defmethod * [incanter.Matrix java.lang.Number] 41.228 + [M x] (* x M)) 41.229 + 41.230 +(defmethod * [incanter.Matrix incanter.Matrix] ;; matrix * matrix 41.231 + [M1 M2] 41.232 + (incanter.core/mmult M1 M2)) 41.233 + 41.234 +(defmethod * [incanter.Matrix Tuple] ;; matrix * tuple 41.235 + [M v] 41.236 + (if (and (apply numbers? v) (up? v)) 41.237 + (* M (matrix-by-cols v)) 41.238 + (throw (Exception. "Currently, you can only multiply a matrix by a tuple of *numbers*")) 41.239 + )) 41.240 + 41.241 +(defmethod * [Tuple incanter.Matrix] ;; tuple * Matrix 41.242 + [v M] 41.243 + (if (and (apply numbers? v) (down? v)) 41.244 + (* (matrix-by-rows v) M) 41.245 + (throw (Exception. "Currently, you can only multiply a matrix by a tuple of *numbers*")) 41.246 + )) 41.247 + 41.248 + 41.249 +(defmethod exp incanter.Matrix 41.250 + [M] 41.251 + (incanter.core/exp M)) 41.252 + 41.253 + 41.254 +(in-ns 'sicm.utils) 41.255 +(use 'clojure.contrib.seq 41.256 + 'clojure.contrib.generic.arithmetic 41.257 + 'clojure.contrib.generic.collection 41.258 + 'clojure.contrib.generic.math-functions) 41.259 + 41.260 +;;∂ 41.261 + 41.262 +;; DEFINITION : Differential Term 41.263 + 41.264 +;; A quantity with infinitesimal components, e.g. x, dxdy, 4dydz. The 41.265 +;; coefficient of the quantity is returned by the 'coefficient' method, 41.266 +;; while the sequence of differential parameters is returned by the 41.267 +;; method 'partials'. 41.268 + 41.269 +;; Instead of using (potentially ambiguous) letters to denote 41.270 +;; differential parameters (dx,dy,dz), we use integers. So, dxdz becomes [0 2]. 41.271 + 41.272 +;; The coefficient can be any arithmetic object; the 41.273 +;; partials must be a nonrepeating sorted sequence of nonnegative 41.274 +;; integers. 41.275 + 41.276 +(deftype DifferentialTerm [coefficient partials]) 41.277 + 41.278 +(defn differential-term 41.279 + "Make a differential term from a coefficient and list of partials." 41.280 + [coefficient partials] 41.281 + (if (and (coll? partials) (every? #(and (integer? %) (not(neg? %))) partials)) 41.282 + (DifferentialTerm. coefficient (set partials)) 41.283 + (throw (java.lang.IllegalArgumentException. "Partials must be a collection of integers.")))) 41.284 + 41.285 + 41.286 +;; DEFINITION : Differential Sequence 41.287 +;; A differential sequence is a sequence of differential terms, all with different partials. 41.288 +;; Internally, it is a map from the partials of each term to their coefficients. 41.289 + 41.290 +(deftype DifferentialSeq 41.291 + [terms] 41.292 + ;;clojure.lang.IPersistentMap 41.293 + clojure.lang.Associative 41.294 + (assoc [this key val] 41.295 + (DifferentialSeq. 41.296 + (cons (differential-term val key) terms))) 41.297 + (cons [this x] 41.298 + (DifferentialSeq. (cons x terms))) 41.299 + (containsKey [this key] 41.300 + (not(nil? (find-first #(= (.partials %) key) terms)))) 41.301 + (count [this] (count (.terms this))) 41.302 + (empty [this] (DifferentialSeq. [])) 41.303 + (entryAt [this key] 41.304 + ((juxt #(.partials %) #(.coefficient %)) 41.305 + (find-first #(= (.partials %) key) terms))) 41.306 + (seq [this] (seq (.terms this)))) 41.307 + 41.308 +(def differential? #(= (type %) DifferentialSeq)) 41.309 + 41.310 +(defn zeroth-order? 41.311 + "Returns true if the differential sequence has at most a constant term." 41.312 + [dseq] 41.313 + (and 41.314 + (differential? dseq) 41.315 + (every? 41.316 + #(= #{} %) 41.317 + (keys (.terms dseq))))) 41.318 + 41.319 +(defmethod fmap DifferentialSeq 41.320 + [f dseq] 41.321 + (DifferentialSeq. 41.322 + (fmap f (.terms dseq)))) 41.323 + 41.324 + 41.325 + 41.326 + 41.327 +;; BUILDING DIFFERENTIAL OBJECTS 41.328 + 41.329 +(defn differential-seq 41.330 + "Define a differential sequence by specifying an alternating 41.331 +sequence of coefficients and lists of partials." 41.332 + ([coefficient partials] 41.333 + (DifferentialSeq. {(set partials) coefficient})) 41.334 + ([coefficient partials & cps] 41.335 + (if (odd? (count cps)) 41.336 + (throw (Exception. "differential-seq requires an even number of terms.")) 41.337 + (DifferentialSeq. 41.338 + (reduce 41.339 + #(assoc %1 (set (second %2)) (first %2)) 41.340 + {(set partials) coefficient} 41.341 + (partition 2 cps)))))) 41.342 + 41.343 + 41.344 + 41.345 +(defn big-part 41.346 + "Returns the part of the differential sequence that is finite, 41.347 + i.e. not infinitely small. If the sequence is zeroth-order, returns 41.348 + the coefficient of the zeroth-order term instead. " 41.349 + [dseq] 41.350 + (if (zeroth-order? dseq) (get (.terms dseq) #{}) 41.351 + (let [m (.terms dseq) 41.352 + keys (sort-by count (keys m)) 41.353 + smallest-var (last (last keys))] 41.354 + (DifferentialSeq. 41.355 + (reduce 41.356 + #(assoc %1 (first %2) (second %2)) 41.357 + {} 41.358 + (remove #((first %) smallest-var) m)))))) 41.359 + 41.360 + 41.361 +(defn small-part 41.362 + "Returns the part of the differential sequence that infinitely 41.363 + small. If the sequence is zeroth-order, returns zero." 41.364 + [dseq] 41.365 + (if (zeroth-order? dseq) 0 41.366 + (let [m (.terms dseq) 41.367 + keys (sort-by count (keys m)) 41.368 + smallest-var (last (last keys))] 41.369 + (DifferentialSeq. 41.370 + (reduce 41.371 + #(assoc %1 (first %2) (second %2)) {} 41.372 + (filter #((first %) smallest-var) m)))))) 41.373 + 41.374 + 41.375 + 41.376 +(defn cartesian-product [set1 set2] 41.377 + (reduce concat 41.378 + (for [x set1] 41.379 + (for [y set2] 41.380 + [x y])))) 41.381 + 41.382 +(defn nth-subset [n] 41.383 + (if (zero? n) [] 41.384 + (let [lg2 #(/ (log %) (log 2)) 41.385 + k (int(java.lang.Math/floor (lg2 n))) 41.386 + ] 41.387 + (cons k 41.388 + (nth-subset (- n (pow 2 k))))))) 41.389 + 41.390 +(def all-partials 41.391 + (lazy-seq (map nth-subset (range)))) 41.392 + 41.393 + 41.394 +(defn differential-multiply 41.395 + "Multiply two differential sequences. The square of any differential 41.396 + variable is zero since differential variables are infinitesimally 41.397 + small." 41.398 + [dseq1 dseq2] 41.399 + (DifferentialSeq. 41.400 + (reduce 41.401 + (fn [m [[vars1 coeff1] [vars2 coeff2]]] 41.402 + (if (not (empty? (clojure.set/intersection vars1 vars2))) 41.403 + m 41.404 + (assoc m (clojure.set/union vars1 vars2) (* coeff1 coeff2)))) 41.405 + {} 41.406 + (cartesian-product (.terms dseq1) (.terms dseq2))))) 41.407 + 41.408 + 41.409 + 41.410 +(defmethod * [DifferentialSeq DifferentialSeq] 41.411 + [dseq1 dseq2] 41.412 + (differential-multiply dseq1 dseq2)) 41.413 + 41.414 +(defmethod + [DifferentialSeq DifferentialSeq] 41.415 + [dseq1 dseq2] 41.416 + (DifferentialSeq. 41.417 + (merge-with + (.terms dseq1) (.terms dseq2)))) 41.418 + 41.419 +(defmethod * [java.lang.Number DifferentialSeq] 41.420 + [x dseq] 41.421 + (fmap (partial * x) dseq)) 41.422 + 41.423 +(defmethod * [DifferentialSeq java.lang.Number] 41.424 + [dseq x] 41.425 + (fmap (partial * x) dseq)) 41.426 + 41.427 +(defmethod + [java.lang.Number DifferentialSeq] 41.428 + [x dseq] 41.429 + (+ (differential-seq x []) dseq)) 41.430 +(defmethod + [DifferentialSeq java.lang.Number] 41.431 + [dseq x] 41.432 + (+ dseq (differential-seq x []))) 41.433 + 41.434 +(defmethod - DifferentialSeq 41.435 + [x] 41.436 + (fmap - x)) 41.437 + 41.438 + 41.439 +;; DERIVATIVES 41.440 + 41.441 + 41.442 + 41.443 +(defn linear-approximator 41.444 + "Returns an operator that linearly approximates the given function." 41.445 + ([f df|dx] 41.446 + (fn [x] 41.447 + (let [big-part (big-part x) 41.448 + small-part (small-part x)] 41.449 + ;; f(x+dx) ~= f(x) + f'(x)dx 41.450 + (+ (f big-part) 41.451 + (* (df|dx big-part) small-part) 41.452 + )))) 41.453 + 41.454 + ([f df|dx df|dy] 41.455 + (fn [x y] 41.456 + (let [X (big-part x) 41.457 + Y (big-part y) 41.458 + DX (small-part x) 41.459 + DY (small-part y)] 41.460 + (+ (f X Y) 41.461 + (* DX (f df|dx X Y)) 41.462 + (* DY (f df|dy X Y))))))) 41.463 + 41.464 + 41.465 + 41.466 + 41.467 + 41.468 +(defn D[f] 41.469 + (fn[x] (f (+ x (differential-seq 1 [0] 1 [1] 1 [2]))))) 41.470 + 41.471 +(defn d[partials f] 41.472 + (fn [x] 41.473 + (get 41.474 + (.terms ((D f)x)) 41.475 + (set partials) 41.476 + 0 41.477 + ))) 41.478 + 41.479 +(defmethod exp DifferentialSeq [x] 41.480 + ((linear-approximator exp exp) x)) 41.481 + 41.482 +(defmethod sin DifferentialSeq 41.483 + [x] 41.484 + ((linear-approximator sin cos) x)) 41.485 + 41.486 +(defmethod cos DifferentialSeq 41.487 + [x] 41.488 + ((linear-approximator cos #(- (sin %))) x)) 41.489 + 41.490 +(defmethod log DifferentialSeq 41.491 + [x] 41.492 + ((linear-approximator log (fn [x] (/ x)) ) x)) 41.493 + 41.494 +(defmethod / [DifferentialSeq DifferentialSeq] 41.495 + [x y] 41.496 + ((linear-approximator / 41.497 + (fn [x y] (/ 1 y)) 41.498 + (fn [x y] (- (/ x (* y y))))) 41.499 + x y))
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/sicm/utils.html Fri Oct 28 00:03:05 2011 -0700 42.3 @@ -0,0 +1,702 @@ 42.4 +<?xml version="1.0" encoding="utf-8"?> 42.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 42.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 42.7 +<html xmlns="http://www.w3.org/1999/xhtml" 42.8 +lang="en" xml:lang="en"> 42.9 +<head> 42.10 +<title>Building a Classical Mechanics Library in Clojure</title> 42.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 42.12 +<meta name="generator" content="Org-mode"/> 42.13 +<meta name="generated" content="2011-08-11 04:10:36 EDT"/> 42.14 +<meta name="author" content="Dylan Holmes"/> 42.15 +<meta name="description" content=""/> 42.16 +<meta name="keywords" content=""/> 42.17 +<style type="text/css"> 42.18 + <!--/*--><![CDATA[/*><!--*/ 42.19 + html { font-family: Times, serif; font-size: 12pt; } 42.20 + .title { text-align: center; } 42.21 + .todo { color: red; } 42.22 + .done { color: green; } 42.23 + .tag { background-color: #add8e6; font-weight:normal } 42.24 + .target { } 42.25 + .timestamp { color: #bebebe; } 42.26 + .timestamp-kwd { color: #5f9ea0; } 42.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 42.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 42.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 42.30 + p.verse { margin-left: 3% } 42.31 + pre { 42.32 + border: 1pt solid #AEBDCC; 42.33 + background-color: #F3F5F7; 42.34 + padding: 5pt; 42.35 + font-family: courier, monospace; 42.36 + font-size: 90%; 42.37 + overflow:auto; 42.38 + } 42.39 + table { border-collapse: collapse; } 42.40 + td, th { vertical-align: top; } 42.41 + th.right { text-align:center; } 42.42 + th.left { text-align:center; } 42.43 + th.center { text-align:center; } 42.44 + td.right { text-align:right; } 42.45 + td.left { text-align:left; } 42.46 + td.center { text-align:center; } 42.47 + dt { font-weight: bold; } 42.48 + div.figure { padding: 0.5em; } 42.49 + div.figure p { text-align: center; } 42.50 + textarea { overflow-x: auto; } 42.51 + .linenr { font-size:smaller } 42.52 + .code-highlighted {background-color:#ffff00;} 42.53 + .org-info-js_info-navigation { border-style:none; } 42.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 42.55 + white-space:nowrap; } 42.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 42.57 + font-weight:bold; } 42.58 + /*]]>*/--> 42.59 +</style> 42.60 +<link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 42.61 +<script type="text/javascript"> 42.62 +<!--/*--><![CDATA[/*><!--*/ 42.63 + function CodeHighlightOn(elem, id) 42.64 + { 42.65 + var target = document.getElementById(id); 42.66 + if(null != target) { 42.67 + elem.cacheClassElem = elem.className; 42.68 + elem.cacheClassTarget = target.className; 42.69 + target.className = "code-highlighted"; 42.70 + elem.className = "code-highlighted"; 42.71 + } 42.72 + } 42.73 + function CodeHighlightOff(elem, id) 42.74 + { 42.75 + var target = document.getElementById(id); 42.76 + if(elem.cacheClassElem) 42.77 + elem.className = elem.cacheClassElem; 42.78 + if(elem.cacheClassTarget) 42.79 + target.className = elem.cacheClassTarget; 42.80 + } 42.81 +/*]]>*///--> 42.82 +</script> 42.83 + 42.84 +</head> 42.85 +<body> 42.86 + 42.87 +<div id="content"> 42.88 + 42.89 + 42.90 + 42.91 +<div class="header"> 42.92 + <div class="float-right"> 42.93 + <!-- 42.94 + <form> 42.95 + <input type="text"/><input type="submit" value="search the blog »"/> 42.96 + </form> 42.97 + --> 42.98 + </div> 42.99 + 42.100 + <h1>aurellem <em>☉</em></h1> 42.101 + <ul class="nav"> 42.102 + <li><a href="/">read the blog »</a></li> 42.103 + <!-- li><a href="#">learn about us »</a></li--> 42.104 + </ul> 42.105 +</div> 42.106 + 42.107 +<h1 class="title">Building a Classical Mechanics Library in Clojure</h1> 42.108 + 42.109 + 42.110 + 42.111 + 42.112 + 42.113 + 42.114 + 42.115 +<div id="table-of-contents"> 42.116 +<h2>Table of Contents</h2> 42.117 +<div id="text-table-of-contents"> 42.118 +<ul> 42.119 +<li><a href="#sec-1">1 Useful data types </a> 42.120 +<ul> 42.121 +<li><a href="#sec-1-1">1.1 Complex numbers </a></li> 42.122 +<li><a href="#sec-1-2">1.2 Power series </a></li> 42.123 +<li><a href="#sec-1-3">1.3 Tuples and tensors </a> 42.124 +<ul> 42.125 +<li><a href="#sec-1-3-1">1.3.1 Tuples are “sequences with spin” </a></li> 42.126 +<li><a href="#sec-1-3-2">1.3.2 Matrices </a></li> 42.127 +</ul> 42.128 +</li> 42.129 +<li><a href="#sec-1-4">1.4 Generic Operations </a></li> 42.130 +</ul> 42.131 +</li> 42.132 +<li><a href="#sec-2">2 Operators and Differentiation </a> 42.133 +<ul> 42.134 +<li><a href="#sec-2-1">2.1 Operators </a></li> 42.135 +<li><a href="#sec-2-2">2.2 Differential Terms and Sequences </a></li> 42.136 +</ul> 42.137 +</li> 42.138 +</ul> 42.139 +</div> 42.140 +</div> 42.141 + 42.142 +<div id="outline-container-1" class="outline-2"> 42.143 +<h2 id="sec-1"><span class="section-number-2">1</span> Useful data types </h2> 42.144 +<div class="outline-text-2" id="text-1"> 42.145 + 42.146 + 42.147 + 42.148 +</div> 42.149 + 42.150 +<div id="outline-container-1-1" class="outline-3"> 42.151 +<h3 id="sec-1-1"><span class="section-number-3">1.1</span> Complex numbers </h3> 42.152 +<div class="outline-text-3" id="text-1-1"> 42.153 + 42.154 + 42.155 +</div> 42.156 + 42.157 +</div> 42.158 + 42.159 +<div id="outline-container-1-2" class="outline-3"> 42.160 +<h3 id="sec-1-2"><span class="section-number-3">1.2</span> Power series </h3> 42.161 +<div class="outline-text-3" id="text-1-2"> 42.162 + 42.163 + 42.164 +</div> 42.165 + 42.166 +</div> 42.167 + 42.168 +<div id="outline-container-1-3" class="outline-3"> 42.169 +<h3 id="sec-1-3"><span class="section-number-3">1.3</span> Tuples and tensors </h3> 42.170 +<div class="outline-text-3" id="text-1-3"> 42.171 + 42.172 + 42.173 + 42.174 +</div> 42.175 + 42.176 +<div id="outline-container-1-3-1" class="outline-4"> 42.177 +<h4 id="sec-1-3-1"><span class="section-number-4">1.3.1</span> Tuples are “sequences with spin” </h4> 42.178 +<div class="outline-text-4" id="text-1-3-1"> 42.179 + 42.180 + 42.181 + 42.182 + 42.183 + 42.184 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 42.185 + 42.186 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">Let some objects have spin</span> 42.187 + 42.188 +(<span style="color: #f0dfaf; font-weight: bold;">defprotocol</span> <span style="color: #f0dfaf;">Spinning</span> 42.189 + (up? [this]) 42.190 + (down? [this])) 42.191 + 42.192 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">spin</span> 42.193 + <span style="color: #8fb28f;">"Returns the spin of the Spinning s, either :up or :down"</span> 42.194 + [<span style="color: #dfdfbf; font-weight: bold;">#^Spinning</span> s] 42.195 + (<span style="color: #f0dfaf; font-weight: bold;">cond</span> (up? s) <span style="color: #8cd0d3;">:up</span> (down? s) <span style="color: #8cd0d3;">:down</span>)) 42.196 + 42.197 + 42.198 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">DEFINITION: A tuple is a sequence with spin</span> 42.199 + 42.200 +(<span style="color: #f0dfaf; font-weight: bold;">deftype</span> <span style="color: #f0dfaf;">Tuple</span> 42.201 + [spin coll] 42.202 + 42.203 + clojure.lang.Seqable 42.204 + (<span style="color: #8cd0d3;">seq</span> [this] (<span style="color: #8cd0d3;">seq</span> (.coll this))) 42.205 + 42.206 + clojure.lang.Counted 42.207 + (<span style="color: #8cd0d3;">count</span> [this] (<span style="color: #8cd0d3;">count</span> (.coll this))) 42.208 + 42.209 + Spinning 42.210 + (up? [this] (<span style="color: #8cd0d3;">=</span> <span style="color: #8cd0d3;">::up</span> (.spin this))) 42.211 + (down? [this] (<span style="color: #8cd0d3;">=</span> <span style="color: #8cd0d3;">::down</span> (.spin this)))) 42.212 + 42.213 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">print-method</span> Tuple 42.214 + [o w] 42.215 + (<span style="color: #8cd0d3;">print-simple</span> 42.216 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (up? o) 42.217 + (<span style="color: #8cd0d3;">str</span> <span style="color: #cc9393;">"u"</span> (.coll o)) 42.218 + (<span style="color: #8cd0d3;">str</span> <span style="color: #cc9393;">"d"</span> (<span style="color: #8cd0d3;">vec</span>(.coll o)))) 42.219 + w)) 42.220 + 42.221 + 42.222 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">CONSTRUCTORS</span> 42.223 + 42.224 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">up</span> 42.225 + <span style="color: #8fb28f;">"Create a new up-tuple containing the contents of coll."</span> 42.226 + [coll] 42.227 + (Tuple. <span style="color: #8cd0d3;">::up</span> coll)) 42.228 + 42.229 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">down</span> 42.230 + <span style="color: #8fb28f;">"Create a new down-tuple containing the contents of coll."</span> 42.231 + [coll] 42.232 + (Tuple. <span style="color: #8cd0d3;">::down</span> coll)) 42.233 +</pre> 42.234 + 42.235 + 42.236 + 42.237 + 42.238 + 42.239 + 42.240 +</div> 42.241 + 42.242 +</div> 42.243 + 42.244 +<div id="outline-container-1-3-2" class="outline-4"> 42.245 +<h4 id="sec-1-3-2"><span class="section-number-4">1.3.2</span> Matrices </h4> 42.246 +<div class="outline-text-4" id="text-1-3-2"> 42.247 + 42.248 + 42.249 + 42.250 + 42.251 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 42.252 +(<span style="color: #8cd0d3;">require</span> 'incanter.core) <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">use incanter's fast matrices</span> 42.253 + 42.254 + 42.255 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">all-equal?</span> [coll] 42.256 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">empty?</span> (<span style="color: #8cd0d3;">rest</span> coll)) true 42.257 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">first</span> coll) (<span style="color: #8cd0d3;">second</span> coll)) 42.258 + (<span style="color: #f0dfaf; font-weight: bold;">recur</span> (<span style="color: #8cd0d3;">rest</span> coll))))) 42.259 + 42.260 + 42.261 +(<span style="color: #f0dfaf; font-weight: bold;">defprotocol</span> <span style="color: #f0dfaf;">Matrix</span> 42.262 + (rows [matrix]) 42.263 + (cols [matrix]) 42.264 + (diagonal [matrix]) 42.265 + (trace [matrix]) 42.266 + (determinant [matrix]) 42.267 + (transpose [matrix]) 42.268 + (conjugate [matrix]) 42.269 +) 42.270 + 42.271 +(<span style="color: #8cd0d3;">extend-protocol</span> Matrix incanter.Matrix 42.272 + (rows [rs] (<span style="color: #8cd0d3;">map</span> down (<span style="color: #8cd0d3;">apply</span> map vector (<span style="color: #8cd0d3;">apply</span> map vector rs)))) 42.273 + (cols [rs] (<span style="color: #8cd0d3;">map</span> up (<span style="color: #8cd0d3;">apply</span> map vector rs))) 42.274 + (diagonal [matrix] (incanter.core/diag matrix) ) 42.275 + (determinant [matrix] (incanter.core/det matrix)) 42.276 + (trace [matrix] (incanter.core/trace matrix)) 42.277 + (transpose [matrix] (incanter.core/trans matrix))) 42.278 + 42.279 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">count-rows</span> [matrix] 42.280 + ((<span style="color: #8cd0d3;">comp</span> count rows) matrix)) 42.281 + 42.282 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">count-cols</span> [matrix] 42.283 + ((<span style="color: #8cd0d3;">comp</span> count cols) matrix)) 42.284 + 42.285 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">square?</span> [matrix] 42.286 + (<span style="color: #8cd0d3;">=</span> (count-rows matrix) (count-cols matrix))) 42.287 + 42.288 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">identity-matrix</span> 42.289 + <span style="color: #8fb28f;">"Define a square matrix of size n-by-n with 1s along the diagonal and</span> 42.290 +<span style="color: #8fb28f;"> 0s everywhere else."</span> 42.291 + [n] 42.292 + (incanter.core/identity-matrix n)) 42.293 + 42.294 + 42.295 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">matrix-by-rows</span> 42.296 + <span style="color: #8fb28f;">"Define a matrix by giving its rows."</span> 42.297 + [& rows] 42.298 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> 42.299 + (<span style="color: #8cd0d3;">not</span> (all-equal? (<span style="color: #8cd0d3;">map</span> count rows))) 42.300 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"All rows in a matrix must have the same number of elements."</span>)) 42.301 + (incanter.core/matrix (<span style="color: #8cd0d3;">vec</span> rows)))) 42.302 + 42.303 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">matrix-by-cols</span> 42.304 + <span style="color: #8fb28f;">"Define a matrix by giving its columns"</span> 42.305 + [& cols] 42.306 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not</span> (all-equal? (<span style="color: #8cd0d3;">map</span> count cols))) 42.307 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"All columns in a matrix must have the same number of elements."</span>)) 42.308 + (incanter.core/matrix (<span style="color: #8cd0d3;">vec</span> (<span style="color: #8cd0d3;">apply</span> map vector cols))))) 42.309 + 42.310 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">identity-matrix</span> 42.311 + <span style="color: #8fb28f;">"Define a square matrix of size n-by-n with 1s along the diagonal and</span> 42.312 +<span style="color: #8fb28f;"> 0s everywhere else."</span> 42.313 + [n] 42.314 + (incanter.core/identity-matrix n)) 42.315 + 42.316 +</pre> 42.317 + 42.318 + 42.319 + 42.320 + 42.321 +</div> 42.322 +</div> 42.323 + 42.324 +</div> 42.325 + 42.326 +<div id="outline-container-1-4" class="outline-3"> 42.327 +<h3 id="sec-1-4"><span class="section-number-3">1.4</span> Generic Operations </h3> 42.328 +<div class="outline-text-3" id="text-1-4"> 42.329 + 42.330 + 42.331 + 42.332 + 42.333 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 42.334 +(<span style="color: #8cd0d3;">use</span> 'clojure.contrib.generic.arithmetic 42.335 + 'clojure.contrib.generic.collection 42.336 + 'clojure.contrib.generic.functor 42.337 + 'clojure.contrib.generic.math-functions) 42.338 + 42.339 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">numbers?</span> 42.340 + <span style="color: #8fb28f;">"Returns true if all arguments are numbers, else false."</span> 42.341 + [& xs] 42.342 + (<span style="color: #8cd0d3;">every?</span> number? xs)) 42.343 + 42.344 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">tuple-surgery</span> 42.345 + <span style="color: #8fb28f;">"Applies the function f to the items of tuple and the additional</span> 42.346 +<span style="color: #8fb28f;"> arguments, if any. Returns a Tuple of the same type as tuple."</span> 42.347 + [tuple f & xs] 42.348 + ((<span style="color: #f0dfaf; font-weight: bold;">if</span> (up? tuple) up down) 42.349 + (<span style="color: #8cd0d3;">apply</span> f (<span style="color: #8cd0d3;">seq</span> tuple) xs))) 42.350 + 42.351 + 42.352 + 42.353 +<span style="color: #708070;">;;; </span><span style="color: #7f9f7f;">CONTRACTION collapses two compatible tuples into a number.</span> 42.354 + 42.355 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">contractible?</span> 42.356 + <span style="color: #8fb28f;">"Returns true if the tuples a and b are compatible for contraction,</span> 42.357 +<span style="color: #8fb28f;"> else false. Tuples are compatible if they have the same number of</span> 42.358 +<span style="color: #8fb28f;"> components, they have opposite spins, and their elements are</span> 42.359 +<span style="color: #8fb28f;"> pairwise-compatible."</span> 42.360 + [a b] 42.361 + (<span style="color: #f0dfaf; font-weight: bold;">and</span> 42.362 + (<span style="color: #8cd0d3;">isa?</span> (<span style="color: #8cd0d3;">type</span> a) Tuple) 42.363 + (<span style="color: #8cd0d3;">isa?</span> (<span style="color: #8cd0d3;">type</span> b) Tuple) 42.364 + (<span style="color: #8cd0d3;">=</span> (<span style="color: #8cd0d3;">count</span> a) (<span style="color: #8cd0d3;">count</span> b)) 42.365 + (<span style="color: #8cd0d3;">not=</span> (spin a) (spin b)) 42.366 + 42.367 + (<span style="color: #8cd0d3;">not-any?</span> false? 42.368 + (<span style="color: #8cd0d3;">map</span> #(<span style="color: #f0dfaf; font-weight: bold;">or</span> 42.369 + (numbers? %1 %2) 42.370 + (contractible? %1 %2)) 42.371 + a b)))) 42.372 + 42.373 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">contract</span> 42.374 + <span style="color: #8fb28f;">"Contracts two tuples, returning the sum of the</span> 42.375 +<span style="color: #8fb28f;"> products of the corresponding items. Contraction is recursive on</span> 42.376 +<span style="color: #8fb28f;"> nested tuples."</span> 42.377 + [a b] 42.378 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not</span> (contractible? a b)) 42.379 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> 42.380 + (Exception. <span style="color: #cc9393;">"Not compatible for contraction."</span>)) 42.381 + (<span style="color: #8cd0d3;">reduce</span> + 42.382 + (<span style="color: #8cd0d3;">map</span> 42.383 + (<span style="color: #8cd0d3;">fn</span> [x y] 42.384 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (numbers? x y) 42.385 + (<span style="color: #8cd0d3;">*</span> x y) 42.386 + (contract x y))) 42.387 + a b)))) 42.388 + 42.389 + 42.390 + 42.391 + 42.392 + 42.393 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">conj</span> Tuple 42.394 + [tuple & xs] 42.395 + (tuple-surgery tuple #(<span style="color: #8cd0d3;">apply</span> conj % xs))) 42.396 + 42.397 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">fmap</span> Tuple 42.398 + [f tuple] 42.399 + (tuple-surgery tuple (<span style="color: #8cd0d3;">partial</span> map f))) 42.400 + 42.401 + 42.402 + 42.403 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">TODO: define Scalar, and add it to the hierarchy above Number and Complex</span> 42.404 + 42.405 + 42.406 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [Tuple Tuple] <span style="color: #708070;">; </span><span style="color: #7f9f7f;">tuple*tuple</span> 42.407 + [a b] 42.408 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (contractible? a b) 42.409 + (contract a b) 42.410 + (<span style="color: #8cd0d3;">map</span> (<span style="color: #8cd0d3;">partial</span> * a) b))) 42.411 + 42.412 + 42.413 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [java.lang.Number Tuple] <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">scalar * tuple</span> 42.414 + [a x] (fmap (<span style="color: #8cd0d3;">partial</span> * a) x)) 42.415 + 42.416 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [Tuple java.lang.Number] 42.417 + [x a] (<span style="color: #8cd0d3;">*</span> a x)) 42.418 + 42.419 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [java.lang.Number incanter.Matrix] <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">scalar * matrix</span> 42.420 + [x M] (incanter.core/mult x M)) 42.421 + 42.422 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [incanter.Matrix java.lang.Number] 42.423 + [M x] (<span style="color: #8cd0d3;">*</span> x M)) 42.424 + 42.425 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [incanter.Matrix incanter.Matrix] <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">matrix * matrix</span> 42.426 + [M1 M2] 42.427 + (incanter.core/mmult M1 M2)) 42.428 + 42.429 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [incanter.Matrix Tuple] <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">matrix * tuple</span> 42.430 + [M v] 42.431 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #f0dfaf; font-weight: bold;">and</span> (<span style="color: #8cd0d3;">apply</span> numbers? v) (up? v)) 42.432 + (<span style="color: #8cd0d3;">*</span> M (matrix-by-cols v)) 42.433 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"Currently, you can only multiply a matrix by a tuple of *numbers*"</span>)) 42.434 + )) 42.435 + 42.436 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [Tuple incanter.Matrix] <span style="color: #708070;">;; </span><span style="color: #7f9f7f;">tuple * Matrix</span> 42.437 + [v M] 42.438 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #f0dfaf; font-weight: bold;">and</span> (<span style="color: #8cd0d3;">apply</span> numbers? v) (down? v)) 42.439 + (<span style="color: #8cd0d3;">*</span> (matrix-by-rows v) M) 42.440 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"Currently, you can only multiply a matrix by a tuple of *numbers*"</span>)) 42.441 + )) 42.442 + 42.443 + 42.444 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">exp</span> incanter.Matrix 42.445 + [M] 42.446 + (incanter.core/exp M)) 42.447 + 42.448 +</pre> 42.449 + 42.450 + 42.451 + 42.452 + 42.453 +</div> 42.454 +</div> 42.455 + 42.456 +</div> 42.457 + 42.458 +<div id="outline-container-2" class="outline-2"> 42.459 +<h2 id="sec-2"><span class="section-number-2">2</span> Operators and Differentiation </h2> 42.460 +<div class="outline-text-2" id="text-2"> 42.461 + 42.462 + 42.463 + 42.464 + 42.465 +</div> 42.466 + 42.467 +<div id="outline-container-2-1" class="outline-3"> 42.468 +<h3 id="sec-2-1"><span class="section-number-3">2.1</span> Operators </h3> 42.469 +<div class="outline-text-3" id="text-2-1"> 42.470 + 42.471 + 42.472 +</div> 42.473 + 42.474 +</div> 42.475 + 42.476 +<div id="outline-container-2-2" class="outline-3"> 42.477 +<h3 id="sec-2-2"><span class="section-number-3">2.2</span> Differential Terms and Sequences </h3> 42.478 +<div class="outline-text-3" id="text-2-2"> 42.479 + 42.480 + 42.481 + 42.482 + 42.483 +<pre class="src src-clojure">(<span style="color: #f0dfaf; font-weight: bold;">in-ns</span> 'sicm.utils) 42.484 +(<span style="color: #8cd0d3;">use</span> 'clojure.contrib.seq 42.485 + 'clojure.contrib.generic.arithmetic 42.486 + 'clojure.contrib.generic.collection 42.487 + 'clojure.contrib.generic.math-functions) 42.488 + 42.489 +<span style="color: #708070;">;;</span><span style="color: #7f9f7f;">∂</span> 42.490 + 42.491 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">DEFINITION : Differential Term</span> 42.492 + 42.493 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">A quantity with infinitesimal components, e.g. x, dxdy, 4dydz. The</span> 42.494 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">coefficient of the quantity is returned by the 'coefficient' method,</span> 42.495 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">while the sequence of differential parameters is returned by the</span> 42.496 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">method 'partials'.</span> 42.497 + 42.498 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">Instead of using (potentially ambiguous) letters to denote</span> 42.499 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">differential parameters (dx,dy,dz), we use integers. So, dxdz becomes [0 2].</span> 42.500 + 42.501 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">The coefficient can be any arithmetic object; the</span> 42.502 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">partials must be a nonrepeating sorted sequence of nonnegative</span> 42.503 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">integers.</span> 42.504 + 42.505 +(<span style="color: #f0dfaf; font-weight: bold;">deftype</span> <span style="color: #f0dfaf;">DifferentialTerm</span> [coefficient partials]) 42.506 + 42.507 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">differential-term</span> 42.508 + <span style="color: #8fb28f;">"Make a differential term given pairs of coefficients and partials."</span> 42.509 + [coefficient partials] 42.510 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #f0dfaf; font-weight: bold;">and</span> (<span style="color: #8cd0d3;">coll?</span> partials) (<span style="color: #8cd0d3;">every?</span> #(<span style="color: #f0dfaf; font-weight: bold;">and</span> (<span style="color: #8cd0d3;">integer?</span> %) (<span style="color: #8cd0d3;">not</span>(<span style="color: #8cd0d3;">neg?</span> %))) partials)) 42.511 + (DifferentialTerm. coefficient (<span style="color: #8cd0d3;">set</span> partials)) 42.512 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (java.lang.IllegalArgumentException. <span style="color: #cc9393;">"Partials must be a collection of integers."</span>)))) 42.513 + 42.514 + 42.515 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">DEFINITION : Differential Sequence</span> 42.516 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">A differential sequence is a sequence of differential terms, all with different partials.</span> 42.517 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">Internally, it is a map from the partials of each term to their coefficients.</span> 42.518 + 42.519 +(<span style="color: #f0dfaf; font-weight: bold;">deftype</span> <span style="color: #f0dfaf;">DifferentialSeq</span> 42.520 + [terms] 42.521 + <span style="color: #708070;">;;</span><span style="color: #7f9f7f;">clojure.lang.IPersistentMap</span> 42.522 + clojure.lang.Associative 42.523 + (<span style="color: #8cd0d3;">assoc</span> [this key val] 42.524 + (DifferentialSeq. 42.525 + (<span style="color: #8cd0d3;">cons</span> (differential-term val key) terms))) 42.526 + (<span style="color: #8cd0d3;">cons</span> [this x] 42.527 + (DifferentialSeq. (<span style="color: #8cd0d3;">cons</span> x terms))) 42.528 + (containsKey [this key] 42.529 + (<span style="color: #8cd0d3;">not</span>(<span style="color: #8cd0d3;">nil?</span> (find-first #(<span style="color: #8cd0d3;">=</span> (.partials %) key) terms)))) 42.530 + (<span style="color: #8cd0d3;">count</span> [this] (<span style="color: #8cd0d3;">count</span> (.terms this))) 42.531 + (<span style="color: #8cd0d3;">empty</span> [this] (DifferentialSeq. [])) 42.532 + (entryAt [this key] 42.533 + ((<span style="color: #8cd0d3;">juxt</span> #(.partials %) #(.coefficient %)) 42.534 + (find-first #(<span style="color: #8cd0d3;">=</span> (.partials %) key) terms))) 42.535 + (<span style="color: #8cd0d3;">seq</span> [this] (<span style="color: #8cd0d3;">seq</span> (.terms this)))) 42.536 + 42.537 + 42.538 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">fmap</span> DifferentialSeq 42.539 + [f dseq] 42.540 + (DifferentialSeq. (fmap f (.terms dseq)))) 42.541 + 42.542 + 42.543 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">BUILDING DIFFERENTIAL OBJECTS</span> 42.544 + 42.545 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">differential-seq</span> 42.546 + <span style="color: #8fb28f;">"Define a differential sequence by specifying coefficient/partials</span> 42.547 +<span style="color: #8fb28f;">pairs, which are used to create differential terms to populate the</span> 42.548 +<span style="color: #8fb28f;">sequence."</span> 42.549 + ([coefficient partials] 42.550 + (DifferentialSeq. {(<span style="color: #8cd0d3;">set</span> partials) coefficient})) 42.551 + ([coefficient partials & cps] 42.552 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">odd?</span> (<span style="color: #8cd0d3;">count</span> cps)) 42.553 + (<span style="color: #f0dfaf; font-weight: bold;">throw</span> (Exception. <span style="color: #cc9393;">"differential-seq requires an even number of terms."</span>)) 42.554 + (DifferentialSeq. 42.555 + (<span style="color: #8cd0d3;">reduce</span> 42.556 + #(<span style="color: #8cd0d3;">assoc</span> %1 (<span style="color: #8cd0d3;">set</span> (<span style="color: #8cd0d3;">second</span> %2)) (<span style="color: #8cd0d3;">first</span> %2)) 42.557 + {(<span style="color: #8cd0d3;">set</span> partials) coefficient} 42.558 + (<span style="color: #8cd0d3;">partition</span> 2 cps)))))) 42.559 + 42.560 + 42.561 + 42.562 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">big-part</span> 42.563 + <span style="color: #8fb28f;">"Returns the part of the differential sequence that is finite,</span> 42.564 +<span style="color: #8fb28f;"> i.e. not infinitely small, as a differential sequence. If given a</span> 42.565 +<span style="color: #8fb28f;"> non-differential object, returns that object."</span> 42.566 + [dseq] 42.567 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not=</span> (<span style="color: #8cd0d3;">type</span> dseq) DifferentialSeq) dseq 42.568 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [m (.terms dseq) 42.569 + keys (<span style="color: #8cd0d3;">sort-by</span> count (<span style="color: #8cd0d3;">keys</span> m)) 42.570 + smallest-var (<span style="color: #8cd0d3;">last</span> (<span style="color: #8cd0d3;">last</span> keys))] 42.571 + (DifferentialSeq. 42.572 + (<span style="color: #8cd0d3;">reduce</span> 42.573 + #(<span style="color: #8cd0d3;">assoc</span> %1 (<span style="color: #8cd0d3;">first</span> %2) (<span style="color: #8cd0d3;">second</span> %2)) 42.574 + {} 42.575 + (<span style="color: #8cd0d3;">remove</span> #((<span style="color: #8cd0d3;">first</span> %) smallest-var) m)))))) 42.576 + 42.577 + 42.578 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">small-part</span> 42.579 + <span style="color: #8fb28f;">"Returns the part of the differential sequence that infinitely</span> 42.580 +<span style="color: #8fb28f;"> small, as a differential sequence. If given a non-differential</span> 42.581 +<span style="color: #8fb28f;"> object, returns that object."</span> 42.582 + [dseq] 42.583 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not=</span> (<span style="color: #8cd0d3;">type</span> dseq) DifferentialSeq) 0 42.584 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [m (.terms dseq) 42.585 + keys (<span style="color: #8cd0d3;">sort-by</span> count (<span style="color: #8cd0d3;">keys</span> m)) 42.586 + smallest-var (<span style="color: #8cd0d3;">last</span> (<span style="color: #8cd0d3;">last</span> keys))] 42.587 + (DifferentialSeq. 42.588 + (<span style="color: #8cd0d3;">reduce</span> 42.589 + #(<span style="color: #8cd0d3;">assoc</span> %1 (<span style="color: #8cd0d3;">first</span> %2) (<span style="color: #8cd0d3;">second</span> %2)) {} 42.590 + (<span style="color: #8cd0d3;">filter</span> #((<span style="color: #8cd0d3;">first</span> %) smallest-var) m)))))) 42.591 + 42.592 + 42.593 + 42.594 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">cartesian-product</span> [set1 set2] 42.595 + (<span style="color: #8cd0d3;">reduce</span> concat 42.596 + (<span style="color: #f0dfaf; font-weight: bold;">for</span> [x set1] 42.597 + (<span style="color: #f0dfaf; font-weight: bold;">for</span> [y set2] 42.598 + [x y])))) 42.599 + 42.600 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">differential-multiply</span> 42.601 + <span style="color: #8fb28f;">"Multiply two differential sequences. The square of any differential</span> 42.602 +<span style="color: #8fb28f;"> variable is zero since differential variables are infinitesimally</span> 42.603 +<span style="color: #8fb28f;"> small."</span> 42.604 + [dseq1 dseq2] 42.605 + (DifferentialSeq. 42.606 + (<span style="color: #8cd0d3;">reduce</span> 42.607 + (<span style="color: #8cd0d3;">fn</span> [m [[vars1 coeff1] [vars2 coeff2]]] 42.608 + (<span style="color: #f0dfaf; font-weight: bold;">if</span> (<span style="color: #8cd0d3;">not</span> (<span style="color: #8cd0d3;">empty?</span> (clojure.set/<span style="color: #dfdfbf; font-weight: bold;">intersection</span> vars1 vars2))) 42.609 + m 42.610 + (<span style="color: #8cd0d3;">assoc</span> m (clojure.set/<span style="color: #dfdfbf; font-weight: bold;">union</span> vars1 vars2) (<span style="color: #8cd0d3;">*</span> coeff1 coeff2)))) 42.611 + {} 42.612 + (cartesian-product (.terms dseq1) (.terms dseq2))))) 42.613 + 42.614 + 42.615 + 42.616 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [DifferentialSeq DifferentialSeq] 42.617 + [dseq1 dseq2] 42.618 + (differential-multiply dseq1 dseq2)) 42.619 + 42.620 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">+</span> [DifferentialSeq DifferentialSeq] 42.621 + [dseq1 dseq2] 42.622 + (DifferentialSeq. 42.623 + (<span style="color: #8cd0d3;">merge-with</span> + (.terms dseq1) (.terms dseq2)))) 42.624 + 42.625 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [java.lang.Number DifferentialSeq] 42.626 + [x dseq] 42.627 + (fmap (<span style="color: #8cd0d3;">partial</span> * x) dseq)) 42.628 + 42.629 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">*</span> [DifferentialSeq java.lang.Number] 42.630 + [dseq x] 42.631 + (fmap (<span style="color: #8cd0d3;">partial</span> * x) dseq)) 42.632 +<span style="color: #708070;">;; </span><span style="color: #7f9f7f;">DERIVATIVES</span> 42.633 + 42.634 + 42.635 + 42.636 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">linear-approximator</span> 42.637 + <span style="color: #8fb28f;">"Returns an operator that linearly approximates the given function."</span> 42.638 + ([f df|dx] 42.639 + (<span style="color: #8cd0d3;">fn</span> [x] 42.640 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [big-part (big-part x) 42.641 + small-part (small-part x)] 42.642 + (<span style="color: #8cd0d3;">+</span> (fmap f big-part) 42.643 + (<span style="color: #8cd0d3;">*</span> (fmap df|dx big-part) small-part))))) 42.644 + ([f df|dx df|dy] 42.645 + (<span style="color: #8cd0d3;">fn</span> [x y] 42.646 + (<span style="color: #f0dfaf; font-weight: bold;">let</span> [X (big-part x) 42.647 + Y (big-part y) 42.648 + DX (small-part x) 42.649 + DY (small-part y)] 42.650 + (<span style="color: #8cd0d3;">+</span> (f X Y) 42.651 + (<span style="color: #8cd0d3;">+</span> (<span style="color: #8cd0d3;">*</span> DX (df|dx X Y)) 42.652 + (<span style="color: #8cd0d3;">*</span> DY (df|dy X Y))))))) 42.653 + ) 42.654 + 42.655 + 42.656 + 42.657 + 42.658 + 42.659 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">D</span>[f] 42.660 + (<span style="color: #8cd0d3;">fn</span>[x] 42.661 + (f (differential-seq x [] 1 [0])))) 42.662 + 42.663 +(<span style="color: #f0dfaf; font-weight: bold;">defn</span> <span style="color: #f0dfaf;">d</span>[f partials] 42.664 + (<span style="color: #8cd0d3;">fn</span> [x] 42.665 + (<span style="color: #8cd0d3;">get</span> 42.666 + (.terms ((D f)x)) 42.667 + (<span style="color: #8cd0d3;">set</span> partials) 42.668 + 0 42.669 + ))) 42.670 + 42.671 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">exp</span> DifferentialSeq [x] 42.672 + ((linear-approximator exp exp) x)) 42.673 + 42.674 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">sin</span> DifferentialSeq 42.675 + [x] 42.676 + ((linear-approximator sin cos) x)) 42.677 + 42.678 +(<span style="color: #f0dfaf; font-weight: bold;">defmethod</span> <span style="color: #f0dfaf;">cos</span> DifferentialSeq 42.679 + [x] 42.680 + ((linear-approximator cos #(<span style="color: #8cd0d3;">-</span> (sin %))) x)) 42.681 + 42.682 + 42.683 + 42.684 +</pre> 42.685 + 42.686 + 42.687 + 42.688 + 42.689 + 42.690 + 42.691 + 42.692 + 42.693 + 42.694 +</div> 42.695 +</div> 42.696 +</div> 42.697 +<div id="postamble"> 42.698 +<p class="date">Date: 2011-08-11 04:10:36 EDT</p> 42.699 +<p class="author">Author: Dylan Holmes</p> 42.700 +<p class="creator">Org version 7.6 with Emacs version 23</p> 42.701 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 42.702 +</div> 42.703 +</div> 42.704 +</body> 42.705 +</html>
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/sicm/utils.org Fri Oct 28 00:03:05 2011 -0700 43.3 @@ -0,0 +1,690 @@ 43.4 +#+TITLE: Building a Classical Mechanics Library in Clojure 43.5 +#+author: Dylan Holmes 43.6 +#+EMAIL: rlm@mit.edu 43.7 +#+MATHJAX: align:"left" mathml:t path:"../MathJax/MathJax.js" 43.8 +#+STYLE: <link rel="stylesheet" type="text/css" href="../css/aurellem.css" /> 43.9 +#+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t 43.10 +#+SETUPFILE: ../templates/level-0.org 43.11 +#+INCLUDE: ../templates/level-0.org 43.12 +#+BABEL: :noweb yes :results silent 43.13 + 43.14 +* Useful data types 43.15 + 43.16 +** Complex numbers 43.17 + 43.18 +** Power series 43.19 + 43.20 +** Tuples and tensors 43.21 + 43.22 +*** Tuples are \ldquo{}sequences with spin\rdquo{} 43.23 + 43.24 +#+srcname: tuples 43.25 +#+begin_src clojure 43.26 +(in-ns 'sicm.utils) 43.27 + 43.28 +;; Let some objects have spin 43.29 + 43.30 +(defprotocol Spinning 43.31 + (up? [this]) 43.32 + (down? [this])) 43.33 + 43.34 +(defn spin 43.35 + "Returns the spin of the Spinning s, either :up or :down" 43.36 + [#^Spinning s] 43.37 + (cond (up? s) :up (down? s) :down)) 43.38 + 43.39 + 43.40 +;; DEFINITION: A tuple is a sequence with spin 43.41 + 43.42 +(deftype Tuple 43.43 + [spin coll] 43.44 + 43.45 + clojure.lang.Seqable 43.46 + (seq [this] (seq (.coll this))) 43.47 + 43.48 + clojure.lang.Counted 43.49 + (count [this] (count (.coll this))) 43.50 + 43.51 + Spinning 43.52 + (up? [this] (= ::up (.spin this))) 43.53 + (down? [this] (= ::down (.spin this)))) 43.54 + 43.55 +(defmethod print-method Tuple 43.56 + [o w] 43.57 + (print-simple 43.58 + (if (up? o) 43.59 + (str "u" (.coll o)) 43.60 + (str "d" (vec(.coll o)))) 43.61 + w)) 43.62 + 43.63 +(def tuple? #(= (type %) Tuple)) 43.64 + 43.65 +;; CONSTRUCTORS 43.66 + 43.67 +(defn up 43.68 + "Create a new up-tuple containing the contents of coll." 43.69 + [coll] 43.70 + (Tuple. ::up coll)) 43.71 + 43.72 +(defn down 43.73 + "Create a new down-tuple containing the contents of coll." 43.74 + [coll] 43.75 + (Tuple. ::down coll)) 43.76 + 43.77 +(defn same-spin 43.78 + "Creates a tuple which has the same spin as tuple and which contains 43.79 +the contents of coll." 43.80 + [tuple coll] 43.81 + (if (up? tuple) 43.82 + (up coll) 43.83 + (down coll))) 43.84 + 43.85 +(defn opposite-spin 43.86 + "Create a tuple which has opposite spin to tuple and which contains 43.87 +the contents of coll." 43.88 + [tuple coll] 43.89 + (if (up? tuple) 43.90 + (down coll) 43.91 + (up coll))) 43.92 +#+end_src 43.93 + 43.94 + 43.95 + 43.96 +*** Matrices 43.97 +#+srcname:matrices 43.98 +#+begin_src clojure 43.99 +(in-ns 'sicm.utils) 43.100 +(require 'incanter.core) ;; use incanter's fast matrices 43.101 + 43.102 + 43.103 +(defn all-equal? [coll] 43.104 + (if (empty? (rest coll)) true 43.105 + (and (= (first coll) (second coll)) 43.106 + (recur (rest coll))))) 43.107 + 43.108 + 43.109 +(defprotocol Matrix 43.110 + (rows [matrix]) 43.111 + (cols [matrix]) 43.112 + (diagonal [matrix]) 43.113 + (trace [matrix]) 43.114 + (determinant [matrix]) 43.115 + (transpose [matrix]) 43.116 + (conjugate [matrix]) 43.117 +) 43.118 + 43.119 +(extend-protocol Matrix incanter.Matrix 43.120 + (rows [rs] (map down (apply map vector (apply map vector rs)))) 43.121 + (cols [rs] (map up (apply map vector rs))) 43.122 + (diagonal [matrix] (incanter.core/diag matrix) ) 43.123 + (determinant [matrix] (incanter.core/det matrix)) 43.124 + (trace [matrix] (incanter.core/trace matrix)) 43.125 + (transpose [matrix] (incanter.core/trans matrix))) 43.126 + 43.127 +(defn count-rows [matrix] 43.128 + ((comp count rows) matrix)) 43.129 + 43.130 +(defn count-cols [matrix] 43.131 + ((comp count cols) matrix)) 43.132 + 43.133 +(defn square? [matrix] 43.134 + (= (count-rows matrix) (count-cols matrix))) 43.135 + 43.136 +(defn identity-matrix 43.137 + "Define a square matrix of size n-by-n with 1s along the diagonal and 43.138 + 0s everywhere else." 43.139 + [n] 43.140 + (incanter.core/identity-matrix n)) 43.141 + 43.142 + 43.143 +(defn matrix-by-rows 43.144 + "Define a matrix by giving its rows." 43.145 + [& rows] 43.146 + (if 43.147 + (not (all-equal? (map count rows))) 43.148 + (throw (Exception. "All rows in a matrix must have the same number of elements.")) 43.149 + (incanter.core/matrix (vec rows)))) 43.150 + 43.151 +(defn matrix-by-cols 43.152 + "Define a matrix by giving its columns" 43.153 + [& cols] 43.154 + (if (not (all-equal? (map count cols))) 43.155 + (throw (Exception. "All columns in a matrix must have the same number of elements.")) 43.156 + (incanter.core/matrix (vec (apply map vector cols))))) 43.157 + 43.158 +(defn identity-matrix 43.159 + "Define a square matrix of size n-by-n with 1s along the diagonal and 43.160 + 0s everywhere else." 43.161 + [n] 43.162 + (incanter.core/identity-matrix n)) 43.163 + 43.164 +#+end_src 43.165 + 43.166 +** Generic Operations 43.167 +#+srcname:arith-tuple 43.168 +#+begin_src clojure 43.169 +(in-ns 'sicm.utils) 43.170 +(use 'clojure.contrib.generic.arithmetic 43.171 + 'clojure.contrib.generic.collection 43.172 + 'clojure.contrib.generic.functor 43.173 + 'clojure.contrib.generic.math-functions) 43.174 + 43.175 +(defn numbers? 43.176 + "Returns true if all arguments are numbers, else false." 43.177 + [& xs] 43.178 + (every? number? xs)) 43.179 + 43.180 +(defn tuple-surgery 43.181 + "Applies the function f to the items of tuple and the additional 43.182 + arguments, if any. Returns a Tuple of the same type as tuple." 43.183 + [tuple f & xs] 43.184 + ((if (up? tuple) up down) 43.185 + (apply f (seq tuple) xs))) 43.186 + 43.187 + 43.188 + 43.189 +;;; CONTRACTION collapses two compatible tuples into a number. 43.190 + 43.191 +(defn contractible? 43.192 + "Returns true if the tuples a and b are compatible for contraction, 43.193 + else false. Tuples are compatible if they have the same number of 43.194 + components, they have opposite spins, and their elements are 43.195 + pairwise-compatible." 43.196 + [a b] 43.197 + (and 43.198 + (isa? (type a) Tuple) 43.199 + (isa? (type b) Tuple) 43.200 + (= (count a) (count b)) 43.201 + (not= (spin a) (spin b)) 43.202 + 43.203 + (not-any? false? 43.204 + (map #(or 43.205 + (numbers? %1 %2) 43.206 + (contractible? %1 %2)) 43.207 + a b)))) 43.208 + 43.209 +(defn contract 43.210 + "Contracts two tuples, returning the sum of the 43.211 + products of the corresponding items. Contraction is recursive on 43.212 + nested tuples." 43.213 + [a b] 43.214 + (if (not (contractible? a b)) 43.215 + (throw 43.216 + (Exception. "Not compatible for contraction.")) 43.217 + (reduce + 43.218 + (map 43.219 + (fn [x y] 43.220 + (if (numbers? x y) 43.221 + (* x y) 43.222 + (contract x y))) 43.223 + a b)))) 43.224 + 43.225 + 43.226 + 43.227 + 43.228 + 43.229 +(defmethod conj Tuple 43.230 + [tuple & xs] 43.231 + (tuple-surgery tuple #(apply conj % xs))) 43.232 + 43.233 +(defmethod fmap Tuple 43.234 + [f tuple] 43.235 + (tuple-surgery tuple (partial map f))) 43.236 + 43.237 + 43.238 + 43.239 +;; TODO: define Scalar, and add it to the hierarchy above Number and Complex 43.240 + 43.241 + 43.242 +(defmethod * [Tuple Tuple] ; tuple*tuple 43.243 + [a b] 43.244 + (if (contractible? a b) 43.245 + (contract a b) 43.246 + (map (partial * a) b))) 43.247 + 43.248 + 43.249 +(defmethod * [java.lang.Number Tuple] ;; scalar * tuple 43.250 + [a x] (fmap (partial * a) x)) 43.251 + 43.252 +(defmethod * [Tuple java.lang.Number] 43.253 + [x a] (* a x)) 43.254 + 43.255 +(defmethod * [java.lang.Number incanter.Matrix] ;; scalar * matrix 43.256 + [x M] (incanter.core/mult x M)) 43.257 + 43.258 +(defmethod * [incanter.Matrix java.lang.Number] 43.259 + [M x] (* x M)) 43.260 + 43.261 +(defmethod * [incanter.Matrix incanter.Matrix] ;; matrix * matrix 43.262 + [M1 M2] 43.263 + (incanter.core/mmult M1 M2)) 43.264 + 43.265 +(defmethod * [incanter.Matrix Tuple] ;; matrix * tuple 43.266 + [M v] 43.267 + (if (and (apply numbers? v) (up? v)) 43.268 + (* M (matrix-by-cols v)) 43.269 + (throw (Exception. "Currently, you can only multiply a matrix by a tuple of *numbers*")) 43.270 + )) 43.271 + 43.272 +(defmethod * [Tuple incanter.Matrix] ;; tuple * Matrix 43.273 + [v M] 43.274 + (if (and (apply numbers? v) (down? v)) 43.275 + (* (matrix-by-rows v) M) 43.276 + (throw (Exception. "Currently, you can only multiply a matrix by a tuple of *numbers*")) 43.277 + )) 43.278 + 43.279 + 43.280 +(defmethod exp incanter.Matrix 43.281 + [M] 43.282 + (incanter.core/exp M)) 43.283 + 43.284 +#+end_src 43.285 + 43.286 +* Operators and Differentiation 43.287 +** Operators 43.288 +#+scrname: operators 43.289 +#+begin_src clojure 43.290 +(in-ns 'sicm.utils) 43.291 +(use 'clojure.contrib.seq 43.292 + 'clojure.contrib.generic.arithmetic 43.293 + 'clojure.contrib.generic.collection 43.294 + 'clojure.contrib.generic.math-functions) 43.295 + 43.296 +(defmethod + [clojure.lang.IFn clojure.lang.IFn] 43.297 + [f g] 43.298 + (fn [& args] 43.299 + (+ (apply f args) (apply g args)))) 43.300 + 43.301 +(defmethod * [clojure.lang.IFn clojure.lang.IFn] 43.302 + [f g] 43.303 + (fn [& args] 43.304 + (* (apply f args) (apply g args)))) 43.305 + 43.306 +(defmethod / [clojure.lang.IFn java.lang.Number] 43.307 + [f x] 43.308 + (fn [& args] 43.309 + (/ (apply f args) x))) 43.310 + 43.311 + 43.312 +(defmethod - [clojure.lang.IFn] 43.313 + [f] 43.314 + (fn [& args] 43.315 + (- (apply f args)))) 43.316 + 43.317 +(defmethod - [clojure.lang.IFn clojure.lang.IFn] 43.318 + [f g] 43.319 + (fn [& args] 43.320 + (- (apply f args) (apply g args)))) 43.321 + 43.322 +(defmethod pow [clojure.lang.IFn java.lang.Number] 43.323 + [f x] 43.324 + (fn [& args] 43.325 + (pow (apply f args) x))) 43.326 + 43.327 + 43.328 +(defmethod + [java.lang.Number clojure.lang.IFn] 43.329 + [x f] 43.330 + (fn [& args] 43.331 + (+ x (apply f args)))) 43.332 + 43.333 +(defmethod * [java.lang.Number clojure.lang.IFn] 43.334 + [x f] 43.335 + (fn [& args] 43.336 + (* x (apply f args)))) 43.337 + 43.338 +(defmethod * [clojure.lang.IFn java.lang.Number] 43.339 + [f x] 43.340 + (* x f)) 43.341 +(defmethod + [clojure.lang.IFn java.lang.Number] 43.342 + [f x] 43.343 + (+ x f)) 43.344 + 43.345 +#+end_src 43.346 + 43.347 +** Differential Terms and Sequences 43.348 +#+srcname: differential 43.349 +#+begin_src clojure 43.350 +(in-ns 'sicm.utils) 43.351 +(use 'clojure.contrib.seq 43.352 + 'clojure.contrib.generic.arithmetic 43.353 + 'clojure.contrib.generic.collection 43.354 + 'clojure.contrib.generic.math-functions) 43.355 + 43.356 +;;∂ 43.357 + 43.358 +;; DEFINITION : Differential Term 43.359 + 43.360 +;; A quantity with infinitesimal components, e.g. x, dxdy, 4dydz. The 43.361 +;; coefficient of the quantity is returned by the 'coefficient' method, 43.362 +;; while the sequence of differential parameters is returned by the 43.363 +;; method 'partials'. 43.364 + 43.365 +;; Instead of using (potentially ambiguous) letters to denote 43.366 +;; differential parameters (dx,dy,dz), we use integers. So, dxdz becomes [0 2]. 43.367 + 43.368 +;; The coefficient can be any arithmetic object; the 43.369 +;; partials must be a nonrepeating sorted sequence of nonnegative 43.370 +;; integers. 43.371 + 43.372 +;; (deftype DifferentialTerm [coefficient partials]) 43.373 + 43.374 +;; (defn differential-term 43.375 +;; "Make a differential term from a coefficient and list of partials." 43.376 +;; [coefficient partials] 43.377 +;; (if (and (coll? partials) (every? #(and (integer? %) (not(neg? %))) partials)) 43.378 +;; (DifferentialTerm. coefficient (set partials)) 43.379 +;; (throw (java.lang.IllegalArgumentException. "Partials must be a collection of integers.")))) 43.380 + 43.381 + 43.382 +;; DEFINITION : Differential Sequence 43.383 +;; A differential sequence is a sequence of differential terms, all with different partials. 43.384 +;; Internally, it is a map from the partials of each term to their coefficients. 43.385 + 43.386 +(deftype DifferentialSeq 43.387 + [terms] 43.388 + ;;clojure.lang.IPersistentMap 43.389 + clojure.lang.Associative 43.390 + (assoc [this key val] 43.391 + (DifferentialSeq. 43.392 + (cons (differential-term val key) terms))) 43.393 + (cons [this x] 43.394 + (DifferentialSeq. (cons x terms))) 43.395 + (containsKey [this key] 43.396 + (not(nil? (find-first #(= (.partials %) key) terms)))) 43.397 + (count [this] (count (.terms this))) 43.398 + (empty [this] (DifferentialSeq. [])) 43.399 + (entryAt [this key] 43.400 + ((juxt #(.partials %) #(.coefficient %)) 43.401 + (find-first #(= (.partials %) key) terms))) 43.402 + (seq [this] (seq (.terms this)))) 43.403 + 43.404 +(def differential? #(= (type %) DifferentialSeq)) 43.405 + 43.406 +(defn zeroth-order? 43.407 + "Returns true if the differential sequence has at most a constant term." 43.408 + [dseq] 43.409 + (and 43.410 + (differential? dseq) 43.411 + (every? 43.412 + #(= #{} %) 43.413 + (keys (.terms dseq))))) 43.414 + 43.415 +(defmethod fmap DifferentialSeq 43.416 + [f dseq] 43.417 + (DifferentialSeq. 43.418 + (fmap f (.terms dseq)))) 43.419 + 43.420 + 43.421 + 43.422 + 43.423 +;; BUILDING DIFFERENTIAL OBJECTS 43.424 + 43.425 +(defn differential-seq 43.426 + "Define a differential sequence by specifying an alternating 43.427 +sequence of coefficients and lists of partials." 43.428 + ([coefficient partials] 43.429 + (DifferentialSeq. {(set partials) coefficient})) 43.430 + ([coefficient partials & cps] 43.431 + (if (odd? (count cps)) 43.432 + (throw (Exception. "differential-seq requires an even number of terms.")) 43.433 + (DifferentialSeq. 43.434 + (reduce 43.435 + #(assoc %1 (set (second %2)) (first %2)) 43.436 + {(set partials) coefficient} 43.437 + (partition 2 cps)))))) 43.438 + 43.439 + 43.440 + 43.441 +(defn big-part 43.442 + "Returns the part of the differential sequence that is finite, 43.443 + i.e. not infinitely small. If the sequence is zeroth-order, returns 43.444 + the coefficient of the zeroth-order term instead. " 43.445 + [dseq] 43.446 + (if (zeroth-order? dseq) (get (.terms dseq) #{}) 43.447 + (let [m (.terms dseq) 43.448 + keys (sort-by count (keys m)) 43.449 + smallest-var (last (last keys))] 43.450 + (DifferentialSeq. 43.451 + (reduce 43.452 + #(assoc %1 (first %2) (second %2)) 43.453 + {} 43.454 + (remove #((first %) smallest-var) m)))))) 43.455 + 43.456 + 43.457 +(defn small-part 43.458 + "Returns the part of the differential sequence that infinitely 43.459 + small. If the sequence is zeroth-order, returns zero." 43.460 + [dseq] 43.461 + (if (zeroth-order? dseq) 0 43.462 + (let [m (.terms dseq) 43.463 + keys (sort-by count (keys m)) 43.464 + smallest-var (last (last keys))] 43.465 + (DifferentialSeq. 43.466 + (reduce 43.467 + #(assoc %1 (first %2) (second %2)) {} 43.468 + (filter #((first %) smallest-var) m)))))) 43.469 + 43.470 + 43.471 + 43.472 +(defn cartesian-product [set1 set2] 43.473 + (reduce concat 43.474 + (for [x set1] 43.475 + (for [y set2] 43.476 + [x y])))) 43.477 + 43.478 +(defn nth-subset [n] 43.479 + (if (zero? n) [] 43.480 + (let [lg2 #(/ (log %) (log 2)) 43.481 + k (int(java.lang.Math/floor (lg2 n))) 43.482 + ] 43.483 + (cons k 43.484 + (nth-subset (- n (pow 2 k))))))) 43.485 + 43.486 +(def all-partials 43.487 + (lazy-seq (map nth-subset (range)))) 43.488 + 43.489 + 43.490 +(defn differential-multiply 43.491 + "Multiply two differential sequences. The square of any differential 43.492 + variable is zero since differential variables are infinitesimally 43.493 + small." 43.494 + [dseq1 dseq2] 43.495 + (DifferentialSeq. 43.496 + (reduce 43.497 + (fn [m [[vars1 coeff1] [vars2 coeff2]]] 43.498 + (if (not (empty? (clojure.set/intersection vars1 vars2))) 43.499 + m 43.500 + (assoc m (clojure.set/union vars1 vars2) (* coeff1 coeff2)))) 43.501 + {} 43.502 + (cartesian-product (.terms dseq1) (.terms dseq2))))) 43.503 + 43.504 + 43.505 + 43.506 +(defmethod * [DifferentialSeq DifferentialSeq] 43.507 + [dseq1 dseq2] 43.508 + (differential-multiply dseq1 dseq2)) 43.509 + 43.510 +(defmethod + [DifferentialSeq DifferentialSeq] 43.511 + [dseq1 dseq2] 43.512 + (DifferentialSeq. 43.513 + (merge-with + (.terms dseq1) (.terms dseq2)))) 43.514 + 43.515 +(defmethod * [java.lang.Number DifferentialSeq] 43.516 + [x dseq] 43.517 + (fmap (partial * x) dseq)) 43.518 + 43.519 +(defmethod * [DifferentialSeq java.lang.Number] 43.520 + [dseq x] 43.521 + (fmap (partial * x) dseq)) 43.522 + 43.523 +(defmethod + [java.lang.Number DifferentialSeq] 43.524 + [x dseq] 43.525 + (+ (differential-seq x []) dseq)) 43.526 +(defmethod + [DifferentialSeq java.lang.Number] 43.527 + [dseq x] 43.528 + (+ dseq (differential-seq x []))) 43.529 + 43.530 +(defmethod - DifferentialSeq 43.531 + [x] 43.532 + (fmap - x)) 43.533 + 43.534 + 43.535 +;; DERIVATIVES 43.536 + 43.537 + 43.538 + 43.539 +(defn linear-approximator 43.540 + "Returns an operator that linearly approximates the given function." 43.541 + ([f df|dx] 43.542 + (fn [x] 43.543 + (let [big-part (big-part x) 43.544 + small-part (small-part x)] 43.545 + ;; f(x+dx) ~= f(x) + f'(x)dx 43.546 + (+ (f big-part) 43.547 + (* (df|dx big-part) small-part) 43.548 + )))) 43.549 + 43.550 + ([f df|dx df|dy] 43.551 + (fn [x y] 43.552 + (let [X (big-part x) 43.553 + Y (big-part y) 43.554 + DX (small-part x) 43.555 + DY (small-part y)] 43.556 + (+ (f X Y) 43.557 + (* DX (f df|dx X Y)) 43.558 + (* DY (f df|dy X Y))))))) 43.559 + 43.560 + 43.561 + 43.562 + 43.563 + 43.564 +(defn D[f] 43.565 + (fn[x] (f (+ x (differential-seq 1 [0] 1 [1] 1 [2]))))) 43.566 + 43.567 +(defn d[partials f] 43.568 + (fn [x] 43.569 + (get 43.570 + (.terms ((D f)x)) 43.571 + (set partials) 43.572 + 0 43.573 + ))) 43.574 + 43.575 +(defmethod exp DifferentialSeq [x] 43.576 + ((linear-approximator exp exp) x)) 43.577 + 43.578 +(defmethod sin DifferentialSeq 43.579 + [x] 43.580 + ((linear-approximator sin cos) x)) 43.581 + 43.582 +(defmethod cos DifferentialSeq 43.583 + [x] 43.584 + ((linear-approximator cos #(- (sin %))) x)) 43.585 + 43.586 +(defmethod log DifferentialSeq 43.587 + [x] 43.588 + ((linear-approximator log (fn [x] (/ x)) ) x)) 43.589 + 43.590 +(defmethod / [DifferentialSeq DifferentialSeq] 43.591 + [x y] 43.592 + ((linear-approximator / 43.593 + (fn [x y] (/ 1 y)) 43.594 + (fn [x y] (- (/ x (* y y))))) 43.595 + x y)) 43.596 + 43.597 +#+end_src 43.598 + 43.599 + 43.600 + 43.601 +* Derivatives Revisited 43.602 +#+begin_src clojure 43.603 +(in-ns 'sicm.utils) 43.604 +(use 'clojure.contrib.seq 43.605 + 'clojure.contrib.generic.arithmetic 43.606 + 'clojure.contrib.generic.collection 43.607 + 'clojure.contrib.generic.math-functions) 43.608 + 43.609 +(defn replace-in 43.610 + "Replaces the nth item in coll with the given item. If n is larger 43.611 + than the size of coll, adds n to the end of the collection." 43.612 + [coll n item] 43.613 + (concat 43.614 + (take n coll) 43.615 + [item] 43.616 + (drop (inc n) coll))) 43.617 + 43.618 +(defn euclidean-structure [f partials] 43.619 + (fn sd[g v] 43.620 + (cond 43.621 + (tuple? v) 43.622 + (opposite-spin 43.623 + v 43.624 + (map 43.625 + (fn [n] 43.626 + (sd (fn [xn] 43.627 + (g 43.628 + (same-spin v 43.629 + (replace-in v n xn)))) 43.630 + (nth v n))) 43.631 + (range (count v))))))) 43.632 + 43.633 + 43.634 + 43.635 + 43.636 +#+end_src 43.637 + 43.638 + 43.639 +* Symbolic Quantities 43.640 + 43.641 +#+srcname: symbolic 43.642 +#+begin_src clojure 43.643 +(in-ns 'sicm.utils) 43.644 +(use 'clojure.contrib.generic.arithmetic 43.645 + 'clojure.contrib.generic.math-functions) 43.646 + 43.647 +(deftype Symbolic 43.648 + [type 43.649 + expression]) 43.650 + 43.651 +(defn print-expression [s] 43.652 + (print (.expression s))) 43.653 + 43.654 +(defn symbolic-number 43.655 + [symbol] 43.656 + (Symbolic. java.lang.Number symbol)) 43.657 + 43.658 +(defn simplify-expression [s] 43.659 + (let [e (.expression s)] 43.660 + (cond 43.661 + (not(list? e)) e 43.662 + (= (first e) '+) 43.663 +) 43.664 + 43.665 + 43.666 + 43.667 +(defmethod + [Symbolic Symbolic] 43.668 + [x y] 43.669 + (Symbolic. (.type x) (list '+ (.expression x) (.expression y)))) 43.670 + 43.671 +(defmethod + [Symbolic java.lang.Number] 43.672 + [s x] 43.673 + (if (zero? x) 43.674 + s 43.675 + (Symbolic. (.type s) (list '+ (.expression s) x)))) 43.676 + 43.677 +(defmethod sin Symbolic 43.678 + [s] 43.679 + (Symbolic. (.type s) (list 'sin (.expression s)))) 43.680 + 43.681 +#+end_src 43.682 + 43.683 +* COMMENT To-be-tangled Source 43.684 +#+begin_src clojure :tangle utils.clj 43.685 +(ns sicm.utils) 43.686 + 43.687 +<<tuples>> 43.688 +<<matrices>> 43.689 +<<arith-tuple>> 43.690 + 43.691 +<<differential>> 43.692 +#+end_src 43.693 +