Sunday, December 19, 2021

Using Spinoza with Python Objects (For in-class exercises)

During the COVID-19 pandemic, I started using Spinoza ( in Intro Programming.  Spinoza lets students try out solving problems in Python.  They get immediate feedback and there's lots of additional pedagogical features.

It uses Brython to run the code.  When it loads each page, parameters for functions are passed as strings.  If you try to create the objects in the Test Generator box, they won't pass correctly when Spinoza executes the tests.  Instead, you have to generate them using additional code that you put in the Solution box.  For example, if you're asking students to write a get_height() method or function for a Monkey class, you have to set things up this way:

  • Use a different name in the Method Name field.  I always just append "_wrapper" to the end.  (E.g. get_height_wrapper.)

  • For the number of parameters, use the total number of primitives you'll need to create any objects for the subject and all parameters.

  • Still put the original function/method header in the scaffolding box.  E.g. def get_height():  If they're writing a method, put it inside the class.  If there are other methods they'll need (__init__ or __str__) then you can include those here too.

class Monkey(object):

    '''Models a monkey.  Attributes: age, height, num_bananas.'''

    def get_height(self):


  • In the solution box, there are a bunch of additional things to do:

    • Add a function that creates an instance of the object:

def create_monkey(age, height, num_bananas):

    monkey = Monkey()

    monkey.age = age

    monkey.height = height

    monkey.num_bananas = bananas

    return monkey 

(This will change a lot if they've already created an __init__ and you include that in the scaffolding.)
    • If you didn't create the class above, create it here.  Also include any other classes you might need that you didn't put in the scaffolding.

    • Add the definition of the wrapper.  It should create the objects, then call the function/method that the student is writing.

def get_height_wrapper(age, height, num_bananas):

    monkey = create_monkey(age, height, num_bananas)

    return monkey.get_height()

    • Add your correct version of the requested function.  (E.g. my_get_height().)  If they're writing a method, you'll have to write this as a function instead.

def my_get_height(monkey):

    return monkey.height

    • Add the solution function, which does the same thing as the wrapper, except that it calls your function instead of the student's.

def solution(age, height, num_bananas):

    monkey = create_monkey(age, height, num_bananas)

    return my_get_height(monkey)

It took me a long time to get this working back in 2020, so I hope this is helpful for other people that want to use Spinoza!

Wednesday, August 25, 2021

A CGT Book for Undergrad Math Beginners

Craig Tennenhouse and I have finished the first version of our CGT book.  Here is the book's homepage.  We designed it to be used by undergraduates who may or may not be math majors.  That meant that we needed to include many discrete math concepts as well, to the point where Craig is currently using the text in his Discrete Math class as well.

I wanted this project to be a sabbatical project as early as eight years ago, in the spring of 2013, before I knew when my first sabbatical would be.  At that time I was teaching my third CGT course at Wittenberg University.  All three had been different: the first was as a Math/CS elective, the second was as a first-year college seminar course, and this third time was as an honors course for students with any major.  It was during this third time that I realized I wanted my own thorough notes with lots of exercises in them.  

I actually had some experience with text book exercises.  Nearly a decade prior, I worked with Otto Bretscher on the solution manual for his Linear Algebra text.  I wanted to have a similar large quantity of exercises so students could practice applying the concepts in a structured way.

I met Craig in the fall of 2013, and we have collaborated here and there since.  I had switched schools, which meant my future first sabbatical was far waylaid.  I got my feet under me at a new university, then, just a few years ago, I mentioned that I wanted to write my own book at a CGT event.  I explained that I wanted something at a bit lower level that would be more appropriate for general undergrads.  Craig asked whether we could write it together, which I was definitely on board with.  We both wanted a freely-downloadable book and I was excited to try and adapt my student/instructor dual mode LaTeX code so we could hide some of the exercise solutions.  (At this point, I don't think Craig realized just how many exercises I wanted to write.)

In the summer of 2019, we met and came up with a good outline.  Craig and I were on board with each others' ideas, such as doing impartial games before partisan, so things went very smoothly.  I used that outline in my sabbatical proposal for the spring semester of 2021.  That got accepted, then COVID-19 hit and Craig and I had to collaborate via video calls instead of in person.  (Our universities are about a 2 hour drive apart.)  We started writing in January, and we just finished enough for our first release. 

The result is a text book appropriate for either Discrete Math or Games.  For students who already know the introductory discrete topics, it's easy to skip those sections (laid out as Math Diversions).  There are over 400 exercises in the text, and about half of those have solutions in the back.  There are also some "Computational Corner" pieces with programming examples in Python.  

We aren't done.  We expect to make a bunch of updates as we improve things (and find errors).  The book will continue to get updated on the webpage.  The chaos of the pandemic caused a bunch of delays, so there are definitely many topics we didn't flesh out as much as we wanted.  Nevertheless, we are both very excited and look forward to hearing feedback from teachers, students, self-learners, and even people who just take a quick glance at the PDF.  We have a space in the book to thank contributors who point out errors we need to fix.  All kinds of feedback are very valuable!

I want to give an extra ``Thank You!'' to Craig, without whom this project would never have been completed.  I am so excited that we managed to get this done!

Please feel free to use the comments section here as one avenue to leave us feedback.

Wednesday, October 23, 2019

Berlekamp Memorial Workshop Talks, Day 2

On the second (and final) day of the MSRI workshop, we had more talks, which I've attempted to summarize.  As always, please feel free to comment to correct what I got wrong and add things I didn't include!

Carlos Santos: "A Universal Ruleset"

Carlos reprised a talk about a subject Elwyn really enjoyed: finding a universal ruleset.  I didn't know this before, but this was a topic that Elwyn even inspired when he asked the question: What is the habitat of *2?  This means, which rulesets contain *2?  Even more general: which rulesets contain positions that equal all elements of the Short Conway Group?  Any such ruleset can be called "Universal".

Carlos mentioned multiple different procedural strategies he used to try to find such a ruleset.  Although, he could have come up with a new one, as he reasoned, "If I invent something, I am cheating."  So instead he attempted to use Amazons, Traffic Lights, Konane, then found victory with Generalized Konane, constructing everything in the SCG from that.  He was very happy that Generalized Konane already existed in CGSuite, so he could use it without "cheating".

Afterwards, Carlos spoke briefly about the supposed separation between recreational mathematics and "serious" mathematics, finishing with, "The opposite of fun is not serious."

Svenja Huntemann: "Bounding the Boiling Point"

(Joint work with Carlos Santos and Richard Nowkowski.)

Svenja talked about temperature and "How much urgency is necessary to play at a specific position.  This is the first talk where I really got an education about Thermography and thermographs.  Svenja's work uses thermic versions of hot games--which are games with the same temperature but with only one option for each player. 

This thermic version makes it easier to find bounds on the temperature.  The boiling point, then is the suprenum of temperatures of a class of games.  If we can find bounds on the confusion intervals of games in the class, we can use that to find the boiling point!

Svenja discussed the boiling point of Domineering and Elwyn's conjecture that it is 2.  There is a bunch of work on this, including an example position with temperature 2.  A new result here is that long "snakes" cannot have temperature above 3.

Neil McKay: "Yellow-Brown Hackenbush"

Neil presented work on a topic Elywn had published in GONC3.  Yellow-Brown Hackenbush is different than Blue-Red Hackenbush because players cannot play on components where all the edges are yellow or all the edges are brown.  (The three colors of edges: YeLlow edges are takeable by Left, BRown are takeable by Right, and OlivE are takeable by Everyone.)  I felt very lucky that I could distinguish been the three colors in the slides.  Neil stuck to those three colors to preserve the choices, but admitted that it was hard to see the difference on the actual slides.

Unlike B-R Hackenbush, every Y-B Hackenbush position is dicotic.  Thus, all positions are infinitesimals.

Additionally, if playing a restricted version on stalks (path graphs), there are some cool simplifications you can do.  Neil has done work and solved the outcomes for the game, but not yet for the actual canonical form values.  This is something that Elwyn had left as an open problem.  Neil concluded by listing a bunch of open problems remaining with both Yellow-Brown and Blue-Red Hackenbush.

Richard Nowakowski: "Pic Arête"

Richard spoke about Pic Arête, which is Dots & Boxes without the extra move for completing a box.  Though it's actually played like Strings-and-Coins.  The game was solved on the grid by Meyniel and Roudnoff in 1988.  Richard considered playing on a general graph.  It turns out that a French team (Blanc, Duchêne, and Gravier) solved this in 2006, except for some cases.  Apparently these solutions don't always find the optimal move, but find a move good enough to win anyways.

Richard extended this to say that each edge contains a game instead of a single move to cut it so that the edge doesn't disappear until the game there becomes { | }, or exactly zero.  Then the overall game uses the same scoring mechanism as Strings & Coins.  E.g. edge weight games of +1 and -1 give you a Blue-Red version of Pic Arête.  Richard showed some neat examples with simplications.

"I claim I solved it last night in a dream," Richard said of one of the problems he's looking at.

Mike Fisher: "Beatty Games: Big and Small"

(Joint work with Mike Fraboni, Svenja, Urban, RJN, and Carlos)

Mike talked about Beatty Sequences and Games, and actually found the values for positions using different values of alpha.  He then dove into the atomic weights. As Mike kept saying, a lot of this was just personal exercises he gave to himself to see what was going on.  He found a relationship to the atomic weights and the number of consecutive numbers in the Beatty sequences below the number.

Mike then turned his attention to Octal Games, using the octal codes to describe Beatty games.  These infinite octal codes cause interesting patterns of Grundy values that Mike plotted.  Beyond all this, Mike then took Beatty sequences in another direction, investigating a partizan variant of the Beatty game.  He discovered that Richard, Angela, Urban and other had already explained the Golden-Ratio version, so he looked at values and Reduced Canonical Forms of games based on other "Metallic Ratios", e.g. Silver, and Bronze.  (I didn't know these existed!)

David Wolfe: "Distinguishing Gamblers from Investors at the Blackjack Table"

David finished up the talks with some work back from 2002/2003.  He first started by explaining basic Blackjack strategies, then talked about how card counting can enter into the mix.  Counting perfectly can shift the advantage a player has from -.5% to +.5%  David wanted to try to gauge the skill of a player by watching them play.  He catered to us a bit by asking: "How can we assess the skill of people playing combinatorial games?"  He added that the whole thing could be extended to evaluate anyone working in a competitive "gaming" field.

Since the variance is very high, you need to watch a player for a long time in order to try to evaluate this.  Also, instead of awarding points for the money a player actually earns, you instead credit them for the expected value of each play.  This is then compared to the baseline strategy for the game that doesn't include card counting.  This was a really cool approach!

These talks have been an excellent tribute to Elwyn.  I was exposed to so much more about what he accomplished than I had known existed.  I'm really fortunate that I was able to attend this meeting.  I'm very appreciative to MSRI and all of the organizers, especially Aaron Siegel.

Tuesday, October 22, 2019

Berlekamp Memorial Workshop Talks, Day 1

Aaron Siegel: "Elwyn Berlekamp and Combinatorial Game Theory"

Aaron gave an amazing history of Elwyn's 56 years of publishing about games.  As he later mentioned, probably none of us at the workshop would have been in the field if it weren't for him.  This was such a great talk.  Here are some of the things I learned:
  • At 10 years old, Elwyn was allowed to play Dots-and-Boxes with his friends in the back of the room during Math class, as he was bored by the lectures.  Thank goodness for understanding teachers!  In 2002, nearly 50 years later, he published a book on Dots-and-Boxes.  In it there are four theorems.  As Aaron summarized, if you only know theorem n and your opponent knows n+1, it's hopeless.
  • As an undergrad at MIT, Elwyn wrote one of the first chess-playing programs and published columns about Bridge in the newspaper.  He would later publish about bridge-playing programs.
  • He learned about Nim at Bell Labs, where he spent three summers also during college.
  • He lost to a Dots-and-Boxes-playing program created by other students, so he learned more about it, then came back and won.
  • He worked at Bell Labs again later and wrote a paper connecting Dots and Boxes to Sprague-Grundy theory.  His supervisors challenged him, asking why this was useful.  He wrote a six-page response, which earned him vindication from the VP.
  • Winning Ways took a long time to complete.  It began when Elwyn met Richard Guy in North Carolina in 1967.  Elwyn proposed writing the book, and Guy suggested they team up with John Conway.  The three of them met in 1969 at a conference at Oxford.  They spent the next 13 years working on Winning Ways, which was published in 1982.  I really had known nothing of the history of the creation of Winning Ways before this talk!
  • Elwyn got into Go in 1988 while working with David Wolfe.  Elwyn created the 9-dan stumping problem, on which he could defeat some of the best Go players as either Black or White.  As David explained, this position was about halfway between a natural endgame and the completely contrived boards that they had worked out a theory for using infinitesimals.
  • In 1996, Elwyn started using Coupon Stacks as a way to get a professional opinion on the temperature of a game.
  • In 2018, Elwyn published his final paper, this time about Entrepreneurial Chess, which we played at the game.
Elwyn's amazing career spanned multiple fields, but, as Aaron mentioned, "I think games were always what he loved best."

Svenja Huntemann: "Introduction to CGT"

Svenja gave an introduction to CGT to fill an unexpectedly empty slot.  Svenja covered impartial games, outcome classes, and basic partisan notions explained via Domineering: fractions, switches, and infinitesimals.  Her off-the-cuff version of this introduction is better than my planned and practiced version.

Melissa Huggan: "The Cheating Robot"

Melissa talked about work with Richard Nowakowski that continues her great PhD work on simultaneous games.  In the simultaneous positions, what if Right knows what Left is going to do before they both make their move?  (The name is derived from a Rock-Paper-Scissors robot that can cheat and win by very quickly reacting to what the human player does.)

In this cool model, it turns out that Zero is unique!  It can only occur when both players can only move to zero (causing a draw).  There can be other drawing scenarios, but they don't act like Zero when included in sums!  Melissa took a closer look at Topping Dominoes and used this to show some interesting examples and how to play optimally in these scenarios.

Urban Larsson: "The Fragility of Golden Games"

Urban talked about some joint work with Yakov Babichenko on non-combinatorial games where payoffs (0 or 1) are on the leaves of a binary tree.  Players alternate choosing between the two subtrees at each level, so the value of the game is easily decided recursively.  If the payoffs are assigned at random, how often does the overall value change?  If the Pr[leaf payoff is 1] is the golden ratio, then we call this a Golden Game.

Fragility is then based on the Hamming Distance to change the outcome of the game.  It turns out that Golden Games are very fragile, while non-Golden games are more robust.  As Urban pointed out, "Golden Games are special with high probability."  They want to look at some applications to machine learning with an interfering adversary.  E.g. how many pixels need to be changed until a machine can no longer recognize that a photo is of either a dog or a wolf?  How fragile are these algorithms?

I'm definitely looking forward to the Day 2 talks!

Monday, July 1, 2019

Ten Years Professing

Ten years ago today I moved from Massachusetts to Ohio to teach at Wittenberg University.  I was recently hooded, affianced, and ready for my shiny new job.  I realized quickly that I always needed more time to prepare my teaching materials.  A gentle disillusionment that explained why my professors were always so harried.  Somehow keeping up hadn't been too difficult in grad school when I taught three courses over three semesters (instead of 3-4 courses each semester) and had other grad students to handle my grading. 

In the past ten years, the race-against-the-clock to implement new course materials continues.  Luckily, the payoff in appreciation from students is tremendous.  That positive attention from teaching is a fuel that first lent me it's energy in 2001 as an undergrad.  I realized how much I wanted to teach then, a feeling reaffirmed when I taught in grad school at BU from 2007 to 2009.

Being a good teacher does not require your own creation of course materials, however.  I hope my work is actually reusable.  If just one other person gets a jump start because they don't have to create all their own content, that would be worth all the extra effort to make it accessible.

I can't make everything publicly available, because then students can just copy answers and solutions.  Still, I've got student versions of my lecture notes, a LaTeX package for writing lecture notes, publicly-available course pages (with assignments), an automated Python (3) grader, and a Python-to-Java tutorial

Ten years has changed a lot.  I'm divorced, a parent, tenured, and have switched schools twice.  As of today, I'm our department chair at Plymouth State.  (This last bit is definitely not going to help me prepare my course materials.)  I've seen a bunch of different students, but I'm still dedicated to their learning.

I got my copy of Games of No Chance 5, which has my Neighboring Nim paper.  (I'm finally published in a GONC!)  Neighboring Nim was something I proved hard back in July 2009, right after that big move to Ohio at the very start of my career.

Summer Software Engineering Reflections

My summer course just ended last week.  I taught Software Engineering, a senior-level course--which is against-the-norm for the summer.  The class was kept intentionally small because I was ramping up a new project and using the very new style of grading I've been going with since last fall.  (I was working on my own project solution concurrently with the students.)

Without revealing too much to my students this fall, here's the DAG for Project 0:

The basic idea behind this is that students can't get points for completing something until they complete the stuff coming before it.  They get the points by showing off their code to me in meetings.  This both lets them redo stuff if it isn't really finished and breaks up the grading so I don't have to find a block of time to get them all done at once.

I also like this because there are extra parts that are not necessary for moving on that students can do to exercise their creative sides.  I can also let students propose new goals to add to the project DAG, then make that available to everyone in the course.

The summer course went really well!  The projects were all really great, and they were each very different even though we were all working in close proximity.  I just barely finished my own version on the last day of class.  (Pedagogically, this is upsetting; realistically, it's rarely feasible for me to complete all my assignments before the students see them on the first run.  Ten years in and I still can't stay far enough ahead.)  These students did amazing work, despite me lagging behind!

Perhaps most important: this is the first time I got all of the students to really implement OO design patterns.  This crop best knows what's going on here.

It took nine tries to get this course right, but I really hope that this means everything will go smoothly starting this fall with the 10th iteration.  (We'll be doing Photo Albums then too, but hopefully they won't get too much of a jump start from this post.)

My current plan is to have the students program some Combinatorial Games again in the Fall of 2020.

I have really good plans for the lecture notes for this course, but that's a ways down the line.

Saturday, April 6, 2019

Sprouts 2019 Talks

Sprouts 2019 was yesterday and we had some excellent talks.  Here are my little summaries of them!

Nick Paolini: "Machine Learning in Combinatorial Games"

Nick gave an intro to Machine Learning as a subcategory of AI, including explaining historic data, models, objective functions, and some optimization.  He described Erik Jarlberg's recent work on Nim  (This explored a question I've been really curious about for years!)  Erik's work found that learning players can figure out how to make correct moves in Nim even when trained on a random player.  Nick also talked about developments with AlphaZero, an AI player for Go, Chess, and Shogi.  Nick then talked about his interest in trying to calculate NimSums via machine learning.

Nathan Mozinski: "Displaying Col Moves Online"

Nate showed the current progress on his senior project: displaying the moves in an active Col game being played between two Java players.  That initial code is code I created for my Data Structures class.  He's modified it to write the state of the game to a text file after each move.  He then added a JavaScript-powered webpage to display that game:  Right now it displays the current board, the previous board, and the win-loss records of the two players in the on-going match.

Craig Tennenhouse: "Towards an Impartial Short Tafl Variant"

Craig talked about Hnefetafl and some impartial variants he's been exploring.  In his rulesets, there is a King and one or more soldiers (who may or may not be attempting a coup).  To make it short, the King can only move North and West and the game ends when it cannot move.  The different rulesets are each based on a different rule for the movement of the soldiers.  Surprisingly, even with only one soldier and a ruleset such as "The soldier must move closer to the king", P-positions appear in very unexpected places!  For the rule "The soldier can only move south or east and can't go past the king", Craig seems to have solved for all the P-positions.