Logic Programming

Chapter 16 - Interactive Worksheets

16.1 Interactive Worksheets

Interactive worksheets are a simple but powerful way for people to manage data and to solve data-related problems. Examples of interactive worksheets range from simple, single-user spreadsheets (such as the interactive grids of cells in systems like Numbers and Excel) to collaborative, multi-institutional planning and design tools.

The power and popularity of interactive worksheets stems from a combination of features.

  1. Meaningful data display. Data is typically presented is presented on worksheets in forms suited to the type of data involved - as tables, charts, graphs, and so forth.

  2. Modifiability. Data can be directly modified by the user in what-you-see-is-what-you-get fashion. Importantly, data can be changed in whatever order suits the user.

  3. Constraint checking. Data is automatically checked for completeness and consistency with static and dynamic constraints. Users are alerted to problems; and, where possible, they are given guidance in eliminating those problems.

  4. Automatic computation of results. Consequences of acceptable changes are automatically computed, and the presentation is updated to reflect those consequences.

While these features can be used in many information management settings, they have special value in certain types of applications, e.g. configuration tasks (such as product configuration worksheets and academic program sheets), teaching (such as interactive exercises and simulated environments), online games (such as Chess, Checkers, Pentago), and so forth.

The process of implementing interactive worksheets using traditional programming technologies is time-consuming and expensive. The good news is that Logic Programming can dramatically simplify this process. Making it easier for developers to create and maintain worksheets. And in many cases making it possible for non-developers to do the same. Creating and maintaining worksheets can and should be "do it yourself" (DIY). Just as it is possible for users without programming expertise to create and manage traditional spreadsheets, it should be possible for users without traditional programming expertise to create and manage worksheets on their own.

In this Chapter, we see some ways in which Logic Programming techniques can be used in creating interactive worksheets that operate in World Wide Web browsers. Although our discussion focusses on this one class of interactive worksheets, the techniques can easily be applied to building interactive worksheets in other technologies.

16.2 Example

As an example of an interactive worksheet implemented as a web page, take a look at the academic program sheet shown here. This worksheet provides a means for a student to design a program of study that achieves his academic goals and at the same time meets the academic requirements of his university.

The worksheet includes a listing of courses available to the student. At the bottom on the left, there is a pie chart indicating the proportion of his selected courses in various subareas of Computer Science. In the middle, there is an indication of the number of units of credit the student is requesting for each selected course. And, on the right, there is a listing of professors responsible for those courses.

The student can change his program by selecting courses in whatever order he likes. Clicking an empty checkbox adds the corresponding course to his program of study. Clicking a checkbox that is already checked removes the corresponding course from his program. Once a course is selected, the student can change the number of units of credit for each course by using the slider associated with that course.

An important part of the update process is constraint checking. As each change is made, the worksheet checks that all academic requirements are satisfied. If there is a violation, the corresponding requirement turns red, indicating that there is something wrong. Once the requirement is satisfied once again, the requirement turns black.

As the program is modified, as changes are made, the worksheet is updated accordingly. For example, as each box is checked, it is added to the course list, and a photo of the associated professor appears. Moving the slider for a course changes the requested credit; and, as such changes are made, the pie chart automatically adjusts to show the portion of time the student is devoting to various subareas of the department.

This is a simple example, but it illustrates the key features of interactive worksheets - visibility of all relevant data, the ability to modify that data, automatic checking of constraints, and automatic calculation and display of consequences.

16.3 Page Data

