Over the holidays I reconnected with an old friend and occasional
chess partner who, upon hearing I was getting soundly thrashed by run
of the mill engines, recommended checking out the ChessTempo site.  It
has online tools for training your chess tactics.  As you attempt to
solve chess problems your rating is computed depending on how well you
do.  The chess problems, too, are rated and adjusted as visitors
attempt them.  This should be familar to any chess or table-tennis
player.  Rather than the Elo rating system, the Glicko rating system is

You have a choice of the relative difficulty of the problems.
After attempting a number of easy puzzles and seeing my rating slowly
climb, I wondered what was the most effective technique to raise my
rating (the classical blunder).  Attempting higher rated problems would lower my
solving rate, but this would be compensated by a smaller loss and
larger gain.  Assuming my actual playing strength is greater than my
current rating (a misconception common to us patzers), there should be a
rating that maximizes the rating gain per problem.

The following Maple module computes the expected rating change
using the Glicko system.

Glicko := module()

export DeltaRating
    ,  ExpectedDelta
    ,  Pwin

    # Return the change in rating for a loss and a win
    # for player 1 against player2
    DeltaRating := proc(r1,rd1,r2,rd2)
    local E, K, g, g2, idd, q;

        q := ln(10)/400;
        g := rd -> 1/sqrt(1 + 3*q^2*rd^2/Pi^2);
        g2 := g(rd2);
        E := 1/(1+10^(-g2*(r1-r2)/400));
        idd := q^2*(g2^2*E*(1-E));

        K := q/(1/rd1^2+idd)*g2;

        (K*(0-E), K*(1-E));

    end proc:

    # Compute the probability of a win
    # for a player with strength s1
    # vs a player with strength s2.

    Pwin := proc(s1, s2)
    local p;
        p := 10^((s1-s2)/400);
    end proc:

    # Compute the expected rating change for
    # player with strength s1, rating r1 vs a player with true rating r2.
    # The optional rating deviations are rd1 and rd2.

    ExpectedDelta := proc(s1,r1,r2,rd1 := 35, rd2 := 35)
    local P, l, w;
        P := Pwin(s1,r2);
        (l,w) := DeltaRating(r1,rd1,r2,rd2);
        P*w + (1-P)*l;
    end proc:

end module:

Assume a player has a rating of 1500 but an actual playing strength of 1700.  Compute the expected rating change for a given puzzle rating, then plot it.  As expected the graph has a peak.


Ept := Glicko:-ExpectedDelta(1700,1500,r2):
plot(Ept,r2 = 1000...2000);

Compute the optimum problem rating



                     {r2 = 1599.350691}

As your rating improves, you'll want to adjust the rating of the problems (the site doesn't allow that fine tuning). Here we plot the optimum puzzle rating (r2) for a given player rating (r1), assuming the player's strength remains at 1700.

Ept := Glicko:-ExpectedDelta(1700, r1, r2):
dEpt := diff(Ept,r2):
r2vsr1 := r -> fsolve(eval(dEpt,r1=r)):
plot(r2vsr1, 1000..1680);

Here is a Maple worksheet with the code and computations.



After pondering this, I realized there is a more useful way to present the results. The shape of the optimal curve is independent of the user's actual strength. Showing that is trivial, just substitute a symbolic value for the player's strength, offset the ratings from it, and verify that the result does not depend on the strength.

Ept := Glicko:-ExpectedDelta(S, S+r1, S+r2):
has(Ept, S);

Here's the general curve, shifted so the player's strength is 0, r1 and r2 are relative to that.

r2_r1 := r -> rhs(Optimization:-Maximize(eval(Ept,r1=r), r2=-500..0)[2][]):
p1 := plot(r2_r1, -500..0, 'numpoints'=30);

Compute and plot the expected points gained when playing the optimal partner and your rating is r-points higher than your strength.

EptMax := r -> eval(Ept, [r1=r, r2=r2_r1(r)]):
plot(EptMax, -200..200, 'numpoints'=30, 'labels' = ["r","Ept"]);

When your playing strength matches your rating, the optimal opponent has a relative rating of


The expected points you win is


Please Wait...