Skip to content

Commit c8828ca

Browse files
committed
link text updates for #1454
1 parent e1eff59 commit c8828ca

15 files changed

Lines changed: 1632 additions & 1631 deletions

File tree

api/README.md

Lines changed: 344 additions & 344 deletions
Large diffs are not rendered by default.

doc/dev/Optimising_STACK_for_large_Maxima_variables.md

Lines changed: 781 additions & 781 deletions
Large diffs are not rendered by default.

doc/dev/PHP-CAS.md

Lines changed: 137 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,137 @@
1-
# PHP interface with the CAS
2-
3-
This document describes the design of the PHP interface to the CAS. This interface was developed specifically to connect STACK to Maxima.
4-
5-
# High level objects
6-
7-
## CAS text
8-
9-
CAS text is literally "computer algebra active text". This is documented [here](../Authoring/CASText.md). Note, that when constructing CAS text it must be able to take a CAS session as an argument to the constructor. In this way we can use lists of variables, such as [question variables](../Authoring/Variables.md) to provide values.
10-
11-
E.g. we might have :
12-
13-
n:rand(5)+2;
14-
15-
in the question variables field. The question is instantiated, and then later we need to create some CAS text, e.g. feedback, in which we have :
16-
17-
You were asked to find the integral of \((x+2)^{@n@}\) with respect to \(x\). In fact ....
18-
19-
Here, we need the CAS text to be able to construct the text, with the previously evaluated value of `n`. This need is also why the CAS session returns the *value* of the variables as well as a displayed form. It is used here.
20-
21-
## CAS session
22-
23-
This class actually calls the CAS itself. The basic ideas is to take a list of maxima commands, including assignments of the form.
24-
25-
key:rawvalue
26-
27-
and executes this list in a single Maxima session. The results of this are then captured and fed back into the CAS strings so we essentially have data in the form:
28-
29-
key =>
30-
value
31-
display
32-
error
33-
34-
An important point here is that expressions (values) can refer to previous keys. This is one reason why we can't tie teachers down to a list of allowed functions. They will be defining variable and function names. We have implemented a lazy approach where the connection to the CAS is only made, and automatically made, when we ask for the values, display form or error terms for a variable. And we don't generate display and value unless they are needed later. E.g. intermediate values do not create LaTeX.
35-
36-
37-
## Answer tests
38-
39-
The answer tests essentially compare two expressions. These may accept an option, e.g. the number of significant figures.
40-
Details of the current answer tests are available [elsewhere](../Authoring/Answer_Tests/index.md). The result of an answer test should be
41-
42-
1. Boolean outcome, true or false,
43-
2. errors,
44-
3. feedback,
45-
4. note.
46-
47-
# Other concepts
48-
49-
## Validity
50-
51-
There are a number of reasons why a CAS expression needs to be "valid". These are
52-
53-
1. security,
54-
2. stability,
55-
3. error trapping,
56-
4. pedagogic reasons, specific to a particular question.
57-
58-
## Single call PRTs and simplification
59-
60-
As of STACK 4.4 we make a single Maxima call to exectue an entire PRT.
61-
This reduces significantly the number of separate calls to maxima, which
62-
is a significant efficienty boost for more complex questions.
63-
64-
Some answer tests rely on "unsimplified" expressions with a "what you see
65-
is what you get" approach.
66-
67-
This example illustrates the issue. The teacher computes the answer to their
68-
question, e.g. find \(\int_{0}^{1} {\frac{{\left(1-x\right)}^4\cdot x^4}{x^2+1}} \mathrm{d}x\),
69-
with the Maxima code
70-
71-
p1:int(x^4*(1-x)^4/(1+x^2),x,0,1);
72-
73-
using simplification (obviously) at the start of the quetion variables, and this simplified expression is used
74-
by the PRT. The answer, \(\frac{22}{7}-\pi\), is held internally in "simplified" form.
75-
The Maxima string output is `22/7-%pi` but internally the answer is actually the following
76-
77-
((MPLUS SIMP) ((RAT SIMP) 22 7) ((MTIMES SIMP) -1 $%PI))
78-
79-
You can see the internal tree structure of a Maxima expression with the following code.
80-
81-
(simp:true, p1:22/7-%pi, ?print(p1));
82-
83-
Rather than `22/7-%pi` the internal structure is really closer to this: `rat(22,7)+ (-1*%pi)`.
84-
85-
On the other hand, a student types in the expression `22/7-%pi` and we deal with this without simplification.
86-
The internal Maxima expression is now
87-
88-
(simp:false, p1:22/7-%pi, ?print(p1));
89-
90-
which gives a different internal structure
91-
92-
((MPLUS) ((MQUOTIENT) 22 7) ((MMINUS) $%PI))
93-
94-
which might best be thought of as `22/7+-(%pi)` where `-` is now a function of a single argument.
95-
96-
In this example, the unsimplified `MQUOTIENT` and simplified `RAT SIMP` are not particularly problematic. However, the difference between `-%pi` and `-1*%pi` is seriouly problematic. Indeed, this kind of distinction is exactly what some
97-
answer tests, e.g. `EqualComAss` and `CasEqual`, are designed to establish. These tests will not work with a mix of simplified and unsimplified expressions, even if to the user they look completely identical!
98-
99-
The solution to this problem is to "rinse" away any maxima internal simplification by using the Maxima `string` function to return the expression to the top level which a user would expect to type. This process corresponds to what happend in older versions of Maxima in which expressions were routinely passed between Maxima and PHP, with the string representation being used.
100-
101-
Some expressions (lists, matrices) are passed by reference in Maxima, so even if the teacher's answer is created without simplification in the first instance, when it is evaluated by the answer tests there is a risk of it becoming simplified when it is later compared by an answer test function.
102-
103-
## Wrinkles: `ordlerless` and `ordergreat`
104-
105-
The Maxima functions `ordlerless` and `ordergreat` can only be executed once. In a Maxima desktop session try
106-
107-
orderless(a,b);
108-
orderless(x,y);
109-
110-
This will result in a Maxima error "orderless: reordering is not allowed.".
111-
112-
These functions only take effect outside the current block. Try executing the following two calls in a clean Maxima desktop session.
113-
114-
````
115-
block(
116-
ordergreat(a,b),
117-
expand((a+b)^2)
118-
);
119-
120-
expand((a+b)^2);
121-
````
122-
123-
Notice that the requested ordering (`a` before `b`) is implemented once the first block is completed, only in the second command. You might expect _both_ commands to respect the requested ordering.
124-
125-
This is a problem in STACK. STACK creates a block to manage execution of commands, including evaluation of the question variables, construction of castext and execution of PRTs. Any call to these functions will therefore be inside a block containing all the other commands.
126-
127-
STACK makes an exception for `ordlerless` and `ordergreat`. However, the work-around means STACK only supports single and simple uses. You must give an explicit call to these functions. You cannot create a list of variables, and then apply `ordlerless` and `ordergreat`. By design expressions like
128-
129-
apply(ordergreat, random_permuation([a,b,c]));
130-
131-
will not work in STACK (but similar constructs will work in the desktop).
132-
133-
See these issue
134-
135-
* https://github.com/maths/moodle-qtype_stack/issues/1384
136-
* https://github.com/maths/moodle-qtype_stack/issues/1241
137-
* https://github.com/maths/moodle-qtype_stack/issues/1207
1+
# PHP interface with the CAS
2+
3+
This document describes the design of the PHP interface to the CAS. This interface was developed specifically to connect STACK to Maxima.
4+
5+
# High level objects
6+
7+
## CAS text
8+
9+
CAS text is literally "computer algebra active text". This is documented in [/Authoring/CASText](../Authoring/CASText.md). Note, that when constructing CAS text it must be able to take a CAS session as an argument to the constructor. In this way we can use lists of variables, such as [question variables](../Authoring/Variables.md) to provide values.
10+
11+
E.g. we might have :
12+
13+
n:rand(5)+2;
14+
15+
in the question variables field. The question is instantiated, and then later we need to create some CAS text, e.g. feedback, in which we have :
16+
17+
You were asked to find the integral of \((x+2)^{@n@}\) with respect to \(x\). In fact ....
18+
19+
Here, we need the CAS text to be able to construct the text, with the previously evaluated value of `n`. This need is also why the CAS session returns the *value* of the variables as well as a displayed form. It is used here.
20+
21+
## CAS session
22+
23+
This class actually calls the CAS itself. The basic ideas is to take a list of maxima commands, including assignments of the form.
24+
25+
key:rawvalue
26+
27+
and executes this list in a single Maxima session. The results of this are then captured and fed back into the CAS strings so we essentially have data in the form:
28+
29+
key =>
30+
value
31+
display
32+
error
33+
34+
An important point here is that expressions (values) can refer to previous keys. This is one reason why we can't tie teachers down to a list of allowed functions. They will be defining variable and function names. We have implemented a lazy approach where the connection to the CAS is only made, and automatically made, when we ask for the values, display form or error terms for a variable. And we don't generate display and value unless they are needed later. E.g. intermediate values do not create LaTeX.
35+
36+
37+
## Answer tests
38+
39+
The answer tests essentially compare two expressions. These may accept an option, e.g. the number of significant figures.
40+
Details of the current answer tests are available [elsewhere](../Authoring/Answer_Tests/index.md). The result of an answer test should be
41+
42+
1. Boolean outcome, true or false,
43+
2. errors,
44+
3. feedback,
45+
4. note.
46+
47+
# Other concepts
48+
49+
## Validity
50+
51+
There are a number of reasons why a CAS expression needs to be "valid". These are
52+
53+
1. security,
54+
2. stability,
55+
3. error trapping,
56+
4. pedagogic reasons, specific to a particular question.
57+
58+
## Single call PRTs and simplification
59+
60+
As of STACK 4.4 we make a single Maxima call to exectue an entire PRT.
61+
This reduces significantly the number of separate calls to maxima, which
62+
is a significant efficienty boost for more complex questions.
63+
64+
Some answer tests rely on "unsimplified" expressions with a "what you see
65+
is what you get" approach.
66+
67+
This example illustrates the issue. The teacher computes the answer to their
68+
question, e.g. find \(\int_{0}^{1} {\frac{{\left(1-x\right)}^4\cdot x^4}{x^2+1}} \mathrm{d}x\),
69+
with the Maxima code
70+
71+
p1:int(x^4*(1-x)^4/(1+x^2),x,0,1);
72+
73+
using simplification (obviously) at the start of the quetion variables, and this simplified expression is used
74+
by the PRT. The answer, \(\frac{22}{7}-\pi\), is held internally in "simplified" form.
75+
The Maxima string output is `22/7-%pi` but internally the answer is actually the following
76+
77+
((MPLUS SIMP) ((RAT SIMP) 22 7) ((MTIMES SIMP) -1 $%PI))
78+
79+
You can see the internal tree structure of a Maxima expression with the following code.
80+
81+
(simp:true, p1:22/7-%pi, ?print(p1));
82+
83+
Rather than `22/7-%pi` the internal structure is really closer to this: `rat(22,7)+ (-1*%pi)`.
84+
85+
On the other hand, a student types in the expression `22/7-%pi` and we deal with this without simplification.
86+
The internal Maxima expression is now
87+
88+
(simp:false, p1:22/7-%pi, ?print(p1));
89+
90+
which gives a different internal structure
91+
92+
((MPLUS) ((MQUOTIENT) 22 7) ((MMINUS) $%PI))
93+
94+
which might best be thought of as `22/7+-(%pi)` where `-` is now a function of a single argument.
95+
96+
In this example, the unsimplified `MQUOTIENT` and simplified `RAT SIMP` are not particularly problematic. However, the difference between `-%pi` and `-1*%pi` is seriouly problematic. Indeed, this kind of distinction is exactly what some
97+
answer tests, e.g. `EqualComAss` and `CasEqual`, are designed to establish. These tests will not work with a mix of simplified and unsimplified expressions, even if to the user they look completely identical!
98+
99+
The solution to this problem is to "rinse" away any maxima internal simplification by using the Maxima `string` function to return the expression to the top level which a user would expect to type. This process corresponds to what happend in older versions of Maxima in which expressions were routinely passed between Maxima and PHP, with the string representation being used.
100+
101+
Some expressions (lists, matrices) are passed by reference in Maxima, so even if the teacher's answer is created without simplification in the first instance, when it is evaluated by the answer tests there is a risk of it becoming simplified when it is later compared by an answer test function.
102+
103+
## Wrinkles: `ordlerless` and `ordergreat`
104+
105+
The Maxima functions `ordlerless` and `ordergreat` can only be executed once. In a Maxima desktop session try
106+
107+
orderless(a,b);
108+
orderless(x,y);
109+
110+
This will result in a Maxima error "orderless: reordering is not allowed.".
111+
112+
These functions only take effect outside the current block. Try executing the following two calls in a clean Maxima desktop session.
113+
114+
````
115+
block(
116+
ordergreat(a,b),
117+
expand((a+b)^2)
118+
);
119+
120+
expand((a+b)^2);
121+
````
122+
123+
Notice that the requested ordering (`a` before `b`) is implemented once the first block is completed, only in the second command. You might expect _both_ commands to respect the requested ordering.
124+
125+
This is a problem in STACK. STACK creates a block to manage execution of commands, including evaluation of the question variables, construction of castext and execution of PRTs. Any call to these functions will therefore be inside a block containing all the other commands.
126+
127+
STACK makes an exception for `ordlerless` and `ordergreat`. However, the work-around means STACK only supports single and simple uses. You must give an explicit call to these functions. You cannot create a list of variables, and then apply `ordlerless` and `ordergreat`. By design expressions like
128+
129+
apply(ordergreat, random_permuation([a,b,c]));
130+
131+
will not work in STACK (but similar constructs will work in the desktop).
132+
133+
See these issue
134+
135+
* https://github.com/maths/moodle-qtype_stack/issues/1384
136+
* https://github.com/maths/moodle-qtype_stack/issues/1241
137+
* https://github.com/maths/moodle-qtype_stack/issues/1207

0 commit comments

Comments
 (0)