Friday, September 26, 2014

Am I a better Gin Rummy player than the AI?

When I have a moment of downtime I like to play Gin Rummy on my cell phone. (I play the one made by AI Factory on an Android phone.) The game offers a number of different opponents to play against (unfortunately not another human, though. My wife and I tried one app that allows us to play each other over Bluetooth but its interface just doesn't match AI Factory's. We also have played with actual cards but, after playing on a phone for too long, shuffling and dealing become annoyingly slow.). The opponents are given a difficulty rating between 1 and 5 stars. I lost most of the stats I had accumulated after switching to a new phone but I always thought "Jane" was the most challenging. On my new phone she's the only one I've played against. Right now I've got a 40-46 win/loss record against Jane. That's a 0.465 win rate. So does that mean I'm worse than Jane?

Don't answer that question! Give me a minute to explain myself before you blurt out "yes!" ... So would you believe me if I said my wife took my phone, lost a bunch of games and ruined my stats? No? I've never been good at lying so let's think about this. My ego is at stake here.

Shoulder devil: You stink at Gin Rummy. You're losing to some freaking electrons zipping around in your phone! Pathetic.
Shoulder angel: You don't stink. 46.5% is good! And this is a game with a lot of random variation. Even a skilled player will lose to an amateur sometimes. And you're getting better each time you play!
(We will ignore the comment on skill and assume for today that my skill was the same over all games played.)
Self: Hmmm... random variation. So maybe it was just a string of bad luck?
Shoulder angel: Yes... I mean maybe... Yes to maybe.

I have played 86 games so far. If I flipped a coin 86 times, how many times will it come out heads? The most likely outcome is 43. But even more likely is not getting this outcome. I'll say that again. You're more likely not to get 43 heads in 86 flips but some other number. How much more likely?

The pmf for the binomial distribution is
\begin{equation}
Pr(K=k) = \binom{n}{k} p^{k} (1-p)^{n-k}
\end{equation}
where $n$ is the number of trials, $k$ is the number of successes and $p$ is the probability of success. For our problem we get
\begin{equation}
Pr(K=43) = \binom{86}{43} (0.5)^{43} (1-0.5)^{86-43} = 0.086.
\end{equation}

So if you flipped a fair coin 86 times every day and did this for thousands of days, you'd get 43 heads on 8.6% of those days. The other 91.4% of the days would result in some other number of heads. (The fact that our rounded probability of 0.086 is 86/1000 and 86 is the number of trials is a coincidence. Don't get hung up on that.)

Shoulder devil: And...
Self: So if you figure out the probability for 40 successes out of 86, you get 0.070. Also small but not so different than 0.086 that you might say that the losses were entirely due to skill.
Shoulder devil: That sounds kind of subjective to me. I think 0.070 and 0.086 are very different. Loser.
Self: Let's quantify it!
(This is when "QUANTIFY" would zoom in and zoom out with a spinning background a-la the Batman symbol.)
Shoulder angel: So what exactly are we quantifying?

What we'd ultimately like to know is the true probability $p$ of success. If it's greater than 0.5 then I am a better player. If it's less, then Jane is better. But we really can't know what that value is so we'll find a confidence interval that makes us comfortable.

At this point we'll try to find the "binomial proportion confidence interval." (I know Wikipedia isn't the best reference. But it is sometimes a good source of references.) The binomial proportion is the probability $p$. The confidence interval will give a range of values of $p$ that is most likely to contain our true value. I won't go into the many methods for calculating this (this is left as an exercise to the reader (I hate reading that in books)). I will give the Clopper-Pearson interval for today. A 95% confidence interval using this method for 40 successes in 86 trials gives $0.35678 \le p \le 0.57592$.

Shoulder angel: Look at that! It could be as high as 0.575! Maybe you are better than Jane.
Shoulder devil: Or as low as 0.357. Don't celebrate too much, chump.