The data underlying a web page appearing in a browser typically takes the form of a hierarchical data structure called a DOM (short for Document Object Model). The top node in this data structure represents the document, and its child nodes represent its components. Nodes in the DOM typically have attributes of various sorts (e.g. the width and height of a table); and, in some cases, those attributes are objects with attributes of their own (e.g. the style attribute of a node has attributes of its own (e.g. font family, font size, and so forth).

In order to use Dynamic Logic Programming to specify the appearance and behavior of a webpage, we need vocabulary to represent the state of a DOM in the form of factoids that express this state.

First of all, we assign identifiers for the nodes of the DOM that we care about. In order to give them meaning, we assign each of our identifiers as the value of the id attribute of the corresponding node. For example, if we wanted to use the identifier mynode to refer to the input element in the HTML fragment shown below, we would list that identifier as the id attribute of that input widget, as shown in this example.

<center> <input id='mynode' type='text' value='hello' size='30' style='color:black'/> </center>

Next, we invent predicates to describe the various properties of these nodes. See below for the most commonly used predicates. For example, we use the binary predicate value to associate an input node (selector or type-in field or textarea) with its value.

value(widget,value): This factoid is true whenever the value associated with widget is value. The widget here may be a text field, selector, radio button field, slider, and so forth.

holds(widget,value): This factoid is true whenever one of the values associated with the multi-valued node widget. The widget in this case multi-valued selector or a checkbox field.

attribute(widget,property,value): This factoid is true whenever the property attribute of widget is value.

style(widget,property,value): This factoid is true whenever the property style of widget is value.

innerhtml(widget,content): This factoid is true whenever the innerHTML of widget is content. Note that content is typically a string of characters.
Given this vocabulary, we can encode relevant information in the form of a dataset. For example, the relevant state of the DOM fragment shown above can be represented by the dataset shown below.


16.4 Gestures

User interaction with a webpage takes the form of gestures (e.g. keystrokes and mouse-clicks). In order to talk about these gestures, we need appropriate vocabulary. For example, we use the constant click to represent the operation of clicking on a button. We use the constant select to represent the operation of selecting a specific option from a selector.

select(widget,value): This action occurs when the user enters or selects value as the value of widget. The widget here may be an object or text field, a selector, a multi-valued menu, a checkbox field, a radio button field, a slider, and so forth.

deselect(widget,value): This action occurs when the user erases or deselects value as the value of widget.

click(widget): This action occurs when the user clicks on widget.

tick: This action occurs periodically. By default, it happens once per second. It is also occurs the user clicks the Run button or the Step button in a simulation control box.

load: This occurs when a page is first loaded.

unload: This action occurs when a user leaves a page.
We use this vocabulary to represent user gestures. For example, if the user clicks a button with identifier a, we represent this as the action click(a). If the user selects 3 from a selector with identifier b, we represent this as select(b,3).

16.5 Operation Definitions

Given a vocabulary for encoding data and gestures, we can describe the behavior of a worksheet by writing suitable operation definitions. The following examples illustrate how this can be done.

Consider the following buttons with identifiers orange, blue, purple, and black.

Suppose that we wanted the worksheet to change the color of this document (identified as page) whenever the user clicks one of these buttons. This behavior can be described with the following operation rules.

click(orange) :: style(page,color,orange)
click(blue) :: style(page,color,blue)
click(purple) :: style(page,color,purple)
click(black) :: style(page,color,black)

Alternatively, we can write these rules more compactly by using a variable, as shown below.

click(X) :: style(page,color,X)

This rule reads as follows. If a user clicks on button with X as id, then, in the next state of the worksheet, the color style of the node identified as page should be X.

Although these operation rules work fine, they are not quite complete. This is because, after clicking the above buttons, the state of our worksheet may include more than one fact of the form style(page,color,X). To completely specify the desired behavior, we need to remove the existing style factoids for page when a button is clicked. This can be done with the following operation rule.

click(X) :: style(page,color,Y) & distinct(X,Y) ==> ~style(page,color,Y)

This rule reads as follows. If a user clicks on button X, and the color of page is Y, and Y is different from X, then in the next state of the worksheet, the color of page should not be Y.

Now consider another example. Here we replace the four buttons with a selector with identifier pagecolor and four options orange, blue, purple, and black.

Let's suppose that we would like change the text color of this document based on the value selected. We can describe this behavior with the following rules.

select(pagecolor,X) :: style(page,color,X)
select(pagecolor,X) :: style(page,color,Y) ==> ~style(page,color,Y)

The first rule states that, if a user selects value X for pagecolor, then style(page,color,X) should be true in the next state, i.e. the text color of the page should be X. The second rule say that, if a user selects value X for pagecolor and the style of page is Y and Y is different from X, then style(page,color,X) should not be true in the next state.

Unfortunately, this is not quite enough. Our transition changes the color of the page, but there is nothing changing the value of the pagecolor attribute. As a result, it will reset to black after the gesture is processed. The following transition rules update the selector.

select(pagecolor,X) :: value(pagecolor,X)
select(pagecolor,X) :: value(pagecolor,Y) ==> ~value(pagecolor,Y)

As a final example, let's look at an example of interactions between input widgets. The operation rules for the four buttons in the first example change the color of the page correctly. However, they do not update the color indicated in the selector.

The transition rule shown below prescribes the desired behavior. When the user clicks a button with identifier X, then we want the value of the value of the selector to be updated and we want any previous value to be removed.

click(X) :: value(pagecolor,X)
click(X) :: value(pagecolor,Y) ==> ~value(pagecolor,Y)

Combining these rules with the rules shown above allows the user to click either the buttons or make selections and get the same effects in both cases.

16.6 View Definitions

In the preceding section, we saw that a single gesture can have multiple effects. For example, changing the value of a selector named pagecolor sets the value of the selector and changes the color of the page. To implement this behavior, we need to manage both conditions in our transition rules, and we need to store both conditions in our dataset. Moreover, if we are not careful, our definitions might get out of sync with each other, and we would not get the behavior we want.

The good news is that it is sometimes possible to write view definitions that describe such behavior more economically and in a way that is less prone to mistakes. By defining some of our predicates as views of other predicates, we do not need to store as much information and we can get by with fewer transition rules.

In the case from the preceding section, suppose that we were to define the color of the page node in terms of the value of the pagecolor node. The definition is shown below.

style(page,color,X) :- value(pagecolor,X)

With this definition in place, we could replace the operation rules shown in the last section with the four shown below.

click(X) :: value(pagecolor,X)
click(X) :: value(pagecolor,Y) ==> ~value(pagecolor,Y)
select(pagecolor,X) :: value(pagecolor,X)
select(pagecolor,X) :: value(pagecolor,Y) ==> ~value(pagecolor,Y)

There are fewer rules here, and they mention fewer predicates. In particular, there is no mention of the style of the page. That property is fully determined by the value of pagecolor, and so we do not need to store or update this information in our rules. Instead, the worksheet computes the style using the view definition given above.

16.7 Semantic Modeling

So far, we have talked about purely reactive worksheets - in which behavior is defined directly in terms of visible features and user gestures. In this section, we look at semantic modeling - where behavior is defined in terms of relationships among objects in the application area of the worksheet (e.g. people, places, movies, and so forth). We look at how we can use operation rules to update this semantic data, and we look at how we can use view definitions to define syntactic attributes in terms of semantic information.

Consider a course scheduling worksheet that is laid out as follows. In this layout, the multi-valued selectors have identifiers course1, course2, course3, and course4, and they have options autumn, winter, spring, and summer.

Course 1 Course 2 Course 3 Course 4

If a user of this worksheet selects the options autumn and spring in course1, then the factoids holds(course1,autumn) and holds(course1,spring) are added to our dataset. Semantically, this means that the user has selected course1 for both the autumn and spring quarters.

Now, consider the alternative layout of this course scheduling worksheet shown below, where the selectors have identifiers autumn, winter, spring, and summer and where they have options course1, course2, course3, and course4 (denoting the courses that may be taken in a quarter).

Autumn Winter Spring Summer

In this alternative layout, the user's course selections correspond to the facts holds(autumn,course1) and holds(spring,course1). Note that these facts are different from the ones stored in the previous worksheet i.e. holds(course1,autumn) and holds(course1,spring). However, at a conceptual level, nothing has changed! In both cases, the user has selected course1 for both the autumn and spring quarters.

The difference between the states of these two conceptually identical worksheets is due to the difference in their layout. One way to design a semantic model of a worksheet is to separate out what is stored in a worksheet's state from what is rendered, e.g. style, value, holds facts.

The first step is to write out operation rules for the gestures on the worksheet's widgets and have the effects correspond to semantically meaningful relations.

For example, in the first course scheduling worksheet, we would use the operation rules shown below.

select(Course,Quarter) :: taken(Course,Quarter)
deselect(Course,Quarter) :: ~taken(Course,Quarter)

In the second course scheduling worksheet, which is conceptually identical to the first one, we would write the following rules.

select(Quarter,Course) :: taken(Course,Quarter)
deselect(Quarter,Course) :: ~taken(Course, Quarter)

The second step in creating a semantic worksheet is to define the layout of the worksheet as a view over these semantically meaningful relations.

For example, in the first course scheduling worksheet, we would define holds as a view of taken

holds(Course,Quarter) :- taken(Course,Quarter)

In the second course scheduling worksheet, we would define holds as shown below.

holds(Quarter,Course) :- taken(Course,Quarter)

Now, suppose a user selects course1 in autumn and spring quarters. The facts stored in both worksheets would be identical.


The upshot is that the rules on each sheet, in effect, constitute a stylesheet for displaying and updating that data. An important benefit of this is that the application data implicit in a worksheet can be exchanged with other worksheets that manage the data in different ways.