Implementing the SuperMemo method with SM8OPT.DLL
Piotr Wozniak, Dec. 17, 1996

SM8OPT.DLL is a library designed for software developers intending to implement the SuperMemo method in their software. Licensing conditions for using SM8OPT.DLL will differ depending on the target application (contact SuperMemo World for more details). In particular, no license fee is required for projects whose sole purpose is research on repetition spacing or on the Algorithm-SM8 used by SM8OPT.DLL. Nevertheless, written permission from SuperMemo World must be obtained beforehand in all cases.

SM8OPT.DLL can be called from any application as any standard Windows DLL library. The job of the developer is to:

* store data pertaining to the learning process (a record less than 20KB in size, later called OptimizationRecord)

* store data pertaining to the individual items of knowledge (a record of about 20 bytes per item, later called ItemOptimizationData)

* execute repetitions on days determined by the date stored at ItemOptimizationData.NextRepetition

* call SM8OPT.DLL at the moment of repetition to obtain new values of OptimizationRecord and ItemOptimizationData

Here is the detailed algorithm for using SM8OPT.DLL:

1. Call GetOptimizationRecordSize to obtain the size of OptimizationRecord.

2. Allocate a memory block of the size determined in Step 1. This block will be used to keep OptimizationRecord throughout the learning session.

3. In the first session, call CreateNewOptimizationRecord(OptRec) where OptRec is a pointer to the memory block allocated in Step 2. This will initialize the value OptimizationRecord. In all following sessions load OptimizationRecord from a file created in Step 12.

4. After creating or loading OptimizationRecord in Step 3, call InitializeOptimizationRecord(OptRec) that will create all temporary variables used by the repetition spacing algorithm.

5. By analogy, for each item call GetItemOptimizationDataSize, allocate memory for ItemOptimizationData, and call CreateNewItemOptimizationData(IOD) where IOD is a pointer to the allocated memory block. Alternatively reload ItemOptimizationData from a file.

6. Having OptimizationRecord and ItemOptimizationData available in memory (pointers OptRec and IOD), repeat the procedure of executing individual repetitions presented in Steps 7 through 12.

7. Using ItemOptimizationData.NextRepetition field (IOD^.NextRepetition) determine the date of the next repetition for each individual item (see later for more on interpretation of NextRepetition value).

8. On the date of repetition call GetRepetitionData(IOD) with IOD pointing to ItemOptimizationData. This will set the new value of ItemOptimizationData with the field NextRepetition pointing to the day on which the next repetition will take place (see later for more on interpretation of NextRepetition value).

9. Before calling GetRepetitionData, set two fields of ItemOptimizationData: Grade - the grade provided in the course of the repetition, and Today - current date relative to the first day of the learning process (see later for more).

10. GetRepetitionData can be called several times in succession (e.g. for grade-undo purposes).

11. Call CommitOptimizationRecord (no parameters) after the final call to GetRepetitionData and after the confirming the validity of the repetition (e.g. by choosing by the user the Next Repetition button). CommitOptimizationRecord updates all temporary variables of the repetition spacing algorithm and updates OptimizationRecord (pointer to this record was provided in Step 4 with InitializeOptimizationRecord and does not have to be specified again).

12. Save ItemOptimizationData to a file (the new value of all fields was determined in Step 8 by calling GetRepetitionData).

13. Upon completing the series of repetitions, save the OptimizationRecord to a file. Call FreeOptimizationRecord and deallocate the memory blocks allocated in Step 2 and Step 5.

Here is the definition of ItemOptimizationData record:

TItemOptimizationData=record

Today:word; {relative to the first day of the learning process. On the first day, Today=1}

Grade:byte; {grade from 0 to 5, where 5 is the best grade}

FirstGrade:byte; {first grade ever obtained by the item during its first repetition}

LastRepetition,NextRepetition:integer; {relative to the first day of the process}.

OldInterval,UsedInterval,OptimumInterval,NewInterval:integer;

Repetitions,NewRepetitions:byte;

Lapses,NewLapses:byte;

RequestedFI:byte;

Ordinal:real;

AFactor,NewAFactor:real;

UFactor,NewUFactor:real;

OldRF,NewRF,OldOF,NewOF:real;

Cases:word;

EstimatedFI,ExpectedFI:real;

NormalizedGrade,NGMin,NGMax:real;

RepetitionsCategory:real;

end;

The only fields that are indeed needed by the developer are: Today, Grade and NextRepetition. Other fields can be used for diagnostic or information purposes.

Today and NextRepetition are counted relative to the first day of the process. It is on the first day of learning, Today=1, and the repetition takes place on the date on which NextRepetition=Today.

Note that LastRepetition and NextRepetition values may be negative in cases where items have been transferred from another system that was created before the initialization of the system in use.

As some of the fields of ItemOptimizationData are computed anew, only a subset of TItemOptimizationData has to be stored in a file. Developers that would want to save disk space may note that only the following fields have to be stored: FirstGrade, LastRepetition, OldInterval, Repetitions, Lapses, RequestedFI, Ordinal, AFactor, and UFactor.

Most notably, NextRepetition does not have to be stored as it can be derived from NextRepetition=LastRepetition+OldInterval.

After a repetition, new values of those fields have to read from: NewInterval, NewRepetitions, NewLapses, NewAFactor and NewUFactor. The new value of LastRepetition equals Today.

The definition of TOptimizationRecord is not presented here as it is quite meaningless without understanding the details of the repetition spacing algorithm denoted Algorithm-SM8.

The use of GetOptimizationRecordSize and GetItemOptimizationDataSize is obligatory as in future releases of SM8OPT.DLL, the size of the optimization data may change. Obviously, there will be no change to the present structure apart from adding new fields taking part in enhanced optimization. For example, the RepetitionCategory has been introduced in December 1996 in a new release of Algorithm SM8 in which interval categories instead of repetition numbers are used to index the matrix of optimal factors. This prevents fooling the algorithm in cases the actual repetition takes place long after the scheduled optimum date.

In addition, SM8OPT.DLL exports the following function that may be of use for developers interested in implementing repetition rescheduling mechanisms:

function ComputeMercyOrdinal(IOD:PItemOptimizationData;ScheduleLength:word):longint;

This function produces and ordinal number from ItemOptimizationData and the proposed length of the rescheduling period. Such ordinals can be used in sorting items for rescheduling. The ordinals range from 0 to 10000 and items with low ordinals should be scheduled first.

SM8OPT.DLL is also available as a Delphi DCU unit file for incorporation in Delphi executables.

Here is the list of all procedures published in SM8OPT.DLL:

procedure CreateNewOptimizationRecord(OptimizationRecord:POptimizationRecord)

function GetOptimizationRecordSize:word

procedure InitializeOptimizationRecord(OptimizationRecord:POptimizationRecord)

procedure FreeOptimizationRecord

function GetItemOptimizationDataSize:word

procedure CreateNewItemOptimizationData(IOD:PItemOptimizationData)

procedure GetRepetitionData(IOD:PItemOptimizationData)

procedure CommitOptimizationRecord

function ComputeMercyOrdinal(IOD:PItemOptimizationData; ScheduleLength:word; var MercyFactors:TMercyFactors):longint

SM8OPT.DLL is available for download from http://www.SuperMemo.com.