So am I better than Jane? Maybe... Yes to maybe.
(My gut tells me that right now that I am not better. Recently, however, I've thought of some new strategies that may help. So, again, maybe.)

Kevin McCallister: You guys give up? Or ya thirsty for more?

A while ago I read this article at Grantland by Bill Barnwell. In the section titled "The Best of the Best" he gives a table of win/loss records of NFL quarterbacks in games decided by one touchdown or less (in footnote 2 of the article he indicates that this means games ending with a point differential of 7 or less). His table includes ties but for my purposes I'll leave those out. His table is sorted, logically, by win percentage. But the number of games ending in this situation for each quarterback ranges from 50 to 117. Is Terry Bradshaw's 0.593 in 59 games really better than Brett Favre's 0.581 in 117 games?

Shoulder devil: Yes. 0.593 is greater than 0.581. Greater is better. Yet you ask the question as if there's some reason for it not to be better. And if you have something in mind, why are you asking a question and not just telling me what you have in mind?

There's a lot of random variation in football games and the quarterback doesn't always control the outcome of a game, even if he is on the field. I submit that we should sort this list of quarterbacks by the lower bound of a 95% confidence interval on their win percentage, i.e., their binomial proportion.

Shoulder angel: Don't forget to be completely honest about the assumptions you're making.

I didn't say this when talking about Gin Rummy games but the assumption with a binomial process is that all trials are iid (independent and identically distributed). Since I assumed my skill level remained the same over all games and that the AI skill doesn't change either, this assumption seems fair. In football games this assumption is weaker (but we're going to make it anyway). For example, Brett Favre has 117 games here. That would take at least 8 seasons to play that many games (ignoring the playoffs). A quarterback's skill can vary over time. I don't have the raw data but how the game plays out matters, too. Was the team ahead and then gave up a meaningless end-game touchdown? Were they behind near the end and taking more risks to win? Were they playing at home? Who were they playing? The point of this is that iid is not as strong of an assumption as it was in Gin Rummy. But, like I said, we're going to make it anyway.

So if we add some new columns to the table and sort it by the lower bound of our 95% confidence interval we get the following.


Player GP W L Win% Win% LB Win% UB Win% Rank LB Rank Change
Tom Brady 76 54 22 0.711 0.595 0.809 1 1 0
Peyton Manning 103 66 37 0.641 0.540 0.733 3 2 1
Jim Kelly 69 44 25 0.638 0.513 0.750 4 3 1
Jay Schroeder 52 34 18 0.654 0.509 0.780 2 4 -2
Dan Marino 107 64 43 0.598 0.499 0.692 8 5 3
Brett Favre 117 68 49 0.581 0.486 0.672 11 6 5
Matt Hasselbeck 65 40 25 0.615 0.486 0.733 5 7 -2
Ken Stabler 67 41 26 0.612 0.485 0.729 6 8 -2
John Elway 112 64 48 0.571 0.474 0.665 14 9 5
Jake Plummer 53 32 21 0.604 0.460 0.735 7 10 -3
Brian Sipe 57 34 23 0.596 0.458 0.724 9 11 -2
Terry Bradshaw 59 35 24 0.593 0.457 0.719 10 12 -2
Joe Montana 69 40 29 0.580 0.455 0.698 13 13 0
Phil Simms 71 40 31 0.563 0.440 0.681 17 14 3
Dave Krieg 80 44 36 0.550 0.435 0.662 20 15 5
Ben Roethlisberger 64 36 28 0.563 0.433 0.686 18 16 2
Eli Manning 60 34 26 0.567 0.432 0.694 16 17 -1
Dan Pastorini 58 33 25 0.569 0.432 0.698 15 18 -3
Joe Theismann 50 29 21 0.580 0.432 0.718 12 19 -7
Fran Tarkenton 55 31 24 0.564 0.423 0.697 19 20 -1

Congratulations to Brett Favre and John Elway. Sorry, Joe Theismann. Interesting also is that only four quarterbacks have lower bound numbers higher than 0.500. That's not to say the rest of the quarterbacks weren't any better than some average replacement but it does go to show just how hard it is to be a really dominant quarterback in close games over a long period of time. Again that comes back to just how much other factors come into play in the outcome of a football game.

Tuesday, September 23, 2014

How to give your Google Voice number away

So for whatever reason you don't want/need your Google Voice number anymore. You could let it go stagnant for 9 months and let Google reclaim it (if Google gave it to you). Or you could give it to a friend who needs it. Now let me be clear that you are not allowed to sell your number. As stated in the Google Voice Acceptable Use Policy, "Do not sell, trade, resell or otherwise exploit for any unauthorized commercial purpose or transfer any Google Voice account or the Google Voice Service." One might argue that you can't transfer a Google Voice account, anyway, without transferring your entire Google account with it. If you transfer just the number from one account to another, with instructions for doing so given by Google here, only the number is transferred and not all of the other account information, such as texts, messages, contacts, etc. Does that mean we have some sort of loophole where we can sell the number but not the account (semantics!)? I don't know and am certainly not a lawyer. But I will describe how you can give your number to a friend.

Skeptical reader: If Google gives instructions on how to transfer your number from one account to another (and you even liked to those instructions earlier) why the heck are you explaining to me how to transfer my number?
Me: Trust! (and/or proximity)

The key to the transfer instructions is that Google requires you to be logged in to both accounts on the same computer, that is, both the account with the number and the account where you'd like the number. I like my friends but I'm not letting them log in to my account while they're logged in to theirs. And if we're not in the same room, then I'd have to share my password with them. That's not going to happen. So to keep my friend honest and to allow us to not have to be in the same room, do the following:

  1. Make a new GMail account with Google. This will be your "escrow" account.
    1. a) DON'T add two-factor authentication or recovery contact details (email, phone number) to this account. You just need a middleman.
  2. Transfer your Google Voice number from your account to this "escrow" account (following the instructions).
  3. Give the username and password of the "escrow" account to your friend.
  4. Now give your friend the instructions so he can transfer the number to his account.

Done! Friend-trust is still intact and now he has your old Google Voice number.

Friday, September 19, 2014

The Chain Rule

A friend of mine started taking a calculus class recently and I've been helping him with studying and homework. It had been a while for me but he had some questions about the chain rule. I thought the notation makes it kind of difficult. The chain rule is:
\[
f(g(x))' = f'(g(x))g'(x)
\]
But isn't $f(g(x))'$ the same thing as $f'(g(x))$? (No.) This is my explanation of how to apply the chain rule.

When not to use the chain rule

If you actually need to use other rules like the sum rule, product rule, or quotient rule.

When to use the chain rule

When you see an equation where you say something like, "I can find the derivative of part of that equation, and if that part were simply $x$ then I could solve the rest, too." You see a function within a function. It takes some practice. These are some pretty good examples.

How to solve the chain rule

The confusing part is that often the notation gives it as $f(g(x))' = f'(g(x))g'(x)$. What I prefer is longer but helps me.

You don't know the derivative to $h(x)$ but you can write it as
\[
h(x) = f(g(x))
\]
Write down $g(x)$ and $f(y)$ explicitly.
\[
f(y) =
\]
\[
g(x) =
\]
(I like to use $y$ instead of $x$ to try to help show the difference between $f$ and $g$.) Once those are written down, find $f'(y)$ and $g'(x)$. Write them out explicitly, also.
\[
f'(y) =
\]
\[
g'(x) =
\]
Now, wherever you still see a $y$ in $f'(y)$, replace it with $g(x)$ (the whole equation). That gives $f'(g(x))$. Now multiply $f'(g(x))$ by $g'(x)$. You're done! (Okay, you may not be done with algebra to simplify the result but you are done with the calculus part.)

Thursday, December 19, 2013

Getting an Elevation Profile From a Set of Directions (or Why is my baby crying?!)

My family and I live in Salt Lake City, UT. My wife's family is from the small town of Joseph City, AZ. We recently drove there for the Christmas holiday to spend time with family. It was our six-month-old daughter's first trip to Arizona and her first drive of this length. Without a baby it would take us about nine-and-a-half to ten hours to make the drive, depending on stops we took. This trip took us 11 hours; five short hours and six very long ones. She was not happy at all on the second half of the trip. It wasn't until we arrived in Joesph City that we realized that perhaps she was experiencing some uncomfortable air pressure differentials and wasn't able to "pop" her ears. That would have been nice to know at the time. We also didn't realize that she's teething and I think she just hated being in the car seat that long.

So my question was this: What's the best path to travel home to avoid elevation changes she might find uncomfortable? There are primarily three ways to travel between Salt Lake City and Joseph City. The first two go from Salt Lake to Kanab, UT, then to Flagstaff, AZ, then to Joseph City. They differ between Kanab and Flagstaff. You can either take 89A through the Kaibab National Forest or you can take 89 through Page, AZ (now temporarily detoured through 89T). According to Google Maps, following 89T instead of 89A is 3 miles longer and 2 minutes shorter. Not bad for an over-nine-hour trip spanning almost 600 miles. The third way is completely different. It travels through eastern Utah going through Moab, UT following Highway 191. This path is shorter than the other two by about 25 miles and 15 minutes according to Google Maps. Before the Route 89 landslide (ADOT updates) we would usually travel through Page, AZ. This time we took the 89A route. Had I known about 89T and that it was recently paved I probably would have gone that way. It's nice to have moderately sized cities along the trip like Kanab and Page. There's pretty much nothing between Kanab and Flagstaff going the 89A route. Our biggest worry was that Illa, our daughter, would break down about an hour past Kanab along 89A. That's exactly what happened.

Here's an elevation profile of the roads traveled following the 89A route (thanks to GPS visualizer):

See that giant peak at around mile 350? That's 89A through the Kaibab National Forest and then descending down to the Colorado River. The canyon is very deep and the bridge elevation is actually at about 3500 ft. This elevation plot uses the earth's elevation, not the road's, which only becomes a problem with bridges. Can you guess where Illa got extremely fussy? That peak. Now previous to this there were other similarly rapid ascents and descents but she had slept through them. This was also about 5 to 6 hours into the trip and she wanted out of that seat. So what do the other two paths look like?

Here it is taking the 89T route:
...stupid peak...

And here is it going through the Moab route:

That looks nice, too.

So I already mentioned and it's shown in the figures that these images were made using the GPS Visualizer website (http://www.gpsvisualizer.com/ and http://www.gpsvisualizer.com/elevation). The elevation profiles require either a link to the Google Maps driving directions or a kml file. What I did was download Google Earth for desktop, find the directions there, export it as a kml file, and upload that. The reason is because I couldn't get the links to work. The problem is that the link must be from the "classic" Google Maps and not the new preview version. Doh!

A tip for those who do use Google Earth. In Google Earth there were no alternate route suggestions and I couldn't see a way to add multiple stops. So I typed it in as given in the bold titles in the figures with multiple "to:" labels and locations. And when I say export it as a kml, I clicked this button
which is just below the driving directions box, pasted the contents into notepad, and saved it as a kml file. What a pain. I wish I had realized that Google Maps preview was the problem. To leave the Google Maps preview to go back to classic, find the question-mark-circle in the lower right of the map screen and click on it. There it will give an option to go back. Or you can open an Incognito window in Chrome to temporarily access classic Google Maps.

And a big thank you to GPS Visualizer. What a cool website that offers much more than elevation profiles.

So what will we do about the trip back and the baby? Probably break the trip over two days.

UPDATE (1/17/2014): So the trip back was a couple of weeks ago and I thought I'd follow up. We took the 89T route back, which was good. When we got to Panguitch we decided to keep going and make the trip in one day. That left one large mountain pass to go over. This was state highway 20 between highway 89 and I-15. She definitely got fussy as we climbed and descended but giving her something to chew on helped. Lesson learned.

Friday, November 15, 2013

D-Link DIR-601 Client Bridge with a Broadcom AP

I wanted a client bridge for a D-Link DIR-601 hardware rev. A1 to a ASUS RT-N16 AP running Tomato USB firmware. Is that so much to ask? Apparently, yes. The DD-WRT forums are full of people having trouble getting Atheros and Broadcom based routers to play nice with one another, especially in settings like a client bridge. The official response: Too bad. Maybe if you're lucky, but don't look at us for help.

Thanks.

So instead I try OpenWRT for the DIR-601. They suggest a pseudobridge. Maybe it works but I couldn't get it working. Then I stumble upon Gargoyle firmware. After finding out the hard way that version 1.5.11 is too big, I flashed version 1.5.10. Once I did that it was super easy to set up and worked the first time. Nice.

The easiest way to do it is this:
  1. No matter what firmware the DIR-601 is running right now, D-Link put in an emergency firmware loader that can be accessed in the following way:
    1. Unplug the router
    2. Push and hold the reset button while unplugged
    3. Plug in the router while holding the reset button
    4. Keep holding the button for about 10 seconds until the power light slowly blinks orange
    5. Manually configure your wired connection to 192.168.0.100, subnet 255.255.255.0.
    6. From a web browser, go to 192.168.0.1
    7. If nothing comes up, repeat steps 1-4 and try again.
    8. From here you can upload the original D-Link firmware or DD-WRT or OpenWRT or Gargoyle. Upload the "factory" firmware, that is, the firmware designed to be uploaded when the router is using D-Link's firmware. Don't upload the firmware designed to be uploaded from a third-party firmware. I used Gargoyle 1.5.10. Download it here. For the DIR-601 choose the AR71XX architecture. Search on the page to find 601-a1, choose factory.
  2. Reset your wired connection to accept DHCP.
  3. Log into your now Gargoyle router at 192.168.1.1. The default password is password.
  4. Set it up. It was pretty straight forward from here to get a client bridge going. What a breath of fresh air.
It works great with my Broadcom based access point (RT-N16). So far I've streamed an hour of Netflix with no problems.

A summary of what didn't work (at least for me):

  • DD-WRT (r16214 or r22118)
    • Client Bridge
    • WDS Station
  • OpenWRT (12.09-beta2 or 12.09)
    • pseudobridge (relayd)
    • WDS Station
  • Flashing anything from D-Link's firmware's GUI (not emergency) except DD-WRT r16214
  • Flashing anything from DD-WRT's GUI except DD-WRT
  • Gargoyle 1.5.11. It's too big. Nice to know it's still offered as a download for people who don't check before assuming a firmware is safe (me).

Friday, October 4, 2013

Academic Integrity

I'd like to post more often to the blog but two big things have happened in my life. First was the birth of our first child in May. She's a beautiful baby girl and is a light to our family. I'm so blessed to have her and my wonderful wife in my life. The second is my upcoming PhD dissertation defense that's scheduled for the 24th of October. Between those two things I've got a lot on my hands. I've got plenty of project ideas and I hope that once I settle into a job in January I'll get more up on the blog.

Despite my dissertation defense coming up in just 20 days, today I had to take some time to talk about academic integrity. And by talk I mean get some feelings off my chest because I'm just so annoyed right now. One of my most popular posts so far has been the MSP430 IR Remote Control. It was a ton of fun to do and I've got many more ideas on where to go from there. It was genuinely rewarding to watch that VCR turn on and off and to know that I did that. For that post I intentionally left the code off the site and unavailable unless you emailed me first. I did this for two reasons. First I'm just a sucker for getting emails from people. How fun! It gives me a chance to interact a little more with people who are working on using the IR transmitter for cool projects. I've had a blast hearing how it would be used. The second reason is one I take seriously. One of the big features of the MSP430 Launchpad pushed by Texas Instruments is its educational value. It's used by many universities in engineering courses to teach about microcontrollers and embedded systems. I did not want my work to become the way some student cheated through his engineering coursework or class project. Even without the code I feel like the post spells out pretty clearly the fundamentals you would need to get a project like this going.

Today I received the following email:
Hi, 
I have gone through your blog and found useful information regarding the IR receiver and codes used in the IR remotes. I'm working on an academic project and I need help regarding the code used for IR remotes using MSP430G2553 launchpad. So I thought I could get your assistance.
Thanks
I let the student know that I was happy to help and asked if it was for a class. I received the following reply:
Hi, 
Thanks for your reply. This is for the microprocessor class. I'm using sparkfun's IR remote and IR receiver breakout to communicate to launchpad controls. I'm using MSP430G2553 with CCS emulator. So could you please help me with coding this circuit using "C" language.
Thanks
Seriously? No. Of course not. Not in the way you intend me to. Do you have a specific question about how IR protocol works? Do you have a specific question about how I got something to work on the microcontroller? Or managed some problem you came across while coding? I'm happy to help. Do you want me to do your school project for you? Absolutely no.

I let the student know that I would not provide code and that his/her school's honor code prohibits such. To which I receive:
I do not need you to give me the code for it, you could at least tell me how to go about it, like what libraries to use and the flow diagram.

Thanks
I could at least... what?! I am under no obligation to tell anyone anything. I don't owe any reader more than what I've given. I don't even owe that. I could even remove content from my blog post if I feel like I'm giving too much to you. I think "you could at least" are the words that have bothered me more than any others through this exchange. Maybe "you could at least" have a solid measure of academic honesty in your work. And as far as "how to go about it" goes, I think the post gives more than enough information and that it speaks for itself. I'll link to it again.

At this point I was a little more blunt with the student. You need to read the material I linked to on the post. You need to struggle with the material. You need to make mistakes. That is how you learn. Your professor did not give you a class project to burden you or annoy you. Your project is not an exercise is getting by with as little work as possible by cobbling together others' work into something that maybe will work and that you surely don't understand. Your project is for you, believe it or not. It's for you to grow, make mistakes, ask yourself "what in the world?" a hundred times before that epiphany where you get it, and come out better for it. It's for you to learn. Just like your project, school itself is not some futile exercise on your way to that sweet engineering job you deserve with the six-figure salary you get from day one. It's for you to learn. And if you cheat, you're not fooling the school or your employer. You're not cleverly getting by those dumb restrictions that just aren't used in "the real world." You're cheating yourself out of the best opportunity you have right now to be something more than what you are right now. It takes a lot of hard work to do it right and a lot of time to do it all. That's precisely why it's worth doing. (I didn't say all of that to the student but some of the good bits.)

