tag:blogger.com,1999:blog-8130892556311030502018-09-30T10:56:43.404-07:00Least Significant NibbleBetter living through algorithmsKarl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.comBlogger56125tag:blogger.com,1999:blog-813089255631103050.post-68445071926143064892017-12-02T15:46:00.000-08:002017-12-02T19:36:27.072-08:00Beverton–Holt: a discrete-time logistic model<p>The Beverton&ndash;Holt equation is a recurrence relation relating abundance of a population in generation $n$ to the abundance of the previous generation $n - 1$: \[ N_n = \frac{PN_{n-1}}{1 + PC^{-1}N_{n-1}}, \] where $N_n$ is the abundance at generation $n$, $P$ is the density-independent productivity of the population, and $C$ is the capacity of the population. This recurrence relation can be solved to explicitly relate the abundance at generation $n$ with the initial abundance $N_0$. Let $Q$ be the equilibrium abundance of the population given by the equation \[ Q = C \left (1-P^{-1} \right). \] Using this definition, the abunance at generation $n$ is given by the equation \[ N_n = \frac{QN_0}{N_0 + P^{-n}\left (Q - N_0 \right )}. \] The standard Beverton&ndash;Holt recurrence relation has an alternative form that is very similar to the solution of the recurrence relation. \begin{align} N_{n} &= \frac{P N_{n-1}}{1 + P C^{-1} N_{n-1}} \\ &= \frac{P N_{n-1}}{1 + P \left (1 - P^{-1 } \right ) Q^{-1} N_{n-1}} \\ &= \frac{P N_{n-1}}{1 + \left (P-1 \right ) Q^{-1} N_{n-1}} \\ &= \frac{P Q N_{n-1}}{Q + P N_{n-1} - N_{n-1}} \\ &= \frac{QN_{n-1}}{N_{n-1} + P^{-1} \left (Q - N_{n-1} \right )}. \end{align} With this alternative recurrence relation in hand, we can now prove the solution to the recurrence relation for $P > 0$ and $C > 0$. </p><strong>Proof</strong><div style="margin-left: 50px;"><p>We proceed by induction on $n$. For the initial generation $n = 1$, by the recurrence relation \[ N_1 = \frac{QN_0}{N_0 + P^{-1} \left (Q - N_0 \right )}. \] Suppose there exists a generation $t \ge 0$ such that \[ N_t = \frac{QN_0}{N_0 + P^{-t}\left (Q - N_0 \right )}. \] Then <div style="display: flex; flex-direction: row;">\begin{align} N_{t+1} &= \frac{Q N_t}{N_t + P^{-1} \left ( Q - N_t \right )} \\ &= \frac{Q N_t}{P^{-1} Q + \left (1 - P^{-1} \right )N_t} \\ &= \frac{Q^2 N_0 \left (N_0 + P^{-t} \left ( Q - N_0 \right ) \right )^{-1}} {P^{-1} Q + \left (1 - P^{-1} \right ) \left (Q N_0 \left (N_0 + P^{-t} \left ( Q - N_0 \right ) \right )^{-1} \right )} \\ &= \frac{Q N_0}{P^{-1} \left (N_0 + P^{-t} \left (Q - N_0 \right ) \right ) + \left (1 - P^{-1} \right ) N_0} \\ &= \frac{Q N_0}{P^{-1} N_0 + P^{-(t + 1)} \left (Q - N_0 \right ) + N_0 - P^{-1} N_0} \\ &= \frac{Q N_0}{N_0 + P^{-(t + 1)} \left (Q - N_0 \right )}. \end{align} <span style="align-self: flex-end;">&#8718;</span></div></div><p>Consider the differential equation describing logistic population growth: \[ \frac{\mathrm{d}N}{\mathrm{d}t} = (P - 1) N \left (1 - \frac{N}{Q} \right ) \] and its solution \[ N(t) = \frac{Q N(0)}{N(0) + (Q - N(0))e^{-(P - 1) t}}. \] Note that the limit as the time step approaches 0 of the Beverton&ndash;Holt model is the logistic equation.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-50995581667421427672017-10-07T11:15:00.000-07:002017-10-07T11:17:22.904-07:00Angular Carto: Compound basemaps<p>This post is part of a series covering how to create reusable Carto map components. Read the <a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">introduction</a> to learn why one would even want to do such a thing. The previous post in the series was voluminous, so I will change things up and describe a minor enhancement to <a href="http://blog.karldickman.us/2017/10/angular-carto-switching-basemaps.html">basemap switching</a>: basemaps that consist of more than one tile layer. This is particularly useful for adding labels to a basemap.</p> <h2>Enhancing the basemap prototype</h2><p>This post builds off of the previous post on basemap selection. I will describe how specific components will change to accommodate multiple tile layers in a basemap. You may find it helpful to read the <a href="http://blog.karldickman.us/2017/10/angular-carto-switching-basemaps.html">previous post</a> to understand how the other components work.</p><p>First, consider the basemap prototype that requires exactly one tile layer. Its public interface exposes <code>addToMap()</code> and <code>removeFromMap()</code> methods.</p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.js" data-gist-line="22-32"></code><p>Accommodating multiple tile layers in the basemap is as simple as adding a <code>for</code> loop to both methods. Note that after each tile layer is added to the map there is the invocation of <code>setZIndex(layer.zIndex)</code>. Leaflet relies on a <a href="https://en.wikipedia.org/wiki/Z-order" title="z-order"><var>z</var>-index</a> to specify the order in which layers are rendered. The appropriate <var>z</var>-index is stored in the <code>zIndex</code> property of each layer.</p><code data-gist-id="7617222d6946b5d817dd849ae5bd9a08" data-gist-file="carto_basemap_and_labels.js" data-gist-line="22-37"></code> <h2>Tweaking the <code>basemap()</code> function</h2><p>Next, consider the <code>basemap()</code> factory function. Its parameters are the Carto/Leaflet map, a label to use in the user interface, and the tile layer to encapsulate, and creates a new object from the basemap prototype.</p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.js" data-gist-line="34-53"></code><p>Accommodating multiple tile layers in the <code>basemap()</code> factory is as simple as allowing the <code>layers</code> parameter to be either a single tile layer or an array of tile layers. First, the function checks whether the <code>layers</code> argument is an array; if it is not, it converts it to an array with 1 element (lines 40&ndash;42). Next, it sets a <code>zIndex</code> property on each layer in ascending order relative to their position in the <code>layers</code> argument. This means that each element in the <code>layers</code> array will be drawn on top of all previous elements in the array (lines 43&ndash;45).</p><code data-gist-id="7617222d6946b5d817dd849ae5bd9a08" data-gist-file="carto_basemap_and_labels.js" data-gist-line="39-64"></code> <h2>The list of basemaps</h2><p>Now that our basemap prototype and factory can handle multiple tile layers, let&rsquo;s throw some labels on top of a Google imagery layer. Carto hosts a variety of label-only layers, so we&rsquo;ll use one of those. Thanks to the modifications we&rsquo;ve made, it&rsquo;s as simple as passing an array to the <code>basemap()</code> function.</p><code data-gist-id="7617222d6946b5d817dd849ae5bd9a08" data-gist-file="carto_basemap_and_labels.js" data-gist-line="103-112,123-124"></code> <h2>Bringing it all together</h2><p>You can Fiddle around with a working compound basemap selector below.</p><script async src="//jsfiddle.net/karldickman/n80zg4rr/embed/"></script> <h2>Why would you do such a thing?</h2><p>Sometimes a basemap with just one tile layer just won&rsquo;t cut it.</p> <h2>Other posts in this series</h2><ul><li><a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">Introduction</a></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-map-factory.html">Map factory</a></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-custom-zoom-buttons.html">Custom zoom buttons</a></li><li><a href="http://blog.karldickman.us/2017/10/angular-carto-switching-basemaps.html">Switching basemaps</a></li><li><strong>Compound basemaps</strong></li></ul>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-46844633373648131312017-10-01T10:33:00.000-07:002017-10-07T10:22:48.257-07:00Angular Carto: Switching Basemaps<p>This post is part of a series covering how to create reusable Carto map components. Read the <a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">introduction</a> to learn why one would even want to do such a thing. In this post, we will discuss how to give the user control of the basemap and how to do some customizations on the basemap selector.</p> <h2>Manipulating the basemap</h2><p>Before we begin, we need to ask ourselves: what is a basemap, and what does it do? In the context of a Carto map, a basemap is a layer of map tiles that sits under the informational layers. In order to be able to switch between different basemaps, each basemap should know how to add itself to the Carto map and how to remove itself from the Carto map.</p><p>This functionality is implemented in the basemap prototype, cleverly named <code>basemapProto</code>. The prototype has two properties and two methods: <dl><dt><code>tileLayer</code></dt><dd>The Leaflet tile layer for the basemap.</dd><dt><code>map</code></dt><dd>The Carto/Leaflet map whose basemap is to be manipulated.</dd><dt id="basemapProto.addToMap"><code>addToMap()</code><dd>Add the basemap to the Carto/Leaflet map object.</dd><dt id="basemapProto.removeFromMap"><code>removeFromMap()</code></dt><dd>Remove the basemap from the Carto/Leaflet map object.</dd></dl></p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.js" data-gist-line="22-32"></code> <p>Now that we&rsquo;ve defined a prototype for the basemaps, we need a way of building new basemaps from the prototype. To do this, we can define a factory function, cleverly named <code>basemap</code>. This function takes three parameters: <dl><dt><code>map</code></dt><dd>The Carto/Leaflet map whose basemap is to be manipulated.</dd><dt><code>label</code></dt><dd>A descriptive label for the map to be used in the user interface.</dd><dt><code>tileLayer</code></dt><dd>The Leaflet tile layer for the basemap.</dd></dl></p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.js" data-gist-line="34-53"></code> <h2>What are controllers?</h2><p>We&rsquo;ve written code to change the basemap, but we still need to build a user interface that calls this code. We will do this by writing a <strong>controller</strong> for basemap selection. Somewhat confusingly, the most common way of using Angular controllers is actually an example of the <strong>Model-View-View Model</strong> (<strong>MVVM</strong> for short) user interface architecture. Consequently, you will often see the phrases &ldquo;controller&rdquo; and &ldquo;view model&rdquo; used interchangeably. To avoid confusion, I will generally stick with &ldquo;controller&rdquo; when referring to an Angular component.</p><p>My favorite guide to the MVVM design pattern remains <a href="https://martinfowler.com/eaaDev/PresentationModel.html">Martin Fowler&rsquo;s</a>, despite being over a decade old as of this writing. <blockquote><p>The essence of a [view model] is of a fully self-contained class that represents all the data and behavior of the UI window, but without any of the controls used to render that UI on the screen. A view then simply projects the state of the [view model] onto the glass.</p><p>To do this the [view model] will have data fields for all the dynamic information of the view. This won&rsquo;t just include the contents of controls, but also things like whether or not they are enabled. In general the [view model] does not need to hold all of this control state (which would be lot) but any state that may change during the interaction of the user. So if a field is always enabled, there won&rsquo;t be extra data for its state in the [view model].</p><p>Since the [view model] contains data that the view needs to display the controls you need to synchronize the [view model] with the view.</p></blockquote></p> <h3>Projecting the state onto the glass</h3><p>Before we discuss the implementation of the controller, it will be useful to discuss how Angular &ldquo;projects the state of the [controller] onto the glass.&rdquo; The controller exposes two properties: <dl><dt><code>basemaps</code></dt><dd>The list of basemaps available for the user to select.</dd><dt><code>selectedBasemap</code></dt><dd>The currently selected basemap.</dd></dl>We can use Angular&rsquo;s <code>ng-options</code> directive to bind the options in a drop-down box to the <code>basemaps</code> property. Let&rsquo;s break down the meaning of the <a href"https://docs.angularjs.org/api/ng/directive/ngOptions" title="ngOptions"><code>ng-options</code></a> expression in the sample code; somewhat confusingly, the expression is read right-to-left: <ul><li><code>basemap in ctrl.basemap</code> means that the options in the drop-down box are bound to each of the items in the controller&rsquo;s <code>basemaps</code> property. Within the expression each item in the list of basemaps is aliased as <code>basemap</code>.</li><li><code>basemap as basemap.label</code> means that when projected on the glass, the <code>label</code> property of the basemap will be displayed to the user.</li></ul></p><p>The Angular <a href="https://docs.angularjs.org/api/ng/directive/ngModel" title="ngModel"><code>ng-model</code></a> directive binds the currently selected item in the drop-down box to the <code>selectedBasemap</code> property of the controller.</p><p>To sum up, the <code>ng-options</code> and <code>ng-model</code> directives ensure that the available options in the drop-down box are bound to the controller&rsquo;s <code>basemaps</code> property, and the selected option is bound to the <code>selectedBasemap</code> property.</p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.html" data-gist-line="20-21"></code> <h3>The state that is to be projected</h3><p>The function that creates basemap controller&rsquo;s is cleverly named <code>basemapController()</code>. It takes one parameter: a list of basemaps for the <code>basemaps</code> property of the controller. Delegating the <code>basemaps</code> property to a parameter of the <code>basemapController()</code> function enhances code reusability. The logic for switching between basemaps is the same for every map we build, but the list of available basemaps is likely to vary from map to map.</p><p>The <code>selectedBasemap</code> property has a more complicated implementation. The property setter (line 68 below) first checks whether a basemap is currently selected; if so, it removes that basemap from the map by calling its <a href="#basemapProto.removeFromMap" title="basemapProto.removeFromMap()"><code>removeFromMap()</code></a> function and sets the basemap&rsquo;s <code>isSelected</code> property to <code>false</code>. Next, it adds the newly selected basemap to the map by calling its <a href="#basemapProto.addToMap" title="basemapProto.addToMap()"><code>addToMap()</code></a> function and sets its <code>isSelected</code> property to <code>true</code>. Finally, it saves the newly selected basemap in the backing store of the property.</p><p>Last of all, if no basemap is selected the map will be unbelievably boring, so the <code>basemapController()</code> function selects the first basemap in the list before returning the controller (lines 85&ndash;87).</p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.js" data-gist-line="55-90"></code> <h2>The list of basemaps</h2><p>For this example, we will make three basemaps available for selection: Google imagery, <a href="http://www.openstreetmap.org/">OpenSteetMap</a>, and the <a href="https://www.arcgis.com/">ArcGIS</a> world topo map. To construct the tile layers, we use Leaflet&rsquo;s <a href="http://leafletjs.com/reference-1.2.0.html#tilelayer" title="TileLayer"><code>L.tileLayer()</code></a> function. The available list of basemaps is fully customizable by returning a different list from the <code>getBasemaps()</code> function.</p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.js" data-gist-line="92-111"></code> <h2>Register the basemap components</h2><p>To get the basemap selection feature up and running, we will have to register everything with Angular. We register the <code>getBasemaps()</code> function as a factory under the name &ldquo;basemaps&rdquo;. The <code>basemapController()</code> creation function is registered as a controller under the name &ldquo;basemapController.&rdquo; Thanks to Angular dependency injection, Angular will resolve the <code>basemaps</code> parameter of the <code>basemapController</code> function by looking up the &ldquo;basemaps&rdquo; name, which we registered previously.</p> <code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.js" data-gist-line="1-2,19-20"></code> <h2>Calling the basemap controller from the HTML</h2><p>To use the basemap controller, we use the <a href="https://docs.angularjs.org/api/ng/directive/ngController" title="ngController"><code>ng-controller</code></a> directive to indicate that a particular controller should be used for an HTML element. The <code>ng-controller</code> expression <code>BasemapController as ctrl</code> indicates that Angular should use whatever controller is registered under the name &ldquo;BasemapController&rdquo;, and that the alias <code>ctrl</code> should be used within that HTML element to refer to the controller.</p><code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.html" data-gist-line="18,20-21,26"></code> <h3>Customizing the appearance of the basemap selector</h3><p>A dropdown list is not the only choice available for controlling basemap selection. Another option is to use the <a href="https://docs.angularjs.org/api/ng/directive/ngRepeat" title="ngRepeat"><code>ng-repeat</code></a> directive to make a stack of buttons instead. The astute reader will note that the basemap&rsquo;s <code>isSelected</code> property is not used by the dropdown, but is used by the button repeater.</p> <code data-gist-id="7969b747c4fcb852e226e98424569b71" data-gist-file="carto_basemap_selector.html" data-gist-line="18,23-26"></code> <h2>Bringing it all together</h2><p>You can Fiddle around with a working Angular Carto basemap selector below.</p><script async src="//jsfiddle.net/karldickman/8y8hp4yv/embed/"></script> <h2>Why would you do such a thing?</h2><p>I don&rsquo;t want to have to rewrite the logic for selecting basemaps from scratch every time, especially because the only thing that ever changes is the list of basemaps, not the selection logic. Do you want to?</p> <h2>Design pattern bingo</h2><ul><li>Angular controller</li><li>Angular dependency injection</li><li>Angular provider (factory)</li></ul> <h2>Other posts in this series</h2><ul><li><a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">Introduction</a></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-map-factory.html">Map factory</a></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-custom-zoom-buttons.html">Custom zoom buttons</a></li><li><strong>Switching basemaps</strong></li></ul>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-33587670600508443842017-06-28T17:40:00.000-07:002017-10-05T11:55:24.664-07:00Angular Carto: Custom Zoom Buttons<p>This is part of a series covering how to create reusable Carto map components. Read the <a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">introduction</a> to learn why one would even want to do such a thing. Read the previous installment, <a href="http://blog.karldickman.us/2017/06/angular-carto-map-factory.html">Carto Map Factory</a>, to learn about adding a Carto map to a webpage and registering the map with the Angular dependency injector.<p><p>In this post, we will discuss how to add custom zoom buttons to the map.</p> <h2>What are directives?</h2><p>We will implement our custom zoom buttons by encapsulating them in an Angular directive. Directives are a technique for packaging up bundles of HTML content and JavaScript code. Once a directive has been registered in your Angular module, it can be interpolated into the HTML of your web page, most commonly as an HTML element or as an attribute on a standard element. A good use case for directives is a text field with a date picker. The date picker should pop up a window with a navigable calendar, allow the user to browse through the calendar to find the date they want, and then save the date in the text field attached to the date picker. Additionally, the ideal date picker should be reusable throughout a website with a minimum of effort on the part of the programmer.</p><p>If directives are a new concept to you, I recommend Sandeep Panda&rsquo;s &ldquo;<a href="https://www.sitepoint.com/practical-guide-angularjs-directives/">A Practical Guide to AngularJS Directives</a>.&rdquo; <h2>The zoom buttons directive</h2><h3>Registering the directive</h3><p>Directives are added to Angular modules using the <a href="https://docs.angularjs.org/guide/directive#creating-directives"><code>directive</code></a> function. The first argument is the name under which we are registering the directive; the second argument is a factory function for creating instances of the directive. Note that the registered name of the directive, <code>zoomButtons</code>, is <a href="http://en.wikipedia.org/wiki/Camel_case">camel-cased</a>.</p><code data-gist-id="849923cbf4b03678418637cfcb6c9d47" data-gist-file="carto_custom_zoom.js" data-gist-line="1-2,24-25,44-45"></code><p>Note that in this sample code, the directive factory is an anonymous function, but you can (and perhaps should!) define a named function in a site-wide library and register the named function wherever zoom buttons are needed. Note also that the directive factory takes a parameter named <code>map</code>. At run time, the Angular dependency injector will pass whatever is registered under the name &ldquo;map&rdquo; as an argument to the directive factory. For more information about registering a Carto map with the Angular dependency injector, please see my previous post &ldquo;<a href="http://blog.karldickman.us/2017/06/angular-carto-map-factory.html">Map Factory</a>.&rdquo;</p> <h3>Restricting calling style</h3><p>Angular provides several different ways of calling a directive from HTML. The two most common are element style (<code>&lt;zoom-buttons&gt;&lt;/zoom-buttons&gt;</code>) and attribute style (<code>&lt;div zoom-buttons&gt;&lt;/div&gt;</code>). All calling styles produce the same results, so the Angular team recommends choosing the calling style to signal how the directive is used. <blockquote><strong>When should I use an attribute versus an element?</strong> Use an element when you are creating a component that is in control of the template. The common case for this is when you are creating a Domain-Specific Language for parts of your template. Use an attribute when you are decorating an existing element with new functionality.</blockquote>To allow those two calling styles, we specify <code>A</code> (for attribute-style) and <code>E</code> (for element-style) in the <code>restrict</code> property of the directive. There are other directive calling styles, but it is not necessary to discuss them here.</p><code data-gist-id="849923cbf4b03678418637cfcb6c9d47" data-gist-file="carto_custom_zoom.js" data-gist-line="24-27,44-45"></code> <h3>Writing HTML to be interpolated</h3><p>Next, we need to define an HTML template for the content that will be interpolated into the web page when the directive is invoked.</p><p>Each directive has its own <code>$scope</code>. If you are not familiar with <code>$scope</code>, for the purposes of this article it is best understood as the <a href="https://namitamalik.github.io/MVC-and-MVVM-with-AngularJS/">view model</a> for an Angular component; in this case, <code>$scope</code> is the view model for the zoom buttons directive. The <code>ng-click</code> data binding and double-brace string interpolation are bound to methods and properties on this directive&rsquo;s <code>$scope</code>.</p><code data-gist-id="849923cbf4b03678418637cfcb6c9d47" data-gist-file="zoom-buttons-template.html"></code><p>This directive defines two buttons for zooming in and out. When clicked, the buttons call, respectively, the <code>zoomIn()</code> and <code>zoomOut()</code> functions on the <code>$scope</code>. The labels on the buttons are likewise defined in the <code>zoomInLabel</code> and <code>zoomOutLabel</code> properties on the <code>$scope</code>. Finally, to ensure that the caller of the directive has control over the appearance of the buttons, their <code>class</code> and <code>style</code> attributes are bound to the <code>buttonClass</code> and <code>buttonStyle</code> properties of the <code>$scope</code>.</p><p>You can define your HTML template either using a string literal, or by pulling it into a separate file if it is too unwieldy to manage within a string literal. Beware: the sample code below shows both techniques, but you should pick one or the other.</p><code data-gist-id="849923cbf4b03678418637cfcb6c9d47" data-gist-file="carto_custom_zoom.js" data-gist-line="24-31,44-45"></code> <h3>Configuring the directive <code>$scope</code></h3><p>When configuring a directive, we define a <code>link()</code> function that configures the directive <code>$scope</code>. The <code>link()</code> function is takes information from the directive invocation in the web page and translates that into the <code>$scope</code> required by the HTML template.</p><code data-gist-id="849923cbf4b03678418637cfcb6c9d47" data-gist-file="carto_custom_zoom.html" data-gist-line="18-24"></code><code data-gist-id="849923cbf4b03678418637cfcb6c9d47" data-gist-file="carto_custom_zoom.js" data-gist-line="24-27,29,32-45"></code><p>The first parameter of the <code>link()</code> function is the <code>$scope</code> to be configured. The second parameter is the HTML element on which the directive was invoked. The third parameter is the attributes of said element. In this particular <code>link()</code> function, information from the attributes are used to set the label and styling properties on the <code>$scope</code>. Note that the <code>$scope.zoom*()</code> functions are set to be <code>map.zoom*.bind(map)</code>. Why not just set them to <code>map.zoom*</code> instead? Because the <code>map.zoom*</code> functions contain a variety of references to <strong><code>this</code></strong>. If you use <code>$scope.zoom* = map.zoom*</code>, those <strong><code>this</code></strong> references will be treated as referring to <code>$scope</code> rather than <code>map</code>. Using <code>$scope.zoom* = map.zoom*.bind(map)</code> binds the zoom methods so that they will still treat their <strong><code>this</code></strong>es as the map rather than the scope.</p> <h2>Bringing it all together</h2><p>You can Fiddle around with a working Angular Carto map with custom buttons below.</p><script async src="//jsfiddle.net/dahwtLn2/embed/"></script> <h2>Why would you do such a thing?</h2><p>Carto/Leaflet maps come with a built-in zoom control. We had to explicitly turn it off with the option <code>zoomControl: false</code>. What&rsquo;s so great about writing our own control in an Angular directive instead of using the built-in control? The main reason is that it gives us control over the look-and-feel of the zoom controls. If the built in Leaflet controls clash with the styling we&rsquo;re using in the rest of the site, we can create buttons with the same functionality but a more appropriate appearance. Still not convinced? That&rsquo;s okay. You&rsquo;ve learned a lot about Angular directives, and that will serve you well in the rest of the series.</p> <h2>Other posts in this series</h2><ul><li><a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">Introduction</a></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-map-factory.html">Map factory</a></li><li><strong>Custom zoom buttons</strong></li><li><a href="http://blog.karldickman.us/2017/10/angular-carto-switching-basemaps.html">Switching basemaps</a></li></ul>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-51384151138239760142017-06-02T17:49:00.002-07:002017-10-05T11:54:51.544-07:00Angular Carto: Map Factory<p>This is part of a series covering how to create reusable Carto map components. Read the <a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">introduction</a> to learn why one would even want to do such a thing.</p><p>In this post, we will discuss how to add a Carto map to a website and how to register the map with Angular so that our Angular components can manipulate the map display.</p> <h2>Reference the scripts</h2><p>Before jumping into your new Carto map, you will first need to make sure that your web page has references to the Carto and Angular javascript libraries. In order for the map to tile correctly, you will also have to reference Carto&rsquo;s standard stylesheet.</p><code data-gist-id="c6d187070bcab1b85952754a4ce8b87c" data-gist-file="carto_map_factory.html" data-gist-line="5-9"></code> <h2>Sizing web page and containers</h2><p>If you&rsquo;re looking for an immersive map that takes up the entire web page, you will need to make sure that the <code>html</code> and <code>body</code> elements and the map container are all styled to fill all space available to them. My preferred method is to define a site-wide style implementing those requirements, including a <code>carto-map-container</code> CSS class that can be applied to the element where the Carto map is inserted.<p><code data-gist-id="c6d187070bcab1b85952754a4ce8b87c" data-gist-file="carto_map_factory.css"></code> <h2>Creating a container for the map</h2><p>The map is inserted in a placeholder <code>div</code> element. You will need to assign that element an <code>id</code>. This <code>id</code> will later be passed to Carto to indicate where the map will be created. You will also need to assign the container <code>div</code> to the <code>carto-map-container</code> CSS class, which we defined above to expand to fill all space available. Experience has shown me that the map container <code>div</code> must be the first child of the <code> body</code> element for Carto to work correctly in Internet Explorer.</p><code data-gist-id="c6d187070bcab1b85952754a4ce8b87c" data-gist-file="carto_map_factory.html" data-gist-line="14-17"></code> <h2>Registering a map factory with Angular</h2><p>In a vanilla Carto web page, adding a map is as simple as instantiating the <code>L.map</code> class. (Technically, this is a <a href="http://leafletjs.com/reference-1.0.3.html#map">Leaflet</a> class, but the distinction is not relevant to the present post.) The complication of using Angular is that we will be building Angular components that manipulate the map, so we need a reliable way for those components to find the Leaflet/Carto map object. The method Angular uses for this is <a href="https://docs.angularjs.org/guide/di">dependency injection</a>. As we build angular components throughout this series, they will all take a parameter named <code>map</code> as a parameter. The Angular dependency injector will inspect each component&rsquo;s constructor and provide the map object registered under the name &ldquo;map&rdquo; as the argument to the <code>map</code> parameter.</p><p>To register the map with Angular, we will register an anonymous function that instantiates and configures the map as <a href="https://docs.angularjs.org/guide/providers#factory-recipe">factory</a> under the name &ldquo;map&rdquo;. (The many options and functions to customize Leaflet/Carto map objects are beyond the scope of this post, so review the <a href="http://leafletjs.com/reference-1.0.3.html#map">Leaflet documentation</a> if you need to learn more.) Once another Angular component requests the map by having a parameter named &ldquo;map&rdquo; in its constructor, Angular will invoke the anonymous function to build the map, and store the resulting value to provide for all future requests of the map. In other words, the map creation function is called only once.</p><p>You should also note that there is another dependency injection at work in this code. The first argument of the <code>L.map</code> initializer is the element ID of the Carto map container. Rather than providing this ID as a string literal, map factory takes a parameter <code>mapContainerID</code>. The actual element ID is registered with the Angular dependency injector using the <a href="https://docs.angularjs.org/guide/providers#value-recipe"><code>value</code></a>. Putting the dependency injector in control of where the map is created loosens the coupling between the map factory and the HTML.</p> <code data-gist-id="c6d187070bcab1b85952754a4ce8b87c" data-gist-file="carto_map_factory.js" data-gist-line="1-25"></code> <h2>Bringing it all together</h2><p>In a normal application where there&rsquo;s at least one component that requires the map, all we would have to do is register the map factory. However, the example code doesn&rsquo;t have any Angular components, so we need to request the map from the Angular dependency injector ourselves. You can safely ignore the <code>window.onload</code> handler in the sample code, because having at least one map-dependent Angular component on your page will obviate the need for it.</p><p>You can Fiddle around with a working Angular Carto map below.</p><script async src="//jsfiddle.net/juzavoph/embed/"></script> <h2>Why would you do such a thing?</h2><p>Why are we registering an anonymous function as an Angular factory, then jumping through hoops to get the Angular dependency injector to invoke the registered function? Why not just instantiate and configure the Leaflet map and be done with it? Good question! The example code provided in this post is definitely more complicated than necessary for the task of putting a map on a web page. Dependency injection shines when we have a complicated application with many components that manipulate the map. Over the course of this series, I think you will begin to see what I mean.</p> <h2>Design pattern bingo</h2><ul><li>Dependency injection</li><li>Angular provider (factory)</li></ul> <h2>Other posts in this series</h2><ul><li><a href="http://blog.karldickman.us/2017/05/angular-carto-introduction.html">Introduction</a></li><li><strong>Map factory</strong></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-custom-zoom-buttons.html">Custom zoom buttons</a></li><li><a href="http://blog.karldickman.us/2017/10/angular-carto-switching-basemaps.html">Switching basemaps</a></li></ul> <h2>Revision history</h2><ul><li>2017-06-06: The example code in this page originally passed the element ID <code>carto-map</code> of the Carto map container as a string literal to the map initialization function <code>L.map</code>. That was poor Angular style and has been rectified.</li></ul>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-68153417303018668592017-05-31T09:09:00.001-07:002017-10-05T11:54:40.584-07:00Angular Carto: Introduction<p>If you work with geospatial data and haven't had a chance to work with <a href="http://www.carto.com/">Carto</a>, you are missing out. Carto is a platform for creating interactive geospatial visualizations on the web. The canned maps that you can build from the web-based designer are surprisingly powerful, especially if you are already familiar with <a href="http://en.wikipedia.org/wiki/SQL">SQL</a> and <a href="http://en.wikipedia.org/wiki/Cascading_Stylesheets">CSS</a>. If you are a proficient web programmer, you can use their <a href="https://carto.com/docs/carto-engine/carto-js">JavaScript API</a> to customize your map in virtually any way you can imagine.</p><p>Carto hits a sweet spot of simplicity and flexibility that suits me nicely. I work on a team whose job is to help our clients make sense of data. The efficiency with which we can produce Carto web applications frees up our time to add value in other areas.</p><p>As great as Carto is, one problem that is becoming more pressing is that we're making a lot of the same maps on different data sets. Consequently, we're starting to do a lot of <a href="https://en.wikipedia.org/wiki/Copy_and_paste_programming">copy-and-paste code reuse</a>. Over the next year, we will be refactoring essential map functionality into reusable components to make setting up and customizing a new map even more efficient. Our framework of choice for this project is <a href="https://angularjs.org/">Angular</a>.</p><p>Angular is a JavaScript framework for developing dynamic web pages. It has a variety of features that interest me, including:</p><ul><li><a href="https://en.wikipedia.org/wiki/Deep_linking">Deep linking</a></li><li><a href="https://namitamalik.github.io/MVC-and-MVVM-with-AngularJS/">Model-View-ViewModel</a> user interface architecture. (My favorite general description of the MVVM architecture remains Martin Fowler&rsquo;s &ldquo;<a href="https://martinfowler.com/eaaDev/PresentationModel.html">Presentation Model</a>.&rdquo;)</li><li>Unit testing</li></ul><p>Fundamentally, though, what appeals to me about Angular is that you can use it to encapsulate up a bunch of low-level DOM manipulations into higher level routines that better fit how I think about the behavior of a web page.</p><p>As we package the our Carto functionality into Angular components, I will be blogging through the techniques that we used at each step. This introduction will also server as the index for the series as it progresses. Thanks for reading.</p><h2>Index</h2><ul><li><strong>Introduction</strong></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-map-factory.html">Map Factory</a></li><li><a href="http://blog.karldickman.us/2017/06/angular-carto-custom-zoom-buttons.html">Custom zoom buttons</a></li><li><a href="http://blog.karldickman.us/2017/10/angular-carto-switching-basemaps.html">Switching basemaps</a></li></ul>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-682587128748501602015-09-19T02:06:00.000-07:002015-09-23T16:39:53.525-07:00Scheme SucksYou will never get read without an eye-grabbing headline.<br /><br />My beef with Schema arose while working through a set of programming problems that are published online. I was interested in using those problems to familiarize myself with the idioms of <a href="http://en.wikipedia.org/wiki/Scheme%20(programming%20language)">Scheme</a> and <a href="http://en.wikipedia.org/wiki/Haskell%20(programming%20language)">Haskell</a>, with which I am less familiar. The exercise in question asks for the sum of all Fibonacci numbers that do not exceed 10000 and are divisible by 2. For the purposes of this post, the Fibonacci sequence is defined by a recurrence relation: \[ \begin{align} F(0) &amp;= 0 \\ F(1) &amp;= 1 \\ F(n) &amp;= F(n - 2) + F(n - 1). \\ \end{align} \] In an imperative language such as <a href="http://en.wikipedia.org/wiki/C%20(programming%20language)">C</a>, this problem can be solved with a program similar to the following one. The logic of this program mimics how a person might solve the problem with a pencil, paper, and a pocket calculator: it keeps a running total of the even Fibonacci numbers as they are computed.<br /><br /><script src="https://gist.github.com/karldickman/1accd8ce0cb20ee8ecf0.js"></script>This is the kind of code I could write in my sleep, which is why I am interested in exploring the functional languages. In a purely functional language such as Haskell, there is (loosely speaking) no state. Consequently, the standard looping construct is recursion. The code example below makes use of the convenient fact that the even Fibonacci numbers can be described by a recurrence relation of their own:<br />\[ \begin{align} F(0) &amp;= 0 \\ F(3) &amp;= 2 \\ F(n) &amp;= F(n-6) + 4F(n-3). \\ \end{align} \] <script src="https://gist.github.com/karldickman/b66b66230e27ffe168f0.js"></script>It will be helpful to discuss this function line-by-line. <br /><ol><li>Base case. The sum of Fibonacci numbers divisible by 2 and not exceeding 0 is 0.</li><li>Base case. The sum of Fibonacci numbers divisible by 2 and not exceeding 1 is 0.</li><li>Recursive case. For limits greater than 1, uses a helper function to accumulate the sum.</li><li value="5">Definition of the helper function that accumulates the sum. The arguments to the helper function are the previous even Fibonacci number $F(n-6)$, the current even Fibonacci number $F(n-3)$, and the sum up to this point.</li><li>If the next even Fibonacci number exceeds the limit, then the sum of the sequence is the sum up to this point.</li><li>If the next even Fibonacci number does not exceed the limit, then the accumulator function is invoked recursively with the current Fibonacci number, the next Fibonacci number, and the new total.</li><li>Recurrence relation for the even Fibonacci numbers, as above.</li></ol>I can write a very similar algorithm in Scheme. Like in Haskell, the function uses a helper function to accumulate the sum of the sequence recursively.<br /><br /><script src="https://gist.github.com/karldickman/2318d458ecc33761fc7d.js"></script>So far, so good. I've worked out how to code a the solution to the problem recursively in two different functional programming languages. Now, let's get to the fun stuff. The solution to this problem can be expressed much more succinctly by defining a sequence of even Fibonacci numbers and using the <code><a href="http://hackage.haskell.org/package/base-4.8.1.0/docs/Prelude.html#v:takeWhile">takeWhile</a></code> function to get the entries that do not exceed the limit.<br /><br /><script src="https://gist.github.com/karldickman/c63af16d71e66ceac964.js"></script>The list of even Fibonacci numbers <code>evenFibs</code> is constructed beginning with the first two even Fibonacci numbers: $F(0)=0$ and $F(3)=2$. Once the first two members of the sequence are present, the rest of the sequence is populated using <code><a href="http://hackage.haskell.org/package/base-4.8.1.0/docs/Prelude.html#v:zipWith">zipWith</a></code>. In functional programming, the <code>zip</code> function takes two lists and returns the corresponding pairs in the list. For example, <code>zip([1, 2], ['a', 'b'])</code> returns <code>[(1, 'a'), (2, 'b')]</code>. The function <code>zipWith</code> calls a projection function on each corresponding pair and adds the result of the projection function to the list instead. For example, <code>zipWith (+) [1, 4] [3, 2]</code> returns <code>[4, 6]</code>, with the projection function being addition ($+\colon \mathbb{R} \times \mathbb{R} \rightarrow \mathbb{R}$). The list <code>evenFibs</code> is constructed by zipping the list with itself so that each element is paired with its previous element. All you need to do is specify the recurrence relation for even Fibonacci numbers as the projection function to <code>zipWith</code>, and you can generate as many items in the sequence as are needed.<br /><br />Once the sequence of even Fibonacci numbers has been defined, the <code>takeWhile</code> function can be used to pull numbers from the sequence while they do not exceed the limit. The first parameter to <code>takeWhile</code>, <code>&lt;= limit</code>, is a predicate to check that an entry in the sequence does not exceed the limit. The <code>sum</code> function is then used to compute the sum of the entries extracted by <code>takeWhile</code>.<br /><br />This approach works for many programming languages that draw on the functional tradition, including ones like C# and Python that are more often used in an imperative style.<br /><br /><script src="https://gist.github.com/karldickman/7aa5b0836150e6b53ae2.js"></script>Now, let's try writing this in Scheme. Unfortunately, in Scheme sequences of undefined size (like the Haskell lists and <a href="https://msdn.microsoft.com/en-us/library/9k7k7cf0.aspx">C#</a> and Python <a href="https://wiki.python.org/moin/Generators">generators</a>) are a different data type than sequences of defined size. The latter are called lists, and are the most common data structure in Scheme. The former are called <a href="http://srfi.schemers.org/srfi-41/srfi-41.html">streams</a>. I expected I could just define a Fibonacci stream and apply the Scheme <code>take-while</code> function to it. MIT Press has a nice <a href="https://mitpress.mit.edu/sicp/full-text/sicp/book/node71.html">article</a> explaining how to define a Fibonacci stream, so I stole some code from there.<br /><br /><script src="https://gist.github.com/karldickman/d4cc72e5dc020e0201f9.js"></script>Unfortunately, the many functions in Scheme that operate on lists will not work on streams, so you have to use the stream versions instead (<code>stream-take-while</code>, <code>stream-fold</code>, etc.).<br /><pre><br />karl@adenauer$ racket -f bad-fibo-sum-stream.scm<br />null-list?: argument out of domain #&lt;stream&gt;<br /></pre>This is quite disappointing. Unlike Haskell, Python, and C#, Scheme needs to define two libraries with identical semantics depending on whether you need to work with a sequence of determinate or indeterminate length. Consider this the first reason that scheme sucks. The second reason is the ubiquitous linked list data structure. Adding an item to the end of a linked list is an $\Theta(n)$ operation. This means that building a list like the Fibonacci sequence from a recurrence relation is a $\Theta(n^2)$ operation. To get around this limitation, you have to construct the sequence backwards, and then reverse it.<br /><br /><script src="https://gist.github.com/karldickman/0e07347035a3fd2e3d8a.js"></script>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-80758333035344462502015-02-04T21:38:00.000-08:002015-02-04T21:38:55.699-08:00Rhetorical bestiary: Survey dataSurvey data is well known to be an imperfect measure of the truth. The many pitfalls of survey data mean that the numbers must be taken with some healthy skepticism.<br />Evidence-free assertions that black people are three times more dishonest than white people in answering surveys about drug use do not a healthy skepticism make. <blockquote class="twitter-tweet" lang="en"><p><a href="https://twitter.com/voxdotcom">@voxdotcom</a> These figures based on self-reported drug use are notoriously unreliable. I thought it was your job to report &quot;context&quot;?</p>&mdash; Billy Chav (@billy_chav) <a href="https://twitter.com/billy_chav/status/563204943390052352">February 5, 2015</a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-75843934023903369672014-12-14T03:03:00.000-08:002014-12-14T03:05:22.554-08:00Drivers Obeying the Law, Part III was biking South down Ladd towards the stoplight at Division, when I heard the Suburban behind me pull around to try a pass. I was going at 25 mph, and there was another car that had just turned off of Division and was heading North in the opposing lane. Once I saw that there was oncoming traffic, I knew there was no way the Suburban could make the pass without causing a head-on collision. But he made the pass anyway! The other car had to slam on their brakes; the right taillight of the Suburban passed a foot from my handlebars.<br /><br />The stoplight at Division was red, so I caught him seconds after he passed me. I tapped on his window and said that he had passed too close. He had given me only a foot, and the minimum passing distance is my fall height (6 ft). He said that he had been "completely in the other lane," and that I should ride further over. Again, I was riding 25 mph--the speed limit--and had I been riding any further over I would have risked getting doored by a person stepping out of a parked car. He then said to me:<br /><br /><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204,204,204); margin: 0px 0px 0px 0.8ex; padding-left: 1ex;">If you want to be a stickler for the rules, just remember that I'm driving a 7,000 pound vehicle, and you weigh maybe 180 pounds. That's <i>your</i> choice.</blockquote><div><br /></div><div>Remember, I did not slow him down in any way. The light was red while he was passing me. It remained red long enough for me to catch him and exchange several sentences at the stoplight. He gained no time whatsoever. He broke at least two laws and put my body and my life in danger--and the bodies and lives in the car coming towards us--for literally no reason at all. When called out on it insisted that it is my responsibility to stay out of his way.</div><div>Tonight's incident won't be in any crash statistics, but that doesn't mean that Clinton and Ladd are safe places to bike. This guy's attitude is too common on Portland bikeways. Drivers almost never allow enough travel distance to complete a pass safely, and end up risking head-on collisions, almost sideswiping bike riders, or both.</div>You would think that riding the speed limit would stop unsafe passes, but it doesn't. I routinely get honked at, passed too closely, or brake checked. I've even had to endure all three in close succession! I've been honked at going 20 in a 20 on Clinton and on NE 37th; I've been honked at doing 30 in a 30 on SW Steele. I've been passed too closely on the big hill on Woodstock Blvd., while biking 10 over the speed limit! I can't even imagine what it is like out there for people who ride at a gentler pace than I do.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-26294268044565769932014-12-13T15:57:00.001-08:002014-12-13T15:59:16.164-08:00Alan Dershowitz is an America-hating Bleeding-heart LiberalAbout 8 years ago, I remarked to my eye doctor that maybe Alan Dershowitz's torture warrant idea wasn't such a bad one if the alternative was no accountability at all. Apparently he thought Dershowitz was an America-hating bleeding heart liberal, though, because he launched into a rant about how the CIA isn't stupid, they know that torture can produce unreliable information, and they always verify torture intelligence against other information gathered. (Other highlights: the ticking bomb scenario proves that using torture to gather intelligence is always justified; we don't know what is going on, so therefore no one should oppose it.) <br />Now that we have the Senate report, we know that my eye doctor was hopelessly naive. The CIA did indeed take intelligence gathered under torture as gospel, sometimes to disastrous ends—nearly letting bin Laden's driver get away, torturing innocent people whose names were given up under torture, etc. <br />I guess I shouldn't be surprised. What would an eye doctor from Bend, Oregon know about the CIA's torture program?Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-13640237617610866762014-12-13T15:18:00.000-08:002014-12-13T15:28:43.887-08:00Torture vs. American ExceptionalismMitt Romney, in <i>No Apology: The Case for American Greatness</i>: <br /><blockquote class="tr_bq">I make no apology for my conviction that America's economic and military leadership is not only good for America but also critical for freedom and peace around the world. (Page 2)<br />... What's chilling to consider is that if America is <i>not</i> the superpower, others will take our place. What nation or nations would rise, and what would be the consequences for our safety, freedom, and prosperity?<br />The world is a safer place when America is strong....<br />... The very existence of American power helps to hold tyrants in check and reduces the risk of precipitous war. (Page 10)<br />... No nation has shed more blood for more noble causes than the United States. Its beneficence and benevolence are unmatched by any nation on earth, and by any nation in history.<br />Abraham Lincoln understood that the destiny of the world was twined to the destiny of America. It is why he called the United States the "last, best hope of earth." It is still so. As citizens of America, we should be filled with love and gratitude for what this country has been, for what it is, and for what it can still be. (Page 33)<br />... I'm one of those who believe America is destined to remain as it been [sic] since the birth of the Republic<span class="st">—</span>the brightest hope of the world. And for that belief I do not apologize. (Page 34)</blockquote>Findings from the recently released torture report, as summarized by the <a href="http://www.washingtonpost.com/wp-srv/special/national/cia-interrogation-report/key-findings/?hpid=z2">Washington <i>Post</i></a> (emphasis added):<br /><blockquote class="tr_bq">[A]ccording to CIA records, seven of the 39 CIA detainees known to have been subjected to the CIA's enhanced interrogation techniques produced no intelligence while in CIA custody. CIA detainees who were subjected to the CIA's enhanced interrogation techniques were usually subjected to the techniques immediately after being rendered to CIA custody. Other detainees provided significant accurate intelligence prior to, or without having been subjected to these techniques. <b>While being subjected to the CIA's enhanced interrogation techniques and afterwards, multiple CIA detainees fabricated information, resulting in faulty intelligence. Detainees provided fabricated information on critical intelligence issues, including the terrorist threats which the CIA identified as its highest priorities.</b><br />... CIA officers regularly called into question whether the CIA's enhanced interrogation techniques were effective, assessing that the use of the techniques failed to elicit detainee cooperation or produce accurate intelligence. <br /><hr />The CIA never conducted a credible, comprehensive analysis of the effectiveness of its enhanced interrogation techniques.... <br />There are no CIA records to indicate that any of the reviews independently validated the "effectiveness" claims presented by the CIA, to include basic confirmation that the intelligence cited by the CIA was acquired from CIA detainees during or after the use of the CIA's enhanced interrogation techniques. Nor did the reviews seek to confirm whether the intelligence cited by the CIA as being obtained "as a result" of the CIA's enhanced interrogation techniques was unique and "otherwise unavailable," as claimed by the CIA, and not previously obtained from other sources. <br /><hr />More broadly, the program caused immeasurable damage to the United States' public standing, as well as to the United States' longstanding global leadership on human rights in general and the prevention of torture in particular.</blockquote>Kevin Drum's <a href="http://www.motherjones.com/kevin-drum/2014/12/senate-report-we-tortured-prisoners-it-didnt-work-and-we-lied-about-it">summary</a> of the torture program seems apt (emphasis added):<br /><blockquote class="tr_bq">The torture was far more brutal than we thought, and the CIA lied about that. It didn't work, and they lied about that too. <b>It produced so much bad intel that it most likely <i>impaired</i> our national security</b>, and of course they lied about that as well. They lied to Congress, they lied to the president, and they lied to the media.</blockquote>Dick Cheney has an entirely different <a href="http://www.washingtontimes.com/news/2014/dec/9/dick-cheney-on-cia-report-its-all-a-bunch-of-hooey/#ixzz3LozbmdFg">take</a> on the matter:<br /><blockquote class="tr_bq">[T]he techniques used by the Bush White House—like water boarding—were “absolutely, totally justified,” and hardly akin to torture.<br />“They deserve a lot of praise,” [Cheney] said, referring to the CIA, The Hill reported. “As far as I’m concerned, they ought to be decorated, not criticized.”<br />He also said that waterboarding and similar tactics were the “right thing[s] to do, and if I had to do it over again, I would do it. When we had that program in place, we kept the country safe from any more mass casualty attacks, which was our objective,” The Hill reported.</blockquote>Cheney's argument on torture is simple: America's first duty is to protect Americans, and that which protects American's is justified. Everyone should have a sliver of sympathy for this argument, even if they reject Cheney's conclusion that his torture program was justified. But this ends-justify-the-means reasoning undermines Mitt Romney's proclamation that "[America']s beneficence and benevolence are unmatched by any nation on earth, and by any nation in history." America tortured people, brutally, without gaining any useful intelligence. America tortured innocent people, brutally, because of faulty intelligence that came from torture. Is this beneficent? Is it benevolent? If you wonder why there are so many skeptics of American exceptionalism, the Senate's torture report might have some answers.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-70744910797251831632014-12-01T21:02:00.004-08:002014-12-02T12:28:53.726-08:00Solidarity for me, but not for theeOn November 14, Portland's KGW TV station <a href="http://www.kgw.com/story/news/local/2014/11/24/portland-officers--post-i-am-darren-wilson-badges/70047440/">reported</a> that "Portland Police Chief [Mike Reese] on Monday ordered three officers to remove 'I am Darren Wilson' images from their Facebook pages." Reese's order was not without controversy:<br /><blockquote class="tr_bq">Maybe the Portland officers where [sic] expressing their rights of free speech when showing solidarity with their brother? [<a href="http://bikeportland.org/2014/11/26/ferguson-equity-active-transportation-114020#comment-5890294">1</a>] <br /><hr />I think that what they are saying is that they don't support&nbsp;the lynching of a white police officer without benefit of due process, a trial or even charges being&nbsp;brought forward.... [<a href="http://www.oregonlive.com/portland/index.ssf/2014/11/readers_react_to_portland_poli.html">2</a>]</blockquote>On November 30, six members of the St. Louis Rams entered the field with their hands up in the air, in the "don't shoot" position, protesting everything that has happened in Ferguson over the last few months. The St. Louis County Police Officers Association was not amused. From the official statement by the SLPOA:<br /><blockquote class="tr_bq">The St. Louis Police Officers Association is profoundly disappointed with the members of the St. Louis Rams football team who chose to ignore the mountains of evidence released from the St. Louis County Grand Jury this week and engage in a display that police officers around the nation found tasteless, offensive and inflammatory…</blockquote>From SLPOA Business Manager Jeff Roorda: <br /><blockquote class="tr_bq">I know that there are those that will say that these players are simply exercising their First Amendment rights. [Blah blah blah]</blockquote>Jamilah Lemieux of <i>Ebony </i>magazine has an excellent <a href="http://www.ebony.com/news-views/rams-players-put-hands-up-st-louis-police-054#.VHy">commentary</a> on the statement issued by the SLPOA. Read the whole thing. I will merely remark on this: if you are a black person, showing solidarity with a boy who was killed is "tasteless, offensive, and inflammatory." Indeed, it is so far outside of the bounds of civilized discourse that not even invoking the First Amendment can justify it. By contrast, if you are a "white police officer," expressing solidarity with the man who killed that boy is not just understandable, but beyond criticism.<br />UPDATE: In addition to believing that the First Amendment does not allow for criticism of police officers, Jeff Roorda apparently also believes that the First Amendment allows police officers abuse their position to <a href="http://www.slate.com/blogs/the_slatest/2014/12/02/st_louis_police_called_boss_of_twitter_critic_leigh_maibes.html">bully and intimidate their critics</a>.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-57117869568290565342014-11-26T15:14:00.002-08:002014-11-26T15:38:02.310-08:00Two ShootingsOn April 17, 2005, during an interrogation, Esteban Carpio shot and killed police detective James L. Allen of Providence, RI. Carpio was re-arrested 45 minutes later. He was punched in the face three times by police detective Christopher Zarella, breaking bones in Carpio's face.<br /><a href="https://www.youtube.com/watch?v=tp1_Ql-meOo">Comments</a> on Carpio:<br /><ul><li>The streets are not like a court room. There is such thing as street justice, which compensates for the crimes that are not paid for by the legal justice system.</li><li>That's what he fucking gets.﻿</li><li>He brought that upon himself﻿</li><li>Should have let the family's of the people he killed&nbsp;go at him, I promise it would have been much worse. Sympathy&nbsp;sorry we're all out here. </li><li>Cops should be commended. He walked into the court alive even after shooting a cop. Now that is something!</li><li>Bet the two people he killed are still dead...﻿ </li><li>Justice bitches... &nbsp;maybe you shouldn't shoot people in the face﻿</li><li>This dude took a mans life away. He desevered to be killed. Hopefully he looses sight, can't talk, and spends his life in jail.﻿</li><li>Bet the cop still has no face and a family torn apart by this persons attempt at flight. What bothers me is now taxes have to pay to house this fool. He should have been taken out. Eye for an eye as in Old Testament fashion.</li><li>This footage makes me feel all warm inside. &nbsp;I am so glad he got beat like that...yes, yes..yes... because he is an animal!!!! &nbsp;Kill him, smash him tare him apart. &nbsp;I hope the cops do this to all these scum bags!!!﻿</li><li>He got A well deserved beating,they should have not stopped and finished him off'.I can't find one good reason for scum like this to be kept alive,let the taxpayer's money go to something worth while.</li></ul>In Ferguson, Missouri, on August 9, 2014, police officer Darren Wilson shot and killed Michael Brown, an unarmed teenager. Evidence about the shooting was presented to a grand jury, which on November 24 decided not to indict officer Wilson of any crime. In the aftermath of the grand jury decision, residents of Ferguson protested, both violently and nonviolently:<br /><ul><li><a href="http://www.nationalreview.com/article/393495/justice-ferguson-editors"><i>National Review</i></a>: There is clearly significant racial tension in Ferguson. But the best way to resolve it is<i>...</i> by working peacefully through the available democratic mechanisms.... [T]he grand jury resisted the mammoth political pressure to indict strictly to assuage racial grievances, instead opting to follow the evidence. When it comes to justice, that is as much as any American can hope for.</li><li><a href="http://www.nationalreview.com/article/393511/deep-ignorance-ferguson-ian-tuttle">Ian Tuttle</a>: There is in fact a law in Missouri that “protects and values” not just Michael Brown’s life but every life — namely, statutes that punish homicide and manslaughter. A grand jury, weighing the evidence, determined that Darren Wilson did not transgress those laws.... As a body politic, perhaps Ferguson should not “move on,” but, legally, Darren Wilson is not a criminal according to the law of his home state, and to punish him as if he were one would be to dismiss the law as illegitimate. That serves no one.</li><li><a href="http://www.nationalreview.com/corner/393430/thoughts-tonight-jonah-goldberg">Jonah Goldberg</a>: I can’t muster sympathy for the looters, car-burners, the dress-up Bolsheviks and that ilk.... Michael Brown’s family ... should be applauded for their honorable and responsible public statements against violence and rioting.</li><li><a href="http://www.oregonlive.com/opinion/index.ssf/2014/11/the_cosby_show_kathleen_parker.html#incart_opinion">Kathleen Parker</a>: We see in Ferguson, Mo., what happens when respect for our legal process is lost: Arsonists and looters expressed their outrage that a grand jury didn't act as they thought it should.... Ferguson is what you get when mob rule overwhelms the rule of law, which was created as the defense of civilized people against the mob.</li><li><a href="http://www.oregonlive.com/portland/index.ssf/2014/11/third_ferguson_protest_planned.html#incart_river">David Koller</a>: Michael Brown got what he deserved. &nbsp;Justice was served.</li><li>The problem with protests in general is they do nothing but create inconvience...and in some cases damage and injury. &nbsp; The real way to pressure for change is to work through the government, who were elected to govern and who can actually change things.</li><li>all I see is a bunch of troublemakers that cover their faces like it was Halloween.</li><li>Why is it that the lowest common denominator, the thugs, get so much press and support. Oh wait, it's other thugs and lowlifes who support them. My bad.</li><li>The Grand Jury heard the facts and read the testimony - that's law.&nbsp; What we're now witnessing is criminal trespass, vandalism and maybe homicide. Lock em up!</li><li>Civil Disobediance used to mean something constructive, now it's just garden variety thuggery.</li><li>They didn't want justice. They wanted&nbsp; a lynching. If they had gotten a lynching they would have demanded Wilson burned at the stake. If they had gotten that they would have rioted looted and burned anyway. It's what they do. It's all they can ever do.&nbsp; What you saw on the streets of Ferguson is the uncivilized gutter trash of society.</li><li>The moral principle they're fighting for seems to be, if you don't like a justice system ruling, you have the right to act like a pack of insanely rabid jackals and loot burn and destroy everything you can to show your displeasure. The philosophy of the Ferguson maniacs is about as far from Dr Martin Luther King as Adolf Hitler but by the looks of the cowardly punks destroying private property in the name of justice, very few of them would even know who Dr King was, let alone be intelligent enough to emulate his methods.</li><li>For all the folks who are giving the “black community has no other voice other than to commit acts of senseless violence crowd”, anarchy is anarchy. What about the Caucasian community in California who are now technically a minority? If a Caucasian was shot by a latino officer under similar circumstances, is burn baby burn OK? If every aggrieved community is given the go ahead to burn down the town, that is what we will have. [<a href="http://bikeportland.org/2014/11/26/ferguson-equity-active-transportation-114020#comment-5890294">1</a>] </li><li>Let's all have a peaceful protest.&nbsp; What is the protest about? Racism? Poverty? Rule of law?&nbsp; Desire to loot a licka sto?</li></ul><ul></ul>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-59769650340368655972014-11-26T12:57:00.002-08:002014-11-26T12:57:35.899-08:00Overlawyering, Part IIShorter <a href="http://www.oregonlive.com/opinion/index.ssf/2014/11/the_cosby_show_kathleen_parker.html#incart_opinion">Kathleen Parker</a>: Having a personal opinion about whether Bill Cosby is a rapist is a violation of his due process rights. Blog posts and tweets must meet the same evidentiary standards as a criminal conviction. Also, FERGUSON!Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-66400798024515379062014-11-01T13:02:00.003-07:002014-11-01T13:04:15.945-07:00Even Prime FallacyThe simplest possible <b>Even Prime Fallacy</b> is shown below:<br /><blockquote class="tr_bq"><b>Salviati</b>: Most prime numbers are odd.<br /><b>Simplicio</b>: Two is even! Your argument completely falls apart.</blockquote>We may express this idea more formally:<br /><blockquote class="tr_bq"><b>Salviati</b>: <i>p</i> is sometimes true.<br /><b>Simplicio</b>: Yes, but <i>p</i> is sometimes false! Your argument completely falls apart.</blockquote>Simplicio has failed to disprove Salviati, not because Simplicio's rebuttal is illogical or irrelevant, but because it is literally the exact same argument as the one Salviati made! "<i>p</i> is sometimes false" is an inevitable logical consequence of "<i>p</i> is sometimes true."<br />Someone who invokes an even prime fallacy probably thinks of an argument as "words you say in response to words someone else says," rather than as an exercise in logic.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-10654857459976837022014-10-06T20:05:00.002-07:002014-12-14T03:05:38.854-08:00Today in Drivers Obeying the Law...<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div>The sign says <b>NO TURN ON RED</b>. It very clearly indicates what lanes you are legally allowed to turn into.<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-SjrA1ICeDNc/VDNXgT2dY8I/AAAAAAAAC4Y/e4iF2K5TiZU/s1600/Bus%2BMall%2BTurn%2BSignal.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-SjrA1ICeDNc/VDNXgT2dY8I/AAAAAAAAC4Y/e4iF2K5TiZU/s1600/Bus%2BMall%2BTurn%2BSignal.png" /></a></div><br />Naturally, the car in front of me turns, on red, into a lane in which it is not allowed. He joins a veritable parade of cars illegally blocking the transit lanes, for what purpose I cannot discern. Further up the street, a car honks at a bus pulling away from the bus stop, even though the car is breaking the law by being in a transit lane. Behind me, a train has to slow to a crawl. The trains take a full block to come to a stop, so the operator has to hit the brakes early to avoid crushing all the cars parked on the tracks.<br />Drivers think the law is very important, which is why they always obey it.<br /><br />Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-65496197641530678002014-10-04T17:04:00.000-07:002014-10-04T17:04:57.456-07:00Consent Schmonsent<a href="http://theweek.com/article/index/269164/the-big-problem-with-californias-new-sexual-consent-law"><span class="byline">Shikha Dalmia</span></a>:<br /><blockquote class="tr_bq">At any given moment, one person wants sex more passionately than the other. What's more, whether due to nurture or nature, there is usually a difference in tempo between men and women, with women generally requiring more "convincing." And someone who requires convincing is not yet in a position to offer "affirmative" much less "enthusiastic" consent. That doesn't mean that the final experience is unsatisfying—but it does mean that initially one has to be coaxed out of one's comfort zone. Affirmative consent would criminalize that.</blockquote>I am finding it next to impossible to read this passage in any other way than "women just need to be raped a little bit or they won't want to have sex." It is deeply, deeply creepy. Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-49962547372525796052014-09-23T10:29:00.002-07:002014-09-23T10:29:37.313-07:00Rhetorical Bestiary: Free Speech is Censorship<a href="https://www.insidehighered.com/news/2014/09/22/salaita-case-illustrates-two-cultures-academe-many-experts-say">Alan Dershowitz</a>: <br /><blockquote class="tr_bq">I would bet anything that 99 percent of the people who are demanding that [Salaita] be restored tenure would be on the exact opposite side of this if he’d been making pro-Israel but equally uncivil statements.</blockquote>Hypocrisy about free speech is universal. Even among Supreme Court justices, who are supposed to be non-ideological, Epstein, Parker, and Segal found a <a href="http://www.nytimes.com/2014/05/06/us/politics/in-justices-votes-free-speech-often-means-speech-i-agree-with.html">strong tendency</a> to support the free speech rights of their ideological brethren and oppose the free speech rights of their ideological opponents. No doubt your average Joe is even less principled than Scalia, Ginsburg, or Kennedy.<br />If free speech hypocrisy is so banal, why make so much of it? The argument goes something like this:<br /><ol><li>Supporters of <i>X</i>'s right to say <i>p</i> claim they care about free speech rights.</li><li>Were <i>X</i> saying ¬<i>p</i>, <i>X</i>'s current supporters would not defend his free speech rights.</li><li>Therefore, censorship is good! P.S., I am not a crackpot.</li></ol>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-61788449088339601232014-08-16T10:53:00.001-07:002014-08-16T10:53:20.081-07:00Clinton Street: Still Too ScaryTwo weeks ago, Bike Portland ran a story on Portland's Clinton St. bike boulevard. It included a quote from <a href="http://www.portlandoregon.gov/transportation/">PBOT</a> traffic safety specialist Greg Raisman:<br /><blockquote class="tr_bq">Our safety performance [on bike boulevards] over time has been excellent. 70 percent of our streets are residential. Less than 20 percent of bike and pedestrian crash activity happens there. … There’s comfort factors that are important in how many cars are on the road. But from a pure safety perspective, the big threat is where you’re crossing the busy streets.</blockquote>Immediately after finishing the article, I hopped on my bike and rode down Clinton to go to dinner with my girlfriend and her coworkers. Just after I passed 43rd Ave. heading toward Chavez, I saw a group of three cyclists heading in the opposite direction with a Subaru following close behind. I kept my eye on the Subaru, because dangerous passing is a daily occurrence on Clinton. Suddenly and without warning, the car swerved into my lane and started heading straight for me. I had to steer hard to the right, almost colliding with a parked car; the Subaru passed within a foot of my handlebar.<br />I have been bike commuting for thirteen years, and this is by far the scariest thing that has ever happened to me on my bike. I am thankful to have escaped without injury, but I worry even more about other riders. I had two or three seconds at most to react before a collision happened. What if it had been my girlfriend? She's newer to cycling and can't steer as tightly as I can. What if she hit her brakes too hard and lost control of her bike? What if she avoided the head-on but slammed into a parked car at 15 mph? What about an 8 year old or an 80 year old?<br />As harrowing as this incident was, this isn't the first close call I've had on Clinton. I've lost count of the number of times I've had to dart off the road to avoid a head-on. I ride Clinton between 51st and 21st to get to work, and not a day goes by without a dangerous pass or two in the morning and another couple in the evening. I applaud Raisman for bringing crash data to the table, but in this case the data can't possibly measure the risk properly. There is an epidemic of aggressive, dangerous driving on Clinton. The only reason why it's not showing up in the crash data is because (thank God) it's been near misses so far. Sooner or later, one of those near misses won't be a miss at all. I am quite certain that if a less skilled rider had been on Clinton that night you'd have read about the crash in the <i>Oregonian</i>, not on some insignificant blog.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-34045834400807096552014-08-11T18:22:00.000-07:002014-08-11T18:22:07.634-07:00Reverence for the LawPatrick George was <a href="http://jalopnik.com/never-speed-in-virginia-lessons-from-my-three-days-in-1613604053">caught</a> driving 93 in a 55. He doesn't think he should be accountable, though:<br /><blockquote class="tr_bq">I didn't hurt anyone, or kill anyone, or sell drugs, or drive drunk, or beat my wife, or steal[.]</blockquote>Next time someone yells at you for rolling your bike through a stop sign, try using Mr. George's excuse. I'm sure your interlocutor will find it persuasive.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-35734413178252189122014-08-10T21:12:00.000-07:002014-08-10T21:13:15.424-07:00OverlawyeringAlmost incidentally to his main point about the firing of Steven Salaita, Scott Lemieux <a href="http://www.lawyersgunsmoneyblog.com/2014/08/yes-steven-salaita-fired-defensible">wrote</a>:<br /><blockquote class="tr_bq">Whether he had signed all the paperwork might be relevant to his <i>legal</i> remedies, but from that standpoint of norms and ethics the job was his[.]</blockquote>All too often the law is used to narrow a discussion as much as possible. Salaita didn't have a contract signed, nothing to see here, move along. None of Dylan Farrow's allegations against Woody Allen have been proven beyond a reasonable doubt in a court of law, nothing to see here, move along.<br />Couple <a href="http://koin.com/2014/07/02/cantankerous-sandy-ridge-trail-couple-arrested/">arrested</a> for repeatedly threating mountain bikers at a dedicated mountain bike trail system with mace and a gun. <a href="http://bikeportland.org/2014/07/02/mtb-news-roundup-arrests-new-trail-sandy-ridge-new-shop-portland-108137#comment-5134185">Nothing to see here</a>. <a href="http://bikeportland.org/2014/07/02/mtb-news-roundup-arrests-new-trail-sandy-ridge-new-shop-portland-108137#comment-5149495">Move along</a>.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-48887659255893312972014-05-26T12:09:00.001-07:002014-05-26T12:09:11.079-07:00Freedom Is SlaveryRobert Birgenau on violence against protesters:<br /><blockquote class="tr_bq">It is unfortunate that some protesters chose to obstruct the police by linking arms and forming a human chain to prevent the police from gaining access to the tents. This is not nonviolent civil disobedience.</blockquote>Robert Birgenau on violence against himself:<br /><blockquote class="tr_bq">[A]s a long time civil rights activist and firm supporter of non-violence, I do not respond to violent, untruthful verbal attacks.</blockquote>I cannot imagine a definition of "violence" under which being held responsible for an assault <i>that you ordered</i> is more violent than pepper spray and nightsticks. Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-77862961455659169782014-05-20T10:13:00.001-07:002014-05-20T10:13:08.844-07:00Rhetorical Bestiary: iPhoneIt is a truth universally acknowledged that every old dude who has ever complained about kids fiddling with iPhones spends about 88% of his time fiddling with his iPhone.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0tag:blogger.com,1999:blog-813089255631103050.post-15771765937078435682014-04-08T19:36:00.000-07:002014-04-08T19:46:15.946-07:00Rhetorical Bestiary: The Perfect Number of TeethIf you do not accept the theory of evolution, I will probably not change your mind. However, I hope I can convince you not to offer this as an anti-evolution argument:<br /><blockquote class="tr_bq">We have the perfect number of teeth to fit in our mouths. While creationism perfectly accounts for that result, evolutionism predicts a contrary result: As our faces evolved from chimpanzee-like faces to human faces, the shortening of the muzzle would have caused the teeth to become badly overcrowded in the front of the mouth.</blockquote><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-KiLvjfbj-04/U0SycO-6FsI/AAAAAAAABPQ/h100eeMDEvE/s1600/Braces_girlsmiling.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-KiLvjfbj-04/U0SycO-6FsI/AAAAAAAABPQ/h100eeMDEvE/s1600/Braces_girlsmiling.jpg" height="400" width="265" /></a></div>Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com1tag:blogger.com,1999:blog-813089255631103050.post-7707630594337224742014-04-08T19:16:00.000-07:002014-04-08T19:41:54.753-07:00Rhetorical Bestiary: The Myth of Graded QuantifiersSalviati: Most prime numbers are odd.<br />Simplicio: Two is even! Your argument completely falls apart.Karl Dickmanhttp://www.blogger.com/profile/14356032704587914010noreply@blogger.com0