<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>NashCoding</title>
	<atom:link href="http://www.nashcoding.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.nashcoding.com</link>
	<description>Yet Another Artificial Intelligence Blog</description>
	<lastBuildDate>Fri, 28 Oct 2011 05:45:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Hacker News Needs Honeypots</title>
		<link>http://www.nashcoding.com/2011/10/28/hackernews-needs-honeypots/</link>
		<comments>http://www.nashcoding.com/2011/10/28/hackernews-needs-honeypots/#comments</comments>
		<pubDate>Fri, 28 Oct 2011 00:01:49 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[HackerNews]]></category>
		<category><![CDATA[Social News]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=428</guid>
		<description><![CDATA[There has been a lot of recent debate regarding how to improve quality control on HackerNews (HN), and to his credit, Paul Graham (pg) has tried a lot of tactics. There is a very clear set of HN guidelines, which very few members these days probably read. For a while, pg tried playing around with [...]]]></description>
			<content:encoded><![CDATA[<p>There has been a lot of recent debate regarding how to improve quality control on <a href="https://news.ycombinator.com">HackerNews</a> (HN), and to his credit, Paul Graham (pg) has tried a lot of tactics. There is a very clear set of <a href="http://ycombinator.com/newsguidelines.html">HN guidelines</a>, which very few members these days probably read. For a while, pg tried playing around with the karma formula and, even if I disagree about <a href="http://www.nashcoding.com/2011/08/23/how-karma-should-be-measured/">the way karma should be measured</a>, at least he gave it an effort. He also hid comment karma from everyone but the author, to help slow the <a href="http://blog.effectcheck.com/2011/05/31/do-social-news-sites-deteriorate/">demonstrable deterioration</a> of the discussion section; apparently this has been successful in pg's observations. Nevertheless, I do believe that we are seeing a continuing trend downward in overall article quality on the front page<sup class='footnote'><a href='#fn-428-1' id='fnref-428-1'>1</a></sup>.</p>
<p>In this post, I present a <a href="http://en.wikipedia.org/wiki/Honeypot_(computing)">honeypot</a> approach to combating group-think and quality deterioration in article selection on social news sites.<span id="more-428"></span></p>
<h2>Article Honeypots</h2>
<p>A honeypot is an article that is link-bait or otherwise in direct violation of the site's guidelines, but is intentionally submitted by an admin as a test to see if users inappropriately upvote it<sup class='footnote'><a href='#fn-428-2' id='fnref-428-2'>2</a></sup>. For each user, three scores are tracked: the number of honeypots seen, the number of honeypots upvoted, and the number of honeypots flagged. A user's seen count increments when they load a page with a honeypot article displayed<sup class='footnote'><a href='#fn-428-3' id='fnref-428-3'>3</a></sup>. If a user upvotes one of the honeypots, their upvoted score is incremented; if the user flags the honeypot, their flagged score is increment. We then take the ratio of the difference of the flagged and upvoted scores, and the seen score to get a honeypot ratio, h:</p>
<p><center><img src='http://s.wordpress.com/latex.php?latex=h%28u%29%20%3D%20%5Cfrac%7Bf_%7Bu%7D%20-%20v_%7Bu%7D%7D%7Bs_%7Bu%7D%7D&#038;bg=ffffff&#038;fg=000000&#038;s=4' alt='h(u) = \frac{f_{u} - v_{u}}{s_{u}}' title='h(u) = \frac{f_{u} - v_{u}}{s_{u}}' class='latex' /></center></p>
<p>where:</p>
<p><img src='http://s.wordpress.com/latex.php?latex=u&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='u' title='u' class='latex' /> is the target user<br />
<img src='http://s.wordpress.com/latex.php?latex=f_%7Bu%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{u}' title='f_{u}' class='latex' /> is the number of honeypots the user flagged<br />
<img src='http://s.wordpress.com/latex.php?latex=v_%7Bu%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='v_{u}' title='v_{u}' class='latex' /> is the number of honeypots the user upvoted<br />
<img src='http://s.wordpress.com/latex.php?latex=s_%7Bu%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='s_{u}' title='s_{u}' class='latex' /> is the total number of honeypots seen by the user</p>
<p>This produces a ratio in the range [-1,1]. We may want to punish people who excessively flag everything, otherwise they'll always have a max h score<sup class='footnote'><a href='#fn-428-4' id='fnref-428-4'>4</a></sup>:</p>
<p><center><img src='http://s.wordpress.com/latex.php?latex=h%28u%29%20%3D%20%5Cfrac%7Bf_%7Bu%7D%20-%20v_%7Bu%7D%7D%7Bs_%7Bu%7D%7D%20-%20%281%20-%20%5Cfrac%7Bf_%7Bu%7D%7D%7Bt_%7Bu%7D%2B1%7D%29&#038;bg=ffffff&#038;fg=000000&#038;s=4' alt='h(u) = \frac{f_{u} - v_{u}}{s_{u}} - (1 - \frac{f_{u}}{t_{u}+1})' title='h(u) = \frac{f_{u} - v_{u}}{s_{u}} - (1 - \frac{f_{u}}{t_{u}+1})' class='latex' /></center></p>
<p>where:</p>
<p><img src='http://s.wordpress.com/latex.php?latex=t_%7Bu%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='t_{u}' title='t_{u}' class='latex' /> is the total number articles a user has flagged</p>
<p>The range of this h-ratio is [-2,1). However, because <img src='http://s.wordpress.com/latex.php?latex=t_%7Bu%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='t_{u}' title='t_{u}' class='latex' /> is very likely going to be much larger than <img src='http://s.wordpress.com/latex.php?latex=f_%7Bu%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f_{u}' title='f_{u}' class='latex' /> for every user, we would expect that no user will ever receive a score near 1 in practice. If the h-ratio of a user is less than an admin-specified threshold, we flag the user as detrimental to the overall quality of the site and their upvotes would either be discounted or ignored entirely.</p>
<h2>Implicit Honeypots</h2>
<p>Since it's not always feasible to expect admins to find or label honeypots, it would be nice to have some way to crowdsource honeypots implicitly. To do this, we take the top N users, ranked by their explicit honeypot ratio, and label them as "super flaggers". For each article, we track the percentage of super flags they've received and if this percentage is above an admin-specified threshold, we automatically label that article as a honeypot:</p>
<pre class="brush:python">
function getSuperFlaggers(honeypots, users, superFlaggersCount):
    # Order users by their honeypot ratio, in descending order
    ranked_users = users.sort(u => u.honeypotRatio)

    return ranked_users.subset(0, superFlaggersCount)

function isHoneypot(article, threshold, superFlaggers):
    count = 0
    seen = 0
    foreach sf in supperFlaggers:
        seen += 1 if seen(sf, article)
        count += 1 if flagged(sf, article)
    percent = count / seen
    return percent >= threshold
</pre>
<p>It would make sense to check this value every time an article hits a certain number of upvotes. One would also likely want to ensure that <tt>seen</tt> has reached a high enough value to be significant before checking. If an article is labeled as a honeypot, then all users who have already seen the article should have their <img src='http://s.wordpress.com/latex.php?latex=h&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='h' title='h' class='latex' /> values retroactively updated.</p>
<h2>Conclusion</h2>
<p>The above post presented two reasonable approaches to improving the quality of the front page on social news sites like HackerNews. Social news sites have long been believed to suffer from the deterioration over time, with <a href="http://blog.effectcheck.com/2011/05/31/do-social-news-sites-deteriorate/">recent evidence</a> supporting that belief. While anecdotal evidence suggests hiding comment karma has helped improve discussion quality, article selection quality has remained largely unchanged<sup class='footnote'><a href='#fn-428-5' id='fnref-428-5'>5</a></sup>. The honeypots approach I described above may help ebb the flow of upvotes to link-bait and inappropriate articles by enabling the community to moderate itself implicitly.</p>
<p>If you liked this article, please <a href="https://news.ycombinator.com/item?id=3166209">vote it up on HackerNews</a>. Assuming you think it meets the quality guidelines. <img src='http://www.nashcoding.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h5>Footnotes</h5>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-428-1'>For instance, see <a href="http://news.ycombinator.com/item?id=3145330">this front-page article</a> from 10/23/11. <span class='footnotereverse'><a href='#fnref-428-1'>&#8617;</a></span></li>
<li id='fn-428-2'>In practice, it may be more reasonable for admins to label user submissions that they see hit the front page and are judged as violating the guidelines. <span class='footnotereverse'><a href='#fnref-428-2'>&#8617;</a></span></li>
<li id='fn-428-3'>If multiple honeypots are displayed, the count is incremented by the number of honeypots seen for the first time by the user. <span class='footnotereverse'><a href='#fnref-428-3'>&#8617;</a></span></li>
<li id='fn-428-4'>Technically, this is only true if they flag everything and upvote nothing. <span class='footnotereverse'><a href='#fnref-428-4'>&#8617;</a></span></li>
<li id='fn-428-5'>The exception here may be voting ring and other clique detection algorithms. However, such algorithms are designed to prevent manipulation of the system rather than enforcing quality guidelines. <span class='footnotereverse'><a href='#fnref-428-5'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2011/10/28/hackernews-needs-honeypots/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>How Karma Should Be Measured</title>
		<link>http://www.nashcoding.com/2011/08/23/how-karma-should-be-measured/</link>
		<comments>http://www.nashcoding.com/2011/08/23/how-karma-should-be-measured/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 23:46:12 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[HackerNews]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=390</guid>
		<description><![CDATA[Measuring karma was a heavily-debated topic for a while on HackerNews. The goal is to provide some measurement that both accurately measures overall contribution to the community and encourages consistent engagement. Several solutions were discussed and a few were even tried. For example, pg tried to replace the overall karma score with an average score. [...]]]></description>
			<content:encoded><![CDATA[<p>Measuring karma was a heavily-debated topic for a while on <a href="http://news.ycombinator.com">HackerNews</a>. The goal is to provide some measurement that both accurately measures overall contribution to the community and encourages consistent engagement. Several solutions were discussed and a few were even tried. For example, pg tried to replace the overall karma score with an average score. All three combinations (total only, average only, and both) were juggled around in the top right corner, until eventually the simple total was used.</p>
<p>While all these attempts were good ideas, I think there is an even better metric that should be used here: the <a href="http://en.wikipedia.org/wiki/Sharpe_ratio">Sharpe ratio</a>.<span id="more-390"></span></p>
<h1>Risk adjusted returns</h1>
<p>When you look to invest in an asset, it's often important to consider the risk of an investment as well as the overall historical returns. Assuming you have no external knowledge of the asset, looking at the volatility of its returns is a pretty good estimate of risk. Ideally, you'd like to see super high returns with no volatility&ndash; just a steady stream of money rolling in day after day.<sup class='footnote'><a href='#fn-390-1' id='fnref-390-1'>1</a></sup> The Sharpe ratio is a way to combine the returns of an asset and its historical risk into a single number.</p>
<p>Simply defined, the Sharpe ratio is the return of the asset minus the risk free rate, all divided by the standard deviation of returns. For instance, if we have an asset which has returned an average of 10% per year and an annualized volatility of 20%, and we assume that we could park our money in a savings account for a risk-free 1% per year, then the Sharpe ratio for this asset is (10 - 1) / 20 = 0.45.</p>
<h1>Naive Sharpe karma</h1>
<p>How does this translate to a social news site like HackerNews? First, let's consider each user to be an investable asset. Each time a comment or story submission is made, that user is generating a return.<sup class='footnote'><a href='#fn-390-2' id='fnref-390-2'>2</a></sup> Since each comment starts with a default score of 1, let's go ahead and make that the risk free rate of return. So the karma metric I'm proposing would be:</p>
<p><center><img src='http://s.wordpress.com/latex.php?latex=f%28x%29%20%3D%20%5Cfrac%7B%5Csum%5Climits_%7Bi%3D1%7D%5E%7Bn%5E%7Bx%7D%7D%7B%28k%5E%7Bx%7D_%7Bi%7D%20-%201%29%7D%7D%7Bn%5E%7Bx%7D%5Csigma%5E%7Bx%7D%7D&#038;bg=ffffff&#038;fg=000000&#038;s=4' alt='f(x) = \frac{\sum\limits_{i=1}^{n^{x}}{(k^{x}_{i} - 1)}}{n^{x}\sigma^{x}}' title='f(x) = \frac{\sum\limits_{i=1}^{n^{x}}{(k^{x}_{i} - 1)}}{n^{x}\sigma^{x}}' class='latex' /></center></p>
<p>where:<br />
<img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /> is the user<br />
<img src='http://s.wordpress.com/latex.php?latex=n%5E%7Bx%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='n^{x}' title='n^{x}' class='latex' /> is the number of comments for user <img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /><br />
<img src='http://s.wordpress.com/latex.php?latex=k%5E%7Bx%7D_%7Bi%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='k^{x}_{i}' title='k^{x}_{i}' class='latex' /> is the karma score for the ith comment of user <img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /><br />
<img src='http://s.wordpress.com/latex.php?latex=%5Csigma%5E%7Bx%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\sigma^{x}' title='\sigma^{x}' class='latex' /> is the standard deviation of the karma scores for user <img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /></p>
<p>In programmer-speak, the pseudo-code for this is<sup class='footnote'><a href='#fn-390-3' id='fnref-390-3'>3</a></sup>:</p>
<pre class="brush:c-sharp">
function karmaSharpe(user) {
    if(user.comments.length == 0)
         return 0;

    var numerator = 0;
    foreach(var comment in user.comments)
         numerator += (comment.karma - 1) / user.comments.length;

    var denominator = stdev(x => user.comments.karma);
    if(denominator < 1)
        denominator = 1;

    return numerator / denominator;
}
</pre>
<h1>A better metric</h1>
<p>The Sharpe ratio is certainly an improvement over the previous two metrics. Totals give a very low-fidelity view of the user's contribution and averages make no distinction between consistent, high-quality members and more skewed users who have a couple really highly-upvoted submissions. The Sharpe ratio addresses both of these shortcomings by including an additional dimension in the calculation: volatility.</p>
<p>The metric is still not perfect, however. A good metric would include time in the formula, since a high-quality user would be consistently contributing <i>every day</i>. An improved metric is below:</p>
<p><center><img src='http://s.wordpress.com/latex.php?latex=f%28x%29%3D%5Cfrac%7B%5Csum%5Climits_%7Bi%3D1%7D%20%20%5E%7Bd%5E%7Bx%7D%7D%20%20%7B%20%20%20%20%28%5Csum%5Climits_%7Bj%3D1%7D%20%20%20%20%20%20%20%20%5E%7Bg%5E%7Bx%7D_%7Bi%7D%7D%20%20%20%20%20%20%20%20%7B%5Cfrac%7Bk%5E%7Bx%7D_%7Bij%7D-1%7D%7Bg%5E%7Bx%7D_%7Bi%7D%7D%7D%20%20%20%20%20-1%29%7D%7D%20%20%7Bd%5E%7Bx%7D%5Csigma%5E%7Bx%7D%7D&#038;bg=ffffff&#038;fg=000000&#038;s=4' alt='f(x)=\frac{\sum\limits_{i=1}  ^{d^{x}}  {    (\sum\limits_{j=1}        ^{g^{x}_{i}}        {\frac{k^{x}_{ij}-1}{g^{x}_{i}}}     -1)}}  {d^{x}\sigma^{x}}' title='f(x)=\frac{\sum\limits_{i=1}  ^{d^{x}}  {    (\sum\limits_{j=1}        ^{g^{x}_{i}}        {\frac{k^{x}_{ij}-1}{g^{x}_{i}}}     -1)}}  {d^{x}\sigma^{x}}' class='latex' /></center></p>
<p>where:<br />
<img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /> is the user<br />
<img src='http://s.wordpress.com/latex.php?latex=d%5E%7Bx%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='d^{x}' title='d^{x}' class='latex' /> is the number of days user <img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /> has been registered<br />
<img src='http://s.wordpress.com/latex.php?latex=g%5E%7Bx%7D_%7Bi%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='g^{x}_{i}' title='g^{x}_{i}' class='latex' /> is the number of comments for user <img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /> made on day <img src='http://s.wordpress.com/latex.php?latex=i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='i' title='i' class='latex' /><br />
<img src='http://s.wordpress.com/latex.php?latex=k%5E%7Bx%7D_%7Bij%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='k^{x}_{ij}' title='k^{x}_{ij}' class='latex' /> is the karma score for the <img src='http://s.wordpress.com/latex.php?latex=j%5E%7Bth%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='j^{th}' title='j^{th}' class='latex' /> comment of the <img src='http://s.wordpress.com/latex.php?latex=i%5E%7Bth%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='i^{th}' title='i^{th}' class='latex' /> day for user <img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /><br />
<img src='http://s.wordpress.com/latex.php?latex=%5Csigma%5E%7Bx%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\sigma^{x}' title='\sigma^{x}' class='latex' /> is the standard deviation of the karma scores for user <img src='http://s.wordpress.com/latex.php?latex=x&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x' title='x' class='latex' /></p>
<p>And in pseudo-code:</p>
<pre class="brush:c-sharp">
function timeAdjustedKarmaSharpe(user) {
    if(user.comments.length == 0)
         return 0;

    var excessReturns = dailyAverageExcessReturns(user);
    return karmaSharpe(excessReturns);
}

function dailyAverageExcessReturns(user) {
    var groups = user.comments.groupBy(c => c.Date);
    var excessReturns = groups.select(g => g.sum(c => c.karma - 1) / g.count);
    return excessReturns;
}
</pre>
<h1>Conclusion</h1>
<p>It may not look very simple, but it actually is straight-forward. We are effectively saying that each user should generate an average comment score of 1 point per day to break even. Anything you make beyond 1 point is considered an excess return for the day. We then simply take the Sharpe ratio of the average daily excess returns. The resulting metric ensures that users are incentivized to make consistent, high-quality submissions and punishes one hit wonders and those who take a spray-and-pray approach.</p>
<p>If you liked this article, please <a href="http://news.ycombinator.com/item?id=2918839">upvote it on HackerNews</a>.</p>
<h5>Footnotes</h5>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-390-1'>Well, assuming that there is no way you're getting into a Ponzi scheme. This is pretty much the guarantee that people expected from Madoff's fund. <span class='footnotereverse'><a href='#fnref-390-1'>&#8617;</a></span></li>
<li id='fn-390-2'>Note that I'll use the term "comment", but story submissions work the same and are thus analogous. <span class='footnotereverse'><a href='#fnref-390-2'>&#8617;</a></span></li>
<li id='fn-390-3'>The pseudo-code is a lazy bastardization of C#. <span class='footnotereverse'><a href='#fnref-390-3'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2011/08/23/how-karma-should-be-measured/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Building a Startup &#8211; 12 Priceless Tools for Launching Your MVP</title>
		<link>http://www.nashcoding.com/2011/05/31/building-a-startup-12-priceless-tools-for-launching-your-mvp/</link>
		<comments>http://www.nashcoding.com/2011/05/31/building-a-startup-12-priceless-tools-for-launching-your-mvp/#comments</comments>
		<pubDate>Tue, 31 May 2011 02:27:31 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[Startups]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=356</guid>
		<description><![CDATA[Building a startup is hard. Really hard. The last thing you want to do is make it harder. Through the trials and tribulations I've undergone in launching my startup, I've discovered several gems that are indispensable. If you're trying to launch a startup, here are the tools you need. HackerNews Every founder needs to keep [...]]]></description>
			<content:encoded><![CDATA[<p>Building a startup is hard. <strong>Really</strong> hard. The last thing you want to do is make it harder. Through the trials and tribulations I've undergone in launching <a href="http://effectcheck.com">my startup</a>, I've discovered several gems that are indispensable. If you're trying to launch a startup, here are the tools you need.<span id="more-356"></span> </p>
<h3><a href="http://news.ycombinator.com">HackerNews</a></h3>
<p>Every founder needs to keep an eye on the startup scene and cutting-edge tools that are being released. I've found competitors, partners, ideas, strategies, tips, and friends via HackerNews. For technologists, it's the best community on the web, period.</p>
<p>Tips:</p>
<ul>
<li>Use <a href="http://ihackernews.com">ihackernews</a> on your mobile phone.</li>
</ul>
<h3><a href="http://themeforest.net?ref=tansey">Theme Forest</a></h3>
<p>I wasted a lot of time on designs for EffectCheck before I finally admitted that designing a full website from scratch is a full time job. I wanted to focus on developing an awesome emotional impact analysis engine, not worry about divs and gradients. Theme Forest has tons of awesome themes that you can customize, and at around $15, the price is right!</p>
<p>Tips:</p>
<ul>
<li>Search for "CSS3" to find the highest quality site templates.</li>
</ul>
<h3><a href="http://bit.ly/p80viK">99Designs</a></h3>
<p>Once you have a site template, you need a logo. This is another area where I tried and failed to come up with something at first. For around $300, you can run a week-long design contest for your logo. I got over 100 submissions and lots of great candidate images.</p>
<p>Tips:</p>
<ul>
<li>Provide LOTS of constant feedback. The artists on the site don't really seem to have a passion for your logo, so you need to guide them well.</li>
<li>Make it blind the last couple of days to prevent copy-cats from flooding in. This also helps encourage the original artists to continue working on your logo.</li>
<li>Support email is slow. Talk to them on twitter if you have a problem. I tried the email route first, and after 24 hours of no response, I tweeted my complaint-- within 1 hour I had my problem resolved.</li>
<li>Ask the artists to see lots of color variations. It's trivial for them to change colors and it helps you get a feel for which color schemes you might like on your site.</li>
<li>Get lots of opinions. Run polls and send links out to friends. Everyone thinks differently; the responses I got from my friends and family varied drastically and helped me decide on a logo. However, be conscious that this is <i>your</i> startup-- so the logo has to look good to you above all else.</li>
<li>Beware of publicly announcing your polls. I made the mistake of tweeting my poll and got a lot of random people with questionable intentions voting. I'm pretty sure some of them were friends of one of the artists and trying to help him win.</li>
</ul>
<h3>Photoshop and <a href="http://shutterstock.com">ShutterStock</a></h3>
<p>Even after buying a template and outsourcing your logo design, you will still need some basic skills in Photoshop to get a full website pushed. The most important skill I've found is the ability to take a stock photo and cut it up well. ShutterStock has some great photos at great prices-- I recommend signing up for the cheaper package that lets you have a dozen "medium-sized" downloadable images, since medium usually means 1000x700 or better which is more than enough for site images. The images for the four sliders on the EffectCheck <a href="http://effectcheck.com">homepage</a> are derived from images on ShutterStock.</p>
<p>Tips:</p>
<ul>
<li>Use the magic wand tool to drastically cut down the time to cut images.</li>
<li>If you're cutting up an image that has a white background, add a new layer and make it a dark color so you can better see the edges of your image. When you save the image, just uncheck that layer.</li>
<li>Blur the edges of photos just slightly to remove jaggies and make the image look smoother on your page.</li>
<p>.
</ul>
<h3>Git and <a href="http://github.com">Github</a></h3>
<p>This almost goes without saying these days, but Git is the clear winner in the battle of the source control versioning systems. Playing off of this, Github has become a social coding explosion-- I've even had <a href="https://github.com/tansey/hand2xml">a project forked</a>! </p>
<p>Tips:</p>
<ul>
<li>Committing lots of open source code to Github is also a great way to boost your startup's network effect among developers.</li>
</ul>
<h3><a href="https://appharbor.com/account/new?referrerUsername=tansey">AppHarbor</a></h3>
<p>As I mentioned in my <a href="http://www.nashcoding.com/2011/04/10/building-a-startup-part-2-defending-net/">previous post</a>, my startup is built on .NET and deployed on AppHarbor. My deployment takes seconds, it's hosted on EC2, and it incidentally includes a free private git repo!</p>
<p>Tips:</p>
<ul>
<li>If you add non-code files to your project, make sure their properties are set to "content", otherwise they won't be copied to your server instance</li>
<li>Check out the new <a href="http://support.appharbor.com/kb/api/developing-a-service-hook">service hooks</a> -- pretty awesome!</li>
</ul>
<h3><a href="http://jquery.com">JQuery</a> and <a href="http://jqueryui.com">JQuery UI</a></h3>
<p>When you need to add that extra polish to your site, JQuery UI is there. I used it in several places for the EffectCheck editor that our clients use, but also to create the tabbed locations on the <a href="http://effectcheck.com/pricing">contact page</a>.</p>
<p>Tips:</p>
<ul>
<li>When debugging AJAX calls, it helps to use a plugin like <a href="http://james.padolsey.com/javascript/prettyprint-for-javascript/">prettyPrint</a> that will dump the JSON result contents to a pretty-printed table.</li>
</ul>
<h3><a href="http://stackoverflow.com">StackOverflow</a></h3>
<p>I've <a href="http://stackoverflow.com/users/330561/wesley-tansey">asked</a> about 30 questions on StackOverflow since I started working on EffectCheck, but it feels like 300. In fact, if you add in the number of times I found a SO link via Google or started asking a question but found the answer on StackOverflow's similar questions panel, it probably is close to that many. I really believe StackOverflow is one of the most important sites to emerge on the internet in the last five years. It's drastically increased my productivity and knowledge in ways I never thought possible.</p>
<p>Tips:</p>
<ul>
<li>Do not be afraid to ask a question. You usually will get an answer within 30 minutes even for tough questions that you've been struggling with for days.</li>
<li>With that in mind, do not let your questions linger unanswered. Every question you ask should either be marked as answered by someone else or self-answered.</li>
</ul>
<h3>Blogging with <a href="http://wordpress.org">WordPress</a></h3>
<p>You need marketing. It may seem like if you build it, they will come-- but <a href="http://jasonlbaptiste.com/featured-articles/if-you-build-it-they-wont-come/">they won't</a>. Having an interesting blog and pushing it on social media sites is a good first step. There are lots of choices for blogging engines, but I've found WordPress to be the best.</p>
<p>Tips:</p>
<ul>
<li>Use SEO-friendly links with words from the article title in the URL.</li>
<li>Push social media sites like <a href="http://reddit.com">reddit</a>, <a href="http://digg.com">Digg</a>, etc. Have a group of friends that will give you a couple upvotes for the initial kick needed to attract the attention of people watching the new stories feed.</li>
<li>When you are about to hit the front page on a major site, make sure you have a caching plug-in like <a href="http://wordpress.org/extend/plugins/wp-super-cache/">WP Super Cache</a> setup so you don't get DDoS'd.</li>
</ul>
<h3><a href="http://www.google.com/apps/intl/en/business/index.html">Google Apps for Business</a> to Host Email</h3>
<p>The free hosting services Google provides for email are great. You can setup groups, create users, and tons of other things all in seconds, plus you get the convenient Gmail web interface.</p>
<p>Tips:</p>
<ul>
<li>Setup a group for your sales and development teams (even if they're both just your and your co-founder). It adds an air of legitimacy, especially if your startup is focused on B2B sales.</li>
</ul>
<h3><a href="http://postmarkapp.com">Postmark</a> for Transactional Emails</h3>
<p>If you ever need some way to send emails automatically, like to confirm new user accounts or customer purchases, you have a few options. I like Postmark over <a href="http://sendgrid.com/">Sendgrid</a> or <a href="http://aws.amazon.com/ses/">Amazon</a>, though I am hearing a lot of buzz about <a href="http://www.mailgun.net/">MailGun</a>. The jury is still out on which app is the best, but EffectCheck uses Postmark and it works great for us!</p>
<p>Tips:</p>
<ul>
<li>If you're in B2B sales like EffectCheck, try having a contact form on your site and have Postmark email your sales team whenever someone submits a new entry.</li>
</ul>
<h3><a href="http://www.sublimetext.com/">Sublime Text</a></h3>
<p>You need a great text editor. There are too many text files in the world that have a special syntax you need highlighted and whatever comes with your OS is probably not nearly as awesome as Sublime Text. You can even use it for free, though it's more than worth the small fee to buy it!</p>
<p>Tips:</p>
<ul>
<li>The auto-complete functionality (ctrl+space on Windows) is particularly nifty, especially if you're coding in a dynamic language like Ruby.</li>
<li>There's lots of plug-ins available, so don't stop at just the defaults.</li>
</ul>
<h3>Conclusion</h3>
<p>That's just a taste of some of the great tools that are out there to help you launch your startup. As I progress, I'm sure I'll find loads more awesome tools worth writing about. Until then, back to hacking together an awesome startup!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2011/05/31/building-a-startup-12-priceless-tools-for-launching-your-mvp/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Building a Startup &#8211; Part 2 &#8211; Defending .NET</title>
		<link>http://www.nashcoding.com/2011/04/10/building-a-startup-part-2-defending-net/</link>
		<comments>http://www.nashcoding.com/2011/04/10/building-a-startup-part-2-defending-net/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 04:02:01 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[AppHarbor]]></category>
		<category><![CDATA[Startups]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=282</guid>
		<description><![CDATA[There has been a lot of trash talk recently about .NET for startups. People make ridiculous claims about how .NET killed MySpace and you should never hire .NET programmers. Well I'm building my startup in .NET and for a lot of good reasons. Why I chose .NET I live in Palo Alto, work at the [...]]]></description>
			<content:encoded><![CDATA[<p>There has been a lot of trash talk recently about .NET for startups. People make ridiculous claims about how <a href="http://www.youtube.com/watch?v=Fi_I20PaPyI&#038;feature=player_embedded">.NET killed MySpace</a> and you should <a href="http://blog.expensify.com/2011/03/25/ceo-friday-why-we-dont-hire-net-programmers/">never hire .NET programmers</a>. Well I'm building <a href="http://effectcheck.com">my startup</a> in .NET and for a lot of good reasons. <span id="more-282"></span></p>
<h5>Why I chose .NET</h5>
<p>I live in Palo Alto, work at the <a href="http://hackerdojo.com">Hacker Dojo</a>, and I am even buying a Macbook Pro tomorrow. Clearly I have totally drank the startup Kool-Aid. The one point I balk at is the idea that choosing .NET is always a mistake. I believe .NET was the right choice for <a href="http://effectcheck.com">EffectCheck</a>, for the following reasons:</p>
<ul>
<li><strong>Existing expertise</strong> - I spent three years working as an AI researcher and quant at a hedge fund. We used two languages: R and C#. If you work with any major financial services provider, they invariably have an awesome .NET API and usually a Java one. So I stuck with C# and became really good at it. I do know Ruby/Rails and I'm playing around with Python/Django now to build an iPhone game, but at the end of the day it would take me 5-10x longer to build everything in those languages.</li>
<li><strong>Core algorithm already implemented</strong> - The awesome AI algorithm behind <a href="http://effectcheck.com">EffectCheck</a> has already been implemented and thoroughly tested in C#. Reimplementing it in another language would mean more testing and debugging.</li>
<li><strong><a href="https://appharbor.com/account/new?referrerUsername=tansey">AppHarbor</a></strong> - It's Heroku for .NET. You simply can't beat it. I push to my git repo and it compiles and deploys automagically. I know lots of Python hackers who swear up and down that they use EC2 and love it, but the server admin gene just isn't in me. I don't want to spend an hour setting up my AMI to get my web app deployed.</li>
<li><strong>Visual Studio</strong> - Hands down the best programming environment anywhere. I've seen cool things from Textmate with Ruby, but I still think the C# intellisense support is way beyond anything available for other languages/frameworks.</li>
<li><strong>I know the community</strong> - Throughout the last few years, mostly on accident, I've come to know a lot of the best .NET hackers. I did some poker research with <a href="http://danielcrenna.com/">Daniel Crenna</a>, I met <a href="http://www.aaronstannard.com/">Aaron Stannard</a> when we both lived in San Diego, and <a href="http://john-sheehan.com/">John Sheehan</a> was on my Startup Weekend team. I was also one of the first AppHarbor users (and support tickets!), which means I've had plenty of discussions with <a href="http://friism.com/">Michael Friis</a>, <a href="http://about.me/runesoerensen">Rune Soerensen</a>, and <a href="https://twitter.com/troethom">Troels Thomsen</a>.</li>
</ul>
<h5>Can't we all just get along?</h5>
<p>I'm not trying to get into a religious war here. Other stacks have their own benefits. Python has awesome libraries like the nltk, scipy, and numpy; Rails has Heroku and tons of great gems. The .NET choice is just personal preference, but that's kind of my point: it doesn't matter if you use .NET or not.</p>
<p>If you look at ASP.NET MVC 3 compared to the two main MVC frameworks out there (Django and Rails), there's very little conceptual difference. I use 960gs, git, jQuery, and (hopefully) soon MongoDB just like plenty of Rails and Django developers. The rest is just the choice of some arbitrary programming language and MVC framework to route calls.</p>
<h5>Conclusion</h5>
<p>So should you use .NET? The obvious answer is "it depends." If at least three of my five reasons resonate with you, then I would probably say yes. You really have nothing to fear anymore-- it's all pretty much the same until you reach <a href="http://blog.stackoverflow.com/category/server/">massive scale</a>. If you reach that point, well, that's one of those good problems.</p>
<p>If you liked this article, please <a href="http://news.ycombinator.com/item?id=2428746">up-vote it on HackerNews</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2011/04/10/building-a-startup-part-2-defending-net/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Building a Startup &#8211; Part 1 &#8211; Introduction</title>
		<link>http://www.nashcoding.com/2011/04/10/building-a-startup-part-1-introduction/</link>
		<comments>http://www.nashcoding.com/2011/04/10/building-a-startup-part-1-introduction/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 03:59:50 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[Natural Language Processing]]></category>
		<category><![CDATA[Startups]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=295</guid>
		<description><![CDATA[I've joined with David Fogel and Yanon Volcani to build EffectCheck. This post is the first in a series detailing how we're building this startup from the ground up. What is EffectCheck? EffectCheck is an algorithm that draws on decades of clinical psychology research to identify the subliminal emotional impact of your word choice. Lots [...]]]></description>
			<content:encoded><![CDATA[<p>I've joined with <a href="http://www.natural-selection.com/people_dfogel.html">David Fogel</a> and <a href="http://www.volcani.com/">Yanon Volcani</a> to build <a href="http://effectcheck.com">EffectCheck</a>. This post is the first in a series detailing how we're building this startup from the ground up.<span id="more-295"></span></p>
<h5>What is EffectCheck?</h5>
<p>EffectCheck is an algorithm that draws on decades of clinical psychology research to identify the subliminal emotional impact of your word choice. </p>
<p>Lots of words have subconscious effects on us. For instance, if you're walking down the street and you see a sign with the word "ELDERLY" written on it, studies<sup class='footnote'><a href='#fn-295-1' id='fnref-295-1'>1</a></sup> show people actually start walking slower without realizing it. Alternatively, consider responding to someone telling a great joke. You can say "That joke is hilarious" or "That joke kills me" -- both mean the same thing, the context is the same, but subconsciously the word "kills" actually raises your stress levels. EffectCheck measures these subliminal effects and helps people discover how their writing likely makes readers feel independent of context.</p>
<h5>Who could use it?</h5>
<p>Anyone who wants to understand the emotions their readers are going to feel. Some examples:</p>
<ul>
<li>Advertisers may want potential customers to feel more confident so the customers buy more merchandise.</li>
<li>Defense attorneys writing their closing arguments may want the jury to feel compassionate towards the defendant.</li>
<li>Politicians giving a speech may want to charge the audience by raising anxiety and hostility.</li>
</ul>
<p>There's clearly a wide range of use cases and EffectCheck can be customized to specific domains given enough training samples.</p>
<h5>What will be covered in this series?</h5>
<p>I'm new to web development, so I'm hoping this will serve as a semi-roadmap for people looking to build their own startup. I'm specifically focusing on people who have cool algorithms or applications that they've written and want to create a startup around them. Some of the topics I'm planning on covering:</p>
<ol>
<li>Why I chose .NET</li>
<li>Running a 99Designs logo contest</li>
<li>Building a developer API platform</li>
<li>A/B testing, funnel analysis and metrics</li>
</ol>
<p>There will be a lot more to come also, but that's all I've dealt with so far. With the exception of this intro post and the "Why I chose .NET" post, I'll try to keep everything technical or instructive; I don't want this blog to become about my random musings and opinions. I also will not be covering any of the implementation details behind the EffectCheck algorithm (trade secrets and NDAs). Everything else is fair game, so if you're looking to build a startup, I hope you find this series helpful!</p>
<h5>Footnotes</h5>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-295-1'>For a better discussion of this experiment, see <a href="http://www.amazon.com/gp/product/1400077427/ref=as_li_ss_tl?ie=UTF8&#038;tag=nashc-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1400077427">Stumbling on Happiness</a><img src="http://www.assoc-amazon.com/e/ir?t=&#038;l=as2&#038;o=1&#038;a=1400077427" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />. It's a great book in general, highly recommended. <span class='footnotereverse'><a href='#fnref-295-1'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2011/04/10/building-a-startup-part-1-introduction/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using the Forms Authentication Membership Provider on AppHarbor</title>
		<link>http://www.nashcoding.com/2011/02/05/using-the-forms-authentication-membership-provider-on-appharbor/</link>
		<comments>http://www.nashcoding.com/2011/02/05/using-the-forms-authentication-membership-provider-on-appharbor/#comments</comments>
		<pubDate>Sat, 05 Feb 2011 21:32:12 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[AppHarbor]]></category>
		<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=273</guid>
		<description><![CDATA[I love AppHarbor. I've been waiting for a year for someone to do "Heroku for .NET", and it's finally here! One of the basic use cases for an ASP.NET MVC web app is membership support. This post will be a very quick walk through on using the default (forms authentication) membership provider for an AppHarbor [...]]]></description>
			<content:encoded><![CDATA[<p>I love <a href="https://appharbor.com/account/new?referrerUsername=tansey">AppHarbor</a>. I've been waiting for a year for someone to do "Heroku for .NET", and it's finally here! One of the basic use cases for an ASP.NET MVC web app is membership support. This post will be a very quick walk through on using the default (forms authentication) membership provider for an AppHarbor web app.<br />
<span id="more-273"></span></p>
<h2>Create your AppHarbor Application</h2>
<p>Creating an application on AppHarbor is straight-forward:</p>
<ol>
<li>Go to your Applications tab.</li>
<li>Click "Create New".</li>
<li>Fill in a name like "TestMembership".</li>
<li>Add a database.</li>
<li>Choose a MSSQL database with the free 20mb option.</li>
<li>Call the database something like "membershipdb".</li>
</ol>
<p>That's all that you need to do in AppHarbor! Leave the tab with your database info open, you'll need that in a minute.</p>
<h2>Create your MVC Application</h3>
<p>Create your ASP.NET MVC application like you would normally:</p>
<ol>
<li>In Visual Studio 2010, File -> New -> Project.</li>
<li>Create a new ASP.NET MVC 3 Project or MVC 2 if you don't have MVC 3 installed.</li>
<li>Choose Internet Application so that the membership provider is setup locally.</li>
</ol>
<p>This is all pretty standard. Now we have to setup the AppHarbor database with the membership table structure.</p>
<h2>Configuring and Using your AppHarbor Database</h2>
<p>There is a great utility called <a href="http://msdn.microsoft.com/en-us/library/x28wfk74.aspx">aspnet_sqlreg.exe</a>. This tool will setup membership support on your MS SQL database automatically:</p>
<ol>
<li>Start a Visual Studio command prompt by going to Start -> All Programs -> Visual Studio 2010 -> Visual Studio Tools -> Visual Studio Command Prompt.</li>
<li>Run the following command, using the your AppHarbor database settings to fill in the values in brackets: <code>aspnet_regsql.exe -S [Host] -d [Name] -U [Username] -P [Password] -A all</code></li>
<li>In your MVC project, open your Web.config file.</li>
<li>Replace the connectionString for ApplicationServices with the connection string found on your AppHarbor database page.</li>
</ol>
<p>This will setup all the membership services on your AppHarbor database, including role management, profile support, etc. The link to the MSDN page on the tool has all the flags in case you only want some features.</p>
<h2>Conclusion</h2>
<p>That's it! You can now push your app to AppHarbor and test out that your membership code works.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2011/02/05/using-the-forms-authentication-membership-provider-on-appharbor/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tutorial – Evolving Neural Networks with SharpNEAT 2 (Part 3)</title>
		<link>http://www.nashcoding.com/2010/10/29/tutorial-%e2%80%93-evolving-neural-networks-with-sharpneat-2-part-3/</link>
		<comments>http://www.nashcoding.com/2010/10/29/tutorial-%e2%80%93-evolving-neural-networks-with-sharpneat-2-part-3/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 17:55:36 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Evolutionary Computation]]></category>
		<category><![CDATA[Neural Networks]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=255</guid>
		<description><![CDATA[In parts 1 and 2 of this tutorial series, we evolved neural networks using the standard NEAT algorithm. In part 3, we're going to use the HyperNEAT algorithm. So far, our neural networks have been effectively ignorant of the geometry of the Tic-Tac-Toe board. They are given nine inputs and are told simply to figure [...]]]></description>
			<content:encoded><![CDATA[<p>In parts <a href="http://www.nashcoding.com/2010/07/17/tutorial-evolving-neural-networks-with-sharpneat-2-part-1/">1</a> and <a href="http://www.nashcoding.com/2010/07/24/tutorial-%e2%80%93-evolving-neural-networks-with-sharpneat-2-part-2/">2</a> of this tutorial series, we evolved neural networks using the standard NEAT algorithm. In part 3, we're going to use the HyperNEAT algorithm.<br />
<span id="more-255"></span><br />
So far, our neural networks have been effectively ignorant of the geometry of the Tic-Tac-Toe board. They are given nine inputs and are told simply to figure out how to play Tic-Tac-Toe. They have no concept of where each input is in relation to the others, which is an additional hurdle for the evolution to overcome. </p>
<p>The HyperNEAT algorithm<sup class='footnote'><a href='#fn-255-1' id='fnref-255-1'>1</a></sup> incorporates the geometry of the search space by effectively adding a layer of indirection. Rather than evolving the neural network directly, HyperNEAT evolves a Compositional Pattern Producing Network (CPPN)<sup class='footnote'><a href='#fn-255-2' id='fnref-255-2'>2</a></sup> which can generate a neural network. CPPNs take the location of two nodes in the problem domain and output the connection between them in the target neural network.</p>
<h2>The IGenomeDecoder</h2>
<p>The main difference between a HyperNEAT experiment and a standard NEAT experiment in SharpNEAT 2 is the genome decoding. In a NEAT experiment, your CreateGenomeDecoder method simply returns a new NeatGenomeDecoder, and you're done. In a HyperNEAT experiment, you have to create a custom decoder that specifies where the input and output nodes are in the problem domain. </p>
<pre class="brush:c-sharp">
public class TicTacToeHyperNeatExperiment
{
    ...

    /// &lt;summary&gt;
    /// Creates a new HyperNEAT genome decoder that can be used to convert
    /// a genome into a phenome.
    /// &lt;/summary&gt;
    public IGenomeDecoder&lt;NeatGenome, IBlackBox&gt; CreateGenomeDecoder()
    {
        // Create an input and an output layer for the HyperNEAT
        // substrate. Each layer corresponds to the game board
        // with 9 squares.
        SubstrateNodeSet inputLayer = new SubstrateNodeSet(9);
        SubstrateNodeSet outputLayer = new SubstrateNodeSet(9);

        // Each node in each layer needs a unique ID.
        // The input nodes use ID range [1,9] and
        // the output nodes use [10,18].
        uint inputId = 1, outputId = 10;

        // The game board is represented as a 2-dimensional plane.
        // Each square is at -1, 0, or 1 in the x and y axis.
        // Thus, the game board looks like this:
        //
        // (-1,1)  | (0,1)   | (1,1)
        // (-1,0)  | (0,0)   | (1,0)
        // (-1,-1) | (0,-1)  | (1,-1)
        //
        // Note that the NeatPlayer class orders the board from
        // left to right, then top to bottom. So we need to create
        // nodes with the following IDs:
        //
        //    1    |    2    |   3
        //    4    |    5    |   6
        //    7    |    8    |   9
        //
        for(int x = -1; x &lt;= 1; x++)
            for (int y = 1; y &gt;= -1; y--, inputId++, outputId++)
            {
                inputLayer.NodeList.Add(new SubstrateNode(inputId, new double[] { x, y }));
                outputLayer.NodeList.Add(new SubstrateNode(outputId, new double[] { x, y }));
            }

        List&lt;SubstrateNodeSet&gt; nodeSetList = new List&lt;SubstrateNodeSet&gt;(2);
        nodeSetList.Add(inputLayer);
        nodeSetList.Add(outputLayer);

        // Define a connection mapping from the input layer to the output layer.
        List&lt;NodeSetMapping&gt; nodeSetMappingList = new List&lt;NodeSetMapping&gt;(1);
        nodeSetMappingList.Add(NodeSetMapping.Create(0, 1, (double?)null));

        // Construct the substrate using a steepened sigmoid as the phenome's
        // activation function. All weights under 0.2 will not generate
        // connections in the final phenome.
        Substrate substrate = new Substrate(nodeSetList,
            DefaultActivationFunctionLibrary.CreateLibraryCppn(),
            0, 0.2, 5, nodeSetMappingList);

        // Create genome decoder. Decodes to a neural network packaged with
        // an activation scheme that defines a fixed number of activations per evaluation.
        IGenomeDecoder&lt;NeatGenome, IBlackBox&gt; genomeDecoder =
            new HyperNeatDecoder(substrate, _activationSchemeCppn,
                                            _activationScheme, false);

        return genomeDecoder;
    }
}
</pre>
<p>In our experiment, the Tic-Tac-Toe board is our problem domain and the game board is represented as a simple 2-d plane. Each node is given a pair of (x,y) coordinates corresponding to its location on the game board. These coordinates are used as inputs to the CPPN when it's generating the neural network.</p>
<p>The above example is a simple 2-layer CPPN with no hidden layers. If you want to add hidden layers, you simply need to create an additional SubstrateNodeSet and add it to the nodeSetList. Then you will need two NodeSetMappings, one from the input (0) to the hidden (1) layer, and one from the hidden (1) to the output (2) layer.<sup class='footnote'><a href='#fn-255-3' id='fnref-255-3'>3</a></sup></p>
<p>Once you have everything specified, you create a Substrate (i.e., the CPPN genome) and return the HyperNeatDecoder.</p>
<h2>Saving HyperNEAT Genomes</h2>
<p>The only other change is going to be in handling the file I/O for the genomes.</p>
<pre class="brush:c-sharp">
class Program
{
    ...

    static void ea_UpdateEvent(object sender, EventArgs e)
    {
        Console.WriteLine(string.Format("gen={0:N0} bestFitness={1:N6}",
                                _ea.CurrentGeneration, _ea.Statistics._maxFitness));

        // Save the best genome to file
        // Note: Unlike the other experiments, you must save
        // function IDs of HyperNEAT genomes.
        var doc = NeatGenomeXmlIO.SaveComplete(
                                new List<NeatGenome>() { _ea.CurrentChampGenome }, true);

        doc.Save(CHAMPION_FILE);
    }
}
</pre>
<p>Since HyperNEAT also evolves each node's activation function, we need to make sure to save that information to file along with the rest of the topology information.</p>
<h2>Conclusion</h2>
<p>Going from NEAT to HyperNEAT is actually very easy. Once you have a good idea of how you are going to map your problem domain to a geometric plane, it's straight-forward to transition. </p>
<p>Unfortunately, the problems we had still persist: the evolution does not converge on an optimal strategy. Since that was never really the goal of these tutorials, it's okay! Our goal was to learn how to use SharpNEAT 2 to evolve neural networks, which I think I can safely say has been accomplished.</p>
<p>Source code is available <a href="http://www.nashcoding.com/wp-content/uploads/2010/10/hyperneat_tictactoe.zip">here</a>. The project used for this part was TicTacToeHyperNeat.</p>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-255-1'>For more information on the HyperNEAT algorithm, see Stanley et. al.'s journal paper: <a href="http://eplex.cs.ucf.edu/papers/stanley_alife09.pdf">A Hypercube-Based Encoding for Evolving Large-Scale Neural Networks</a> <span class='footnotereverse'><a href='#fnref-255-1'>&#8617;</a></span></li>
<li id='fn-255-2'>CPPNs are similar to standard neural networks, except that they contain nodes with different activation functions.  The intuition is that different activation functions are more effective at expressing different kinds of symmetries and regularities that may be present in the problem domain. For the purposes of this tutorial, you can basically assume a CPPN is just another kind of neural network. <span class='footnotereverse'><a href='#fnref-255-2'>&#8617;</a></span></li>
<li id='fn-255-3'>Note that the EPlex gang have figured out how to automatically place nodes in HyperNEAT, but the current release of SharpNEAT does not implement their algorithm. For more information on the algorithm, see <a href="http://eplex.cs.ucf.edu/papers/risi_gecco10.pdf">this paper</a>. <span class='footnotereverse'><a href='#fnref-255-3'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2010/10/29/tutorial-%e2%80%93-evolving-neural-networks-with-sharpneat-2-part-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A C# Blackjack Simulation Framework</title>
		<link>http://www.nashcoding.com/2010/10/03/a-csharp-blackjack-simulation-framework/</link>
		<comments>http://www.nashcoding.com/2010/10/03/a-csharp-blackjack-simulation-framework/#comments</comments>
		<pubDate>Sun, 03 Oct 2010 16:34:33 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[Blackjack]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=235</guid>
		<description><![CDATA[Since I haven't had time to sit down and write new code lately, I decided to dig into the closet and start pulling out code that I've worked on but haven't released yet. Today's gem is a framework for simulating Blackjack (also known as 21) strategies. Blackjack is a popular casino game where each player [...]]]></description>
			<content:encoded><![CDATA[<p>Since I haven't had time to sit down and write new code lately, I decided to dig into the closet and start pulling out code that I've worked on but haven't released yet. Today's gem is a framework for simulating Blackjack (also known as 21) strategies.<br />
<span id="more-235"></span><br />
<a href="http://en.wikipedia.org/wiki/Blackjack">Blackjack</a> is a popular casino game where each player is dealt a two-card hand (typically face-up) and the dealer is dealt a two-card hand with one card face up and the other face down. Your goal is to get your hand's value closer to 21 than the dealer's, without going over ("busting").</p>
<h2>Creating a Blackjack Game</h2>
<p>The basic game rules are well known, but each casino has its own minor variants that can affect the odds and correct plays. The NashCoding Blackjack Framework (NBF) enables simulating a wide variety of these variants via the BlackjackSettings class:</p>
<pre class="brush:c-sharp">
/// &lt;summary&gt;
/// A collection of various settings for a game of Blackjack.
/// &lt;/summary&gt;
public class BlackjackSettings
{
    /// &lt;summary&gt;
    /// The number of 52-card decks contained in the dealer's shoe.
    /// &lt;/summary&gt;
    public int DecksPerShoe { get; set; }

    /// &lt;summary&gt;
    /// The number of cards to deal before the shoe is reshuffled.
    /// &lt;/summary&gt;
    public int MinCardsDealtBeforeReshuffle { get; set; }

    /// &lt;summary&gt;
    /// The minimum amount a player can bet.
    /// &lt;/summary&gt;
    public decimal MinimumBet { get; set; }

    /// &lt;summary&gt;
    /// The maximum amount a player can bet.
    /// &lt;/summary&gt;
    public decimal MaximumBet { get; set; }

    /// &lt;summary&gt;
    /// The threshold where the dealer stops hitting and
    /// stands (typically 17).
    /// &lt;/summary&gt;
    public int DealerHardStandThreshold { get; set; }

    /// &lt;summary&gt;
    /// The threshold where the dealer stops hitting and
    /// stands if one of their cards is a soft ace.
    /// &lt;/summary&gt;
    public int DealerSoftStandThreshold { get; set; }

    /// &lt;summary&gt;
    /// The reward multiplier for Blackjack, default is
    /// 2.5 (i.e., pays 1.5:1).
    /// &lt;/summary&gt;
    public decimal BlackjackPayoff { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is offered insurance when the
    /// dealer shows a potential blackjack.
    /// &lt;/summary&gt;
    public bool InsuranceOffered { get; set; }

    /// &lt;summary&gt;
    /// The cost to purchase insurance, as a fraction
    /// of the original bet.
    /// &lt;/summary&gt;
    public decimal InsuranceCost { get; set; }

    /// &lt;summary&gt;
    /// The payoff for insurance, where 2 is 1:1 payoff.
    /// &lt;/summary&gt;
    public decimal InsurancePayoff { get; set; }

    /// &lt;summary&gt;
    /// The maximum number of times a player can split
    /// in a hand.
    /// &lt;/summary&gt;
    public int MaxSplitsAllowed { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is allowed to resplit aces.
    /// Ex: Dealt AA, split to AA and Ax -- can the
    /// first hand be resplit?
    /// &lt;/summary&gt;
    public bool ResplitAcesAllowed { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is allowed to split on 20.
    /// &lt;/summary&gt;
    public bool SplitTensAllowed { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is allowed to hit after
    /// splitting aces.
    /// &lt;/summary&gt;
    public bool HittingSplitAcesAllowed { get; set; }

    /// &lt;summary&gt;
    /// Whether the player can double down only on ten or
    /// eleven. If false, the player can double down on
    /// any hand.
    /// &lt;/summary&gt;
    public bool DoubleDownOnlyTenOrEleven { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is allowed to double down on a
    /// soft hand (contains an ace).
    /// &lt;/summary&gt;
    public bool SoftDoubleDownAllowed { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is allowed to double down after
    /// splitting hands other than AA.
    /// &lt;/summary&gt;
    public bool DoubleDownNonAceSplitsAllowed { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is allowed to double down after
    /// splitting AA.
    /// &lt;/summary&gt;
    public bool DoubleDownSplitAcesAllowed { get; set; }

    /// &lt;summary&gt;
    /// Whether the player is allowed to surrender their hand
    /// and receive a partial payoff back.
    /// &lt;/summary&gt;
    public bool SurrenderAllowed { get; set; }

    /// &lt;summary&gt;
    /// The payoff for surrendering, as a fraction of the
    /// original bet. Typically this is 0.5.
    /// &lt;/summary&gt;
    public decimal SurrenderPayoff { get; set; }
}
</pre>
<p>The defined game settings are passed to the constructor of the BlackjackGame engine class:</p>
<pre class="brush:c-sharp">
/// &lt;summary&gt;
/// A Blackjack game engine class. This class enables the user to simulate
/// a potentially-infinite number of blackjack hands played by a collection
/// of players.
/// &lt;/summary&gt;
public class BlackjackGame
{
    /// &lt;summary&gt;
    /// The settings for this game.
    /// &lt;/summary&gt;
    public BlackjackSettings Settings { get; set; }

    private const int SHUFFLES_PER_SHOE = 10;
    private Shoe _shoe;

    /// &lt;summary&gt;
    /// Creates a new instance of a game of Blackjack.
    /// &lt;/summary&gt;
    public BlackjackGame(BlackjackSettings settings)
    {
        Settings = settings;
        _shoe = new Shoe(settings.DecksPerShoe);
    }

    /// &lt;summary&gt;
    /// Plays a game of Blackjack with the collection of players.
    /// &lt;/summary&gt;
    public void Play(IEnumerable&lt;IBlackjackPlayer&gt; players)
    {
        ...
    }
}
</pre>
<h2>Blackjack Strategies</h2>
<p>Once you've constructed a game, you can then simulate a Blackjack session with any collection of player strategies. The NBF comes with a predefined set of strategies:</p>
<ul>
<li><strong>Basic Strategy</strong> - This is the standard strategy you find in Las Vegas gift shops on those little playing card-sized action tables. It's a losing strategy, but without card counting it's about as close to a fair bet as you're likely to get.</li>
<li><strong>Wizard of Odds Simple Strategy</strong> - For most people, basic strategy is too complicated to memorize. The <a href="http://wizardofodds.com/blackjack">Wizard of Odds</a> gives a simplified version of basic strategy that sacrifices a small percentage of expected value compared to basic strategy but is concise enough to memorize.</li>
<li><strong>Simple Five Count Strategy</strong> - The more fives that have been played, the more likely it is the dealer will bust when it hits. This strategy plays basic strategy but counts the number of fives that have been played, increasing the bet size as more fives are dealt.</li>
</ul>
<p>The three above strategies are just a jumping off point. It's simple enough to create your own strategy that does a more complex counting system, just implement the IBlackjackPlayer interface:</p>
<pre class="brush:c-sharp">
/// &lt;summary&gt;
/// An interface that all Blackjack players and strategies must implement.
/// &lt;/summary&gt;
public interface IBlackjackPlayer
{
    /// &lt;summary&gt;
    /// The total amount that the player has won or lost in the current game.
    /// &lt;/summary&gt;
    decimal Profit { get; set; }

    /// &lt;summary&gt;
    /// The number of splits this player has done in the current game.
    /// &lt;/summary&gt;
    int Splits { get; set; }

    /// &lt;summary&gt;
    /// Returns true if the player will play the next hand.
    /// False means they're done and not sitting back down.
    /// &lt;/summary&gt;
    bool PlayAnotherHand();

    /// &lt;summary&gt;
    /// Returns the amount the player is wagering on this hand.
    /// &lt;/summary&gt;
    decimal GetBet(decimal min, decimal max);

    /// &lt;summary&gt;
    /// Returns true if the player wants to split the hand.
    /// &lt;/summary&gt;
    bool Split(HandInfo info);

    /// &lt;summary&gt;
    /// Returns true if the player wants to double down on the hand.
    /// &lt;/summary&gt;
    bool DoubleDown(HandInfo info);

    /// &lt;summary&gt;
    /// Returns true if the player wants to hit the hand.
    /// &lt;/summary&gt;
    bool Hit(HandInfo info);

    /// &lt;summary&gt;
    /// Returns true if the player wants to buy insurance.
    /// &lt;/summary&gt;
    bool BuyInsurance(HandInfo info);

    /// &lt;summary&gt;
    /// Returns true if the player wants to surrender this hand.
    /// &lt;/summary&gt;
    bool Surrender(HandInfo info);

    /// &lt;summary&gt;
    /// Updates the player with the full info on the hand and how
    /// much they won or lost on it. Counting strategies can update
    /// here.
    /// &lt;/summary&gt;
    void HandOver(HandInfo info);

    /// &lt;summary&gt;
    /// Called when the dealer shuffles the deck
    /// &lt;/summary&gt;
    void Reshuffle();
}
</pre>
<h2>Running the Simulator</h2>
<p>The ConsoleBlackjack project provides the skeleton needed to run the project:</p>
<pre class="brush:c-sharp">
class Program
{
    static void Main(string[] args)
    {
        BlackjackSettings settings = LoadSettingsFromFile("settings.xml");
        BlackjackGame game = new BlackjackGame(settings);

        var handsToPlay = 100000000L;
        var player = new SimpleFiveCountPlayer(handsToPlay);

        game.Play(new [] { player });
        Console.WriteLine("Profit: {0:N2}%",
                player.Profit / settings.MinimumBet / (decimal)handsToPlay * 100m);
    }

    ...
}
</pre>
<p>Note that this project also provides a ConsoleBlackjackPlayer that enables you to play blackjack yourself via the command line. Just create a new instance of ConsoleBlackjackPlayer the same way you would any other strategy, and set the Game property to the Blackjack game instance.</p>
<h2>Conclusion</h2>
<p>The NashCoding Blackjack Framework is designed to facilitate statistics and AI research in the game of Blackjack. It should be able to simulate about 100,000 hands per second on a modern machine, and typically you need at least 100 million hands to get a stable expected value for a strategy. Although the game has been researched heavily, there are still a lot of questions to be answered particularly regarding the interaction of multiple strategies. If you find the framework useful or if you discover a bug, please let me know. <img src='http://www.nashcoding.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Source code for this post is available <a href="http://www.nashcoding.com/wp-content/uploads/2010/10/Blackjack.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2010/10/03/a-csharp-blackjack-simulation-framework/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Evolving Nash Equilibria &#8211; A Quick Correction</title>
		<link>http://www.nashcoding.com/2010/09/29/evolving-nash-equilibria-a-quick-correction/</link>
		<comments>http://www.nashcoding.com/2010/09/29/evolving-nash-equilibria-a-quick-correction/#comments</comments>
		<pubDate>Wed, 29 Sep 2010 15:02:46 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Evolutionary Computation]]></category>
		<category><![CDATA[Poker]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=27</guid>
		<description><![CDATA[As I noted in my first post, I was a little skeptical about whether a Nash Equilibrium (NE) could be evolved by taking the squared loss of each hand. My conclusions were that, given an expected value evaluation function, it was possible using a best-opponent fitness but not using a squared-loss fitness. There turns out [...]]]></description>
			<content:encoded><![CDATA[<p>As I <a href="http://www.nashcoding.com/?p=4">noted in my first post</a>, I was a little skeptical about whether a Nash Equilibrium (NE) could be evolved by taking the squared loss of each hand. My conclusions were that, given an expected value evaluation function, it was possible using a best-opponent fitness but not using a squared-loss fitness. There turns out to be a small bug in the squared loss code which caused a big change in results. Below are the results for the correct fitness function implementation.<br />
<span id="more-27"></span><br />
<div id="attachment_25" class="wp-caption alignnone" style="width: 733px"><a href="http://www.nashcoding.com/wp-content/uploads/2010/04/squared_losses.png"><img class="size-full wp-image-25" title="squared_losses" src="http://www.nashcoding.com/wp-content/uploads/2010/04/squared_losses.png" alt="Champion parameter values using squared losses as fitness." width="723" height="393" /></a><p class="wp-caption-text">Champion parameter values using squared losses as fitness.</p></div></p>
<p>As you can see, the fitness function does actually find the NE for the AKQ game. It stabilizes at player 1 betting 1/3 of the time with a queen and player 2 calling 1/3 of the time with a king.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2010/09/29/evolving-nash-equilibria-a-quick-correction/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tutorial – Evolving Neural Networks with SharpNEAT 2 (Part 2)</title>
		<link>http://www.nashcoding.com/2010/07/24/tutorial-%e2%80%93-evolving-neural-networks-with-sharpneat-2-part-2/</link>
		<comments>http://www.nashcoding.com/2010/07/24/tutorial-%e2%80%93-evolving-neural-networks-with-sharpneat-2-part-2/#comments</comments>
		<pubDate>Sat, 24 Jul 2010 20:33:44 +0000</pubDate>
		<dc:creator>Wesley</dc:creator>
				<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Evolutionary Computation]]></category>
		<category><![CDATA[Neural Networks]]></category>
		<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.nashcoding.com/?p=177</guid>
		<description><![CDATA[In part 1 of the tutorial, we setup a basic experiment to evolve a neural network to play Tic-Tac-Toe against a couple of hand-coded opponents. In part 2, we're going to create a competitive coevolution experiment where the networks evolve by playing against themselves. Competitive coevolution is an approach to evolving individuals by competing them [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.nashcoding.com/?p=90">part 1</a> of the tutorial, we setup a basic experiment to evolve a neural network to play Tic-Tac-Toe against a couple of hand-coded opponents. In part 2, we're going to create a competitive coevolution experiment where the networks evolve by playing against themselves.<br />
<span id="more-177"></span><br />
Competitive coevolution is an approach to evolving individuals by competing them against each other and using relative fitness scores. This approach is particularly useful when you have a domain where writing a hand-coded opponent is prohibitively expensive. While games like Tic-Tac-Toe may be simple enough to write optimal players, once you get to games that are more complex like Checkers or Chess, it becomes almost impossible to write a scripted expert player.<sup class='footnote'><a href='#fn-177-1' id='fnref-177-1'>1</a></sup></p>
<p>The current <a href="http://sites.google.com/site/sharpneat/dev-releases-status">SharpNEAT</a> release does not include any support for coevolution, so we're going to build it from scratch.<sup class='footnote'><a href='#fn-177-2' id='fnref-177-2'>2</a></sup></p>
<h2>The ICoevolutionPhenomeEvaluator</h2>
<p>If you recall from Part 1, we created a custom implementation of the IPhenomeEvaluator. This evaluator played a black box against both a random player and an optimal player then returned a fitness score. We'll stick to the same design by creating the ICoevolutionPhenomeEvaluator:</p>
<pre class="brush:c-sharp">
/// &lt;summary&gt;
/// Represents an evaluator that competes two phenomes against each other.
/// &lt;/summary&gt;
public interface ICoevolutionPhenomeEvaluator&lt;TPhenome&gt;
{
    ...
    /// &lt;summary&gt;
    /// Evaluate the provided phenomes and return their fitness scores.
    /// &lt;/summary&gt;
    void Evaluate(TPhenome phenome1, TPhenome phenome2,
                       out FitnessInfo fitness1, out FitnessInfo fitness2);
}
</pre>
<p>Classes implementing this interface define an Evaluate method that competes phenome1 against against phenome2, setting their respective fitness scores at the end.</p>
<h2>A Parallel Coevolution Genome List Evaluator</h2>
<p>The standard approach in two-player competitive coevolution is to play round-robin style (i.e., exhaustively compete every possible pair of individuals). Scores are then aggregated together into a final fitness score for each individual. To do this, we need to create a custom implementation of IGenomeListEvaluator.</p>
<pre class="brush:c-sharp">
public class ParallelCoevolutionListEvaluator&lt;TGenome, TPhenome&gt;
      : IGenomeListEvaluator&lt;TGenome&gt;
{
    readonly IGenomeDecoder&lt;TGenome, TPhenome&gt; _genomeDecoder;
    readonly ICoevolutionPhenomeEvaluator&lt;TPhenome&gt; _phenomeEvaluator;
    readonly ParallelOptions _parallelOptions;
    ...
    /// &lt;summary&gt;
    /// Main genome evaluation loop with no phenome caching (decode
    /// on each evaluation). Individuals are competed pairwise against
    /// every other in the population.
    /// Evaluations are summed to get the final genome fitness.
    /// &lt;/summary&gt;
    public void Evaluate(IList&lt;TGenome&gt; genomeList)
    {
        //Create a temporary list of fitness values
        FitnessInfo[] results = new FitnessInfo[genomeList.Count];
        for (int i = 0; i &lt; results.Length; i++)
            results[i] = FitnessInfo.Zero;

        // Exhaustively compete individuals against each other.
        Parallel.For(0, genomeList.Count, delegate(int i)
        {
            for(int j = 0; j &lt; genomeList.Count; j++)
            {
                // Don't bother evaluating inviduals against themselves.
                if (i == j)
                    continue;

                // Decode the first genome.
                TPhenome phenome1 = _genomeDecoder.Decode(genomeList[i]);

                // Check that the first genome is valid.
                if (phenome1 == null)
                    continue;

                // Decode the second genome.
                TPhenome phenome2 = _genomeDecoder.Decode(genomeList[j]);

                // Check that the second genome is valid.
                if (phenome2 == null)
                    continue;

                // Compete the two individuals against each other and get
                // the results.
                FitnessInfo fitness1, fitness2;
                _phenomeEvaluator.Evaluate(phenome1, phenome2,
                                                       out fitness1, out fitness2);

                // Add the results to each genome's overall fitness.
                // Note that we need to use a lock here because
                // the += operation is not atomic.
                lock (results)
                {
                    results[i]._fitness += fitness1._fitness;
                    results[i]._alternativeFitness +=
                                                  fitness1._alternativeFitness;
                    results[j]._fitness += fitness2._fitness;
                    results[j]._alternativeFitness +=
                                                  fitness2._alternativeFitness;
                }
            }
        });

        // Update every genome in the population with its new fitness score.
        for (int i = 0; i &lt; results.Length; i++)
        {
            genomeList[i].EvaluationInfo.SetFitness(results[i]._fitness);
            genomeList[i].EvaluationInfo.AlternativeFitness =
                                                  results[i]._alternativeFitness;
        }
    }
}
</pre>
<p>We start by creating an array of fitness scores that will store the overall fitness of each genome. We then do a parallel nested for-loop over the population.<sup class='footnote'><a href='#fn-177-3' id='fnref-177-3'>3</a></sup> Each individual is decoded from a genome to its phenotypic representation, and the two phenomes are evaluated against each other. Once the evaluation is finished, we update the genomes' overall fitness scores. When all evaluations are done, we set the genome's final fitness scores.</p>
<p>We've now built a general two-player competitive coevolution extension for SharpNEAT. It's time to get back to our specific problem domain.</p>
<h2>Creating a Coevolution Evaluator for Tic-Tac-Toe</h2>
<p>Our coevolution evaluator will take two black boxes and compete them in a game of Tic-Tac-Toe, with 10 points for a win, 1 point for a draw, and 0 points for a loss.<sup class='footnote'><a href='#fn-177-4' id='fnref-177-4'>4</a></sup> The code is actually pretty simple:</p>
<pre class="brush:c-sharp">
public class TicTacToeCoevolutionEvaluator : ICoevolutionPhenomeEvaluator<IBlackBox>
{
    ...

    /// &lt;summary&gt;
    /// Evaluate the two black boxes by playing them against each other in a
    /// game of Tic-Tac-Toe. All permutations of size 2 are going to be
    /// evaluated, so we only play one game: box1 is X, box2 is O.
    /// &lt;/summary&gt;
    public void Evaluate(IBlackBox box1, IBlackBox box2,
                        out FitnessInfo fitness1, out FitnessInfo fitness2)
    {
        // box1 plays as X.
        NeatPlayer player1 = new NeatPlayer(box1, SquareTypes.X);

        // box2 plays as O.
        NeatPlayer player2 = new NeatPlayer(box2, SquareTypes.O);

        // Play the two boxes against each other.
        var winner = TicTacToeGame.PlayGameToEnd(player1, player2);

        // Score box1
        double score1 = getScore(winner, SquareTypes.X);
        fitness1 = new FitnessInfo(score1, score1);

        // Score box2
        double score2 = getScore(winner, SquareTypes.O);
        fitness2 = new FitnessInfo(score2, score2);

        // Update the evaluation counter.
        _evalCount++;
    }
}
</pre>
<p>Our ParallelCoevolutionListEvaluator is going to evaluate all permutations, so we will see matchups of genome #1 vs. genome #2 and genome #2 vs. genome #1. Thus, we only have to play 1 game per evaluation, with player 1 as X. </p>
<h2>A Custom Experiment</h2>
<p>Since we're using our own list evaluator, we will need to create our own INeatExperiment. Most of the code is identical to the code from SimpleNeatExperiment in part 1. The only important difference is in the CreateEvolutionAlgorithm method:</p>
<pre class="brush:c-sharp">
public class TicTacToeCoevolutionExperiment : INeatExperiment
{
    ...

    /// &lt;summary&gt;
    /// Create and return a NeatEvolutionAlgorithm object ready for running
    /// the NEAT algorithm/search. Various sub-parts of the algorithm are
    /// also constructed and connected up.
    /// This overload accepts a pre-built genome2 population and their
    /// associated/parent genome factory.
    /// &lt;/summary&gt;
    public NeatEvolutionAlgorithm&lt;NeatGenome&gt; CreateEvolutionAlgorithm(
             IGenomeFactory&lt;NeatGenome&gt; genomeFactory,
             List&lt;NeatGenome&gt; genomeList)
    {
        // Create distance metric. Mismatched genes have a fixed distance
        // of 10; for matched genes the distance is their weigth difference.
        IDistanceMetric distanceMetric = new ManhattanDistanceMetric(1.0, 0.0, 10.0);
        ISpeciationStrategy&lt;NeatGenome&gt; speciationStrategy =
                  new ParallelKMeansClusteringStrategy&lt;NeatGenome&gt;(
                      distanceMetric, _parallelOptions);

        // Create complexity regulation strategy.
        IComplexityRegulationStrategy complexityRegulationStrategy =
                  ExperimentUtils.CreateComplexityRegulationStrategy(
                     _complexityRegulationStr, _complexityThreshold);

        // Create the evolution algorithm.
        NeatEvolutionAlgorithm&lt;NeatGenome&gt; ea =
                  new NeatEvolutionAlgorithm&lt;NeatGenome&gt;(
                    _eaParams, speciationStrategy, complexityRegulationStrategy);

        // Create genome decoder.
        IGenomeDecoder&lt;NeatGenome, IBlackBox&gt; genomeDecoder =
                  CreateGenomeDecoder();

        // Create a genome list evaluator. This packages up the genome decoder
        // with the phenome evaluator.
        IGenomeListEvaluator&lt;NeatGenome&gt; genomeListEvaluator =
                  new ParallelCoevolutionListEvaluator&lt;NeatGenome, IBlackBox&gt;(
                      genomeDecoder, PhenomeEvaluator);

        // Wrap a hall of fame evaluator around the baseline evaluator.
        genomeListEvaluator =
                 new ParallelHallOfFameListEvaluator&lt;NeatGenome, IBlackBox&gt;(
                     50, 0.5, ea, genomeListEvaluator, genomeDecoder, PhenomeEvaluator);

        // Initialize the evolution algorithm.
        ea.Initialize(genomeListEvaluator, genomeFactory, genomeList);

        // Finished. Return the evolution algorithm
        return ea;
    }
    ...
}
</pre>
<p>The first portion of the code sets up the way SharpNEAT performs speciation, complexity regulation, and the basic EvolutionAlgorithm. We aren't toying with those parts (maybe in a future tutorial).</p>
<p>After that, we get to the code that creates our custom list evaluator. If you compare this with the code for SimpleNeatExperiment, you'll see all we had to do here was replace type of evaluator we're creating.</p>
<h2>Bonus! A Hall of Fame Evaluator</h2>
<p>In the above code you probably noticed we are also creating something called ParallelHallOfFameListEvaluator and passing it our original list evaluator. It's common in coevolution experiments to maintain a "hall of fame" where every few generations we save the best individual. Future individuals then have to compete against not just the current population but also the best individuals from the previous populations. Let's take a look at the first part of how this evaluator is implemented:</p>
<pre class="brush:c-sharp">
/// &lt;summary&gt;
/// Represents a Hall of Fame evaluator.
///
/// Champion genomes are periodically stored to create a Hall of Fame. All successive
/// generations are required to evaluate against both their own population and
/// the hall of fame. A genome's overall fitness is a weighted sum of its
/// fitness against the population and the hall of fame.
/// &lt;/summary&gt;
public class ParallelHallOfFameListEvaluator&lt;TGenome, TPhenome&gt;
      : IGenomeListEvaluator&lt;TGenome&gt;
{
    readonly IGenomeDecoder&lt;TGenome, TPhenome&gt; _genomeDecoder;
    readonly ICoevolutionPhenomeEvaluator&lt;TPhenome&gt; _phenomeEvaluator;
    readonly ParallelOptions _parallelOptions;
    readonly uint _generationsPerChampion;
    readonly IGenomeListEvaluator&lt;TGenome&gt; _innerEvaluator;
    readonly double _hallOfFameWeight;

    uint _lastUpdate;
    List&lt;TGenome&gt; _hallOfFame;

    ...

    /// &lt;summary&gt;
    /// Construct with the provided number of generations per champion, weight to the hall
    /// of fame fitness, parallel options, and other parameters.
    /// &lt;/summary&gt;
    public ParallelHallOfFameListEvaluator(uint generationsPerChampion,
                              double hallOfFameWeight,
                              AbstractGenerationalAlgorithm&lt;TGenome&gt; ea,
                              IGenomeListEvaluator&lt;TGenome&gt; innerEvaluator,
                              IGenomeDecoder&lt;TGenome, TPhenome&gt; genomeDecoder,
                              ICoevolutionPhenomeEvaluator&lt;TPhenome&gt; phenomeEvaluator,
                              ParallelOptions options)
    {
        Debug.Assert(hallOfFameWeight >= 0d);
        Debug.Assert(hallOfFameWeight <= 1d);

        _generationsPerChampion = generationsPerChampion;
        _hallOfFameWeight = hallOfFameWeight;
        _innerEvaluator = innerEvaluator;
        _genomeDecoder = genomeDecoder;
        _phenomeEvaluator = phenomeEvaluator;
        _parallelOptions = options;

        _hallOfFame = new List&lt;TGenome&gt;();
        ea.UpdateEvent += new EventHandler(ea_UpdateEvent);
    }

    ...

    private void ea_UpdateEvent(object sender, EventArgs e)
    {
        // Make sure that the event sender is an EA.
        Debug.Assert(sender is AbstractGenerationalAlgorithm&lt;TGenome&gt;);

        // Cast the EA so we can access the current champion.
        AbstractGenerationalAlgorithm&lt;TGenome&gt; ea =
                         (AbstractGenerationalAlgorithm&lt;TGenome&gt;)sender;

        // Update every few generations.
        if (ea.CurrentGeneration &lt; (_generationsPerChampion + _lastUpdate))
            return;

        // Update the update counter.
        _lastUpdate = ea.CurrentGeneration;

        // Add the genome to the hall of fame.
        _hallOfFame.Add(ea.CurrentChampGenome);

        Console.WriteLine("Hall of Fame Updated. Size: {0}", _hallOfFame.Count);
    }

}
</pre>
<p>The hall of fame evaluator takes a few parameters worth noting:</p>
<ul>
<li><b>generationsPerChampion</b> - The number of generations that have to elapse before saving another population champion to the hall of fame.</li>
<li><b>hallOfFameWeight</b> - The weight given to the fitness against the hall of fame, as a percentage of the total weight. For example, if hallOfFameWeight is 0.3, then the final fitness for a genome will be 0.3 * hallOfFameFitness + 0.7 * innerEvaluatorFitness.</li>
<li><b>innerEvaluator</b> - The evaluator to use as the other portion of the overall fitness.</li>
</ul>
<p>In the constructor, the hall of fame evaluator adds itself to the evolution algorithm's update event. The EA will trigger the ea_UpdateEvent method periodically, according to whatever UpdateScheme we have defined. We assume that whatever scheme the user has chosen is what they want, and we work around it in ea_UpdateEvent. In this method, we check if we are due for an update and if we are, we add the current population champion to the hall of fame.</p>
<p>Most of the evaluation code is identical to the coevolution list evaluator:</p>
<pre class="brush:c-sharp">
public class ParallelHallOfFameListEvaluator&lt;TGenome, TPhenome&gt;
      : IGenomeListEvaluator&lt;TGenome&gt;
{
    ...

    /// &lt;summary&gt;
    /// Main genome evaluation loop with no phenome caching (decode on each evaluation).
    /// Individuals are competed pairwise against every champion in the hall of fame.
    /// The final fitness score is the weighted sum of the fitness versus the champions
    /// and the fitness score by the inner evaluator.
    /// &lt;/summary&gt;
    public void Evaluate(IList&lt;TGenome&gt; genomeList)
    {
        _innerEvaluator.Evaluate(genomeList);

        // Create a temporary list of fitness values
        // with the scores of the inner evaluator.
        FitnessInfo[] results = new FitnessInfo[genomeList.Count];
        double innerWeight = 1.0 - _hallOfFameWeight;
        for (int i = 0; i &lt; results.Length; i++)
            results[i] = new FitnessInfo(
                        genomeList[i].EvaluationInfo.Fitness * innerWeight,
                        genomeList[i].EvaluationInfo.AlternativeFitness * innerWeight);

        // Calculate how much each champion game is worth
        double championGameWeight = _hallOfFameWeight / (double)_hallOfFame.Count;

        // Exhaustively compete individuals against each other.
        Parallel.For(0, genomeList.Count, delegate(int i)
        {
            // Decode the first genome.
            TPhenome phenome1 = _genomeDecoder.Decode(genomeList[i]);

            // Check that the first genome is valid.
            if (phenome1 == null)
                return;

            for (int j = 0; j &lt; _hallOfFame.Count; j++)
            {
                // Decode the second genome.
                TPhenome phenome2 = _genomeDecoder.Decode(_hallOfFame[j]);

                // Check that the second genome is valid.
                if (phenome2 == null)
                    continue;

                // Compete the two individuals against each other and get the results.
                FitnessInfo fitness1, fitness2;
                _phenomeEvaluator.Evaluate(phenome1, phenome2,
                                                       out fitness1, out fitness2);

                // Add the results to each genome's overall fitness.
                // Note that we need to use a lock here because
                // the += operation is not atomic.
                lock (results)
                {
                    results[i]._fitness += fitness1._fitness * championGameWeight;
                    results[i]._alternativeFitness +=
                                  fitness1._alternativeFitness * championGameWeight;
                }
            }
        });

        // Update every genome in the population with its new fitness score.
        for (int i = 0; i &lt; results.Length; i++)
        {
            genomeList[i].EvaluationInfo.SetFitness(results[i]._fitness);
            genomeList[i].EvaluationInfo.AlternativeFitness =
                                                          results[i]._alternativeFitness;
        }
    }

    ...
}
</pre>
<p>There are a couple differences from the coevolution list evaluator. Rather than setting the overall fitness scores to zero at the start, we set them equal to the weighted value of the inner evaluator's fitness scores. Also, our inner loop is over the hall of fame rather than the population. The rest of code then functions just like the coevolution evaluator, but adds weighted scores for each individual evaluation.</p>
<h2>Running the Experiment</h2>
<p>Surprisingly, our actual main Program file is almost exactly the same. The only alteration we have to make is that we're creating a different type of experiment (TicTacToeCoevolutionExperiment):</p>
<pre class="brush:c-sharp">
class Program
{
    static NeatEvolutionAlgorithm&lt;NeatGenome&gt; _ea;
    const string CHAMPION_FILE =
                 @"..\..\..\NeatTicTacToe\bin\Debug\coevolution_champion.xml";

    static void Main(string[] args)
    {
        // Initialise log4net (log to console).
        XmlConfigurator.Configure(new FileInfo("log4net.properties"));

        // Experiment classes encapsulate much of the nuts
       // and bolts of setting up a NEAT search.
        TicTacToeCoevolutionExperiment experiment =
                                      new TicTacToeCoevolutionExperiment();

        // Load config XML.
        XmlDocument xmlConfig = new XmlDocument();
        xmlConfig.Load("tictactoe.config.xml");
        experiment.Initialize("TicTacToe", xmlConfig.DocumentElement);

        // Create evolution algorithm and attach update event.
        _ea = experiment.CreateEvolutionAlgorithm();
        _ea.UpdateEvent += new EventHandler(ea_UpdateEvent);

        // Start algorithm (it will run on a background thread).
        _ea.StartContinue();

        // Hit return to quit.
        Console.ReadLine();
    }

    static void ea_UpdateEvent(object sender, EventArgs e)
    {
        Console.WriteLine(string.Format("gen={0:N0} bestFitness={1:N6}",
                        _ea.CurrentGeneration, _ea.Statistics._maxFitness));

        // Save the best genome to file
        var doc = NeatGenomeXmlIO.SaveComplete(
                       new List&lt;NeatGenome&gt;() { _ea.CurrentChampGenome }, false);
        doc.Save(CHAMPION_FILE);
    }
}
</pre>
<p>The program saves the best genome to the GUI's debug\bin directory, so you can launch the game and easily load the champion XML file.</p>
<h2>Conclusion</h2>
<p>That's it! In this tutorial, we saw how to create a two-player competitive coevolution experiment in SharpNEAT. We created an experiment to evolve a Tic-Tac-Toe AI by playing individuals in the population them against each other. By now you know how to setup a coevolution experiment, create custom population evaluators, and handle update events</p>
<p>If you played against our AI, you probably noticed it (still) sucks. That's (still) okay! The coevolution player is definitely at least as good as the player from part 1, and we didn't have to hand-code any opponent strategies, so I'm calling it a success. The next part of this tutorial will introduce HyperNEAT, a powerful extension to the NEAT algorithm that enables us to leverage the inherent geometry and symmetry of the game board. The result will (hopefully) be a stronger AI opponent.</p>
<p>Source code for part 2 of the tutorial is available <a href="http://www.nashcoding.com/wp-content/uploads/2010/07/TicTacToeCoevolution.zip">here</a>.</p>
<p><b>Update July 25, 2010:</b> I implemented a second approach to competitive coevolution. This approach, called Host-Parasite coevolution, has two populations evolving simultaneously. Fitness scoring is then a function of performance against the other population (called the parasite population) and a hall of fame of previous generational champions. The project doesn't cover any new features of SharpNEAT, so I'm not going to make a full write up on it. If you want to read more about the approach see <a href="http://nn.cs.utexas.edu/keyword?stanley:jair04">this paper</a>. Updated source code is available <a href="http://www.nashcoding.com/wp-content/uploads/2010/07/HostParasiteTicTacToe.zip">here</a>.</p>
<h5>Footnotes</h5>
<div class='footnotes'>
<div class='footnotedivider'></div>
<ol>
<li id='fn-177-1'>For an excellent book on evolving neural networks to play checkers, check out <a href="http://www.amazon.com/gp/product/1558607838?ie=UTF8&#038;tag=nashc02-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=1558607838">Blondie24</a><img src="http://www.assoc-amazon.com/e/ir?t=nashc-20&#038;l=as2&#038;o=1&#038;a=1558607838" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />. Full disclosure: it was written by my current boss, but he's only my boss because I read it and it inspired me to go into AI. <img src='http://www.nashcoding.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  <span class='footnotereverse'><a href='#fnref-177-1'>&#8617;</a></span></li>
<li id='fn-177-2'>For simplicity, we're going to assume that "coevolution" means two-player competitive coevolution. In general, coevolution is not limited to two players and you can even have cooperative coevolution. I just really didn't want to create a bunch of classes that start with <i>TwoPlayerCompetitiveCoevolution</i>. <span class='footnotereverse'><a href='#fnref-177-2'>&#8617;</a></span></li>
<li id='fn-177-3'>If you're not familiar with the Parallel Task Library, don't worry. This code is equivalent to just two nested foreach statements. <span class='footnotereverse'><a href='#fnref-177-3'>&#8617;</a></span></li>
<li id='fn-177-4'>As I noted in part 1, remember that fitness scores in NEAT always have to be positive. <span class='footnotereverse'><a href='#fnref-177-4'>&#8617;</a></span></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.nashcoding.com/2010/07/24/tutorial-%e2%80%93-evolving-neural-networks-with-sharpneat-2-part-2/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