As a student myself for many years, I don't expect any less of myself or my peers than having high standards of academic honesty and integrity. Don't ask me or anyone else to do work for you. Do ask for help. Don't ask for work.

I've got a dissertation to write.

Sunday, June 2, 2013

OBD-II Adapter used with Snapshot from Progressive

I recently decided to look into car insurance rates again to make sure I wasn't overpaying. I do this maybe every 12 to 18 months or so. Progressive Auto Insurance gave a good quote and in it I was given the option to include Snapshot. It's a device to plug into your OBD-II port in your car. It reports back to Progressive via the AT&T cell network what time of day you drive, how you accelerate and how you brake. The device will make an audible beep if you brake to hard. I've previously written about devices you can plug into the ODB-II port of you car to log and monitor data from your car, in my case with the Torque Android app. It's fun and I haven't done too much analyzing log data but I may still.

I decided to wait on changing car insurance companies but I did decide to do a free 30 day trial of Snapshot. It would give me a sense of how it works and of how much more I could save off of Progressive's rate by letting them know how/when I drive. I got two of their devices in the mail for our two cars. My question was if I could have this and my own OBD-II device plugged in at the same time. I purchased this OBD-II splitter from Amazon because with just a 30 day trial I wouldn't have time for the long boat from China. I tried it out and it works! The Snapshot device will beep when the car first starts and again if you brake too hard. I noticed that the delay from car start-up to hearing the Snapshot start-up beep took longer when I had both devices plugged in. But it did beep. I also intentionally braked too hard to make it beep at me, which it did. All the while I was using Torque to read info from the car in real time. Great!

I can't guarantee that Snapshot would always work in this situation. With or without Snapshot, my own OBD-II device was able to read about 17 PIDs/second (PID is a command/response to/from the car). The Torque wiki of bluetooth adapters lists some that are capable of up to 60 PIDs/second. Assuming 60/s is the limit of the car, this suggests to me that Snapshot has plenty of time with my own adapter attached to get the information it needs. And I bet some cars have slower computers than others (i.e. have varying PID limits) so Snapshot doesn't have a problem with a slowdown due to my adapter sharing the bus. Also great!

There's no free lunch, though. That splitter cable is long. In one car it was causing the two adapters to dangle right next to where I would put my leg when braking. This is extremely dangerous! DO NOT DO THIS! Having things in the way of safely driving your car is NOT an option. If for whatever reason this scenario was something you absolutely needed, get the help of a professional to ensure the adapters and splitter are installed safely. The same goes for using your phone while driving. BE SAFE. When I use Torque I start it logging while the car is parked and then put it away while driving. Don't compromise safety.

TL;DR: The two adapters can be used at the same time. Maybe not with better, faster OBD-II adapters, though. And safety is always first.

UPDATE (2/11/2014):
So I made this test in November and December but there it is. We drove to/from Idaho for Thanksgiving and I captured data during the long trips. The csv files from the Torque app look great. But what about Snapshot? Was it capturing data, too? If you go to Progressive's website, you can look at the data. Here's what I saw for those trips:

You can see that I drove around 75 mph for a few hours, with some stops for lunch or gas. So the Snapshot device and my OBD-II adapter were both able to capture data at the same time.