mirror of
https://github.com/jlengrand/LAFF.git
synced 2026-03-10 08:31:21 +00:00
393 lines
9.5 KiB
JavaScript
Executable File
393 lines
9.5 KiB
JavaScript
Executable File
function select_problem(btnId){
|
|
if (problem_type == 0){
|
|
|
|
if (btnId == "p0")
|
|
init_problem(p1.L, p1.U, p1.x);
|
|
if (btnId == "p1")
|
|
init_problem(p2.L, p2.U, p2.x);
|
|
if (btnId == "p2")
|
|
init_problem(p3.L, p3.U, p3.x);
|
|
if (btnId == "p3")
|
|
init_problem(p4.L, p4.U, p4.x);
|
|
if (btnId == "p4")
|
|
init_problem(p5.L, p5.U, p5.x);
|
|
display_problem();
|
|
}
|
|
else{
|
|
alert("Refresh page to start again");
|
|
}
|
|
problem_type = -1;
|
|
}
|
|
|
|
function display_problem(){
|
|
context_switch(document.getElementById('take'+take));
|
|
|
|
//create Take 1 problem
|
|
document.getElementById('Step0-1').innerHTML +=
|
|
create_multiplier_input(DIM, 1, "T1L",
|
|
create_equation(DIM, DIM, 0, "eq", "-0", A, b) );
|
|
|
|
//create Take 2 problem
|
|
document.getElementById('Step0-2').innerHTML +=
|
|
create_multiplier_input(DIM, 1, "T2L",
|
|
create_matrix(DIM, DIM+1, curAb, false, true, "T2A", "-0") );
|
|
|
|
//create Take 3 problem
|
|
document.getElementById('Step0-3').innerHTML +=
|
|
create_multiplier_input(DIM, 1, "T3L",
|
|
create_matrix(DIM, DIM+1, curAb, false, true, "T3A", "-0"), true );
|
|
|
|
//create Take 4 problem
|
|
document.getElementById('Step0-4').innerHTML +=
|
|
create_multiplier_input(DIM, 1, "T4L",
|
|
create_matrix(DIM, DIM, A, false, false, "T4A", "-0"), true);
|
|
|
|
make_gauss(DIM, DIM, L,cur_step, gaussL);
|
|
document.getElementById('Step0b-4').innerHTML +=
|
|
"<table><tr><td>" +
|
|
create_matrix(DIM, DIM,
|
|
gaussL, false, false, "", "") +
|
|
"</td><td>" +
|
|
create_matrix(DIM, 1, b, false, false, "T4b", "-0") +
|
|
"</td></tr></table>" ;
|
|
}
|
|
|
|
|
|
function init_problem(LL, UU, xx){
|
|
zero_array(DIM*DIM,A);
|
|
zero_array(DIM, b);
|
|
zero_array(DIM*DIM, gaussL);
|
|
|
|
for (var i = 0; i != DIM*DIM; ++i){
|
|
L[i] = LL[i];
|
|
U[i] = UU[i];
|
|
}
|
|
for (var i = 0; i != DIM; ++i){
|
|
x[i] = xx[i];
|
|
}
|
|
|
|
multiply_matrix(/*NO_TRANS, NO_TRANS, */
|
|
DIM, DIM, DIM,
|
|
/*1.0,*/ L, DIM, U,DIM,
|
|
/*1.0,*/ A, DIM);
|
|
|
|
multiply_matrix(/*NO_TRANS, NO_TRANS, */
|
|
DIM, 1, DIM,
|
|
/*1.0,*/ A, DIM, x, 1,
|
|
/*1.0,*/ b, 1);
|
|
|
|
|
|
for (var i = 0; i != 4; ++i){
|
|
with(cur_data[i]){
|
|
for (var j = 0; j != DIM*DIM; ++j){
|
|
curA[j] = A[j];
|
|
curAb[j] = A[j];
|
|
}
|
|
for (var j = 0; j != DIM; ++j){
|
|
curb[j] = b[j];
|
|
curAb[j+DIM*DIM] = b[j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function reveal(take){
|
|
document.getElementById("ans"+take).style.display = "block";
|
|
}
|
|
|
|
function create_ending(take){
|
|
out="<div><h3>Now perform back substitution</h3><input type='button' value='Reveal Solution' onClick='reveal("+take+")'/>";
|
|
out += "<div style='display:none' id='ans"+take+"'>";
|
|
for (var i = 0; i != DIM; ++i){
|
|
out += "χ<sub>"+i+"</sub> = "+x[i];
|
|
if (i+1 < DIM)
|
|
out += ", ";
|
|
}
|
|
out += "</div>";
|
|
out += "</div>";
|
|
return out;
|
|
}
|
|
|
|
function disable_take(old_take){
|
|
old_take.style.border = "2px none orange";
|
|
}
|
|
|
|
function enable_take(new_take){
|
|
new_take.style.border = "2px solid orange";
|
|
}
|
|
|
|
function context_switch(this_div){
|
|
disable_take(document.getElementById('take'+take));
|
|
enable_take(this_div);
|
|
|
|
new_take = parseInt(this_div.id.substring(4), 10);
|
|
|
|
//save current state
|
|
if (curA)
|
|
cur_data[take-1].curA = curA;
|
|
if (curb)
|
|
cur_data[take-1].curb = curb;
|
|
if (curAb)
|
|
cur_data[take-1].curAb = curAb;
|
|
cur_data[take-1].step = cur_step;
|
|
|
|
//load current state
|
|
take = new_take;
|
|
curA = cur_data[take-1].curA;
|
|
curb = cur_data[take-1].curb;
|
|
curAb = cur_data[take-1].curAb;
|
|
cur_step = cur_data[take-1].step;
|
|
}
|
|
|
|
|
|
|
|
function make_gauss(r, c, L, cur_step, gaussL){
|
|
for (var i =0; i != r; ++i){
|
|
for (var j =0; j != c; ++j){
|
|
if (i != j)
|
|
gaussL[j*r+i] = -L[j*r+i];
|
|
else
|
|
gaussL[j*r+i] = 1;
|
|
if (j!=cur_step-1 && i!=j){
|
|
gaussL[j*r+i] = 0;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
function appended_matrix(A, b, Ab){
|
|
for (var i = 0; i !=A.length; ++i){
|
|
Ab[i] = A[i];
|
|
}
|
|
for (var i = 0; i !=b.length; ++i){
|
|
Ab[i+A.length] = b[i];
|
|
}
|
|
}
|
|
|
|
function create_multiplier_input(r, step, id, mtx, gauss){
|
|
var out = "<table><tr><td><table><tr><td";
|
|
if (gauss)
|
|
out += " class='left'";
|
|
out += "> </td><td><table>";
|
|
|
|
for (var i = 0;i != r; ++i){
|
|
out += "<tr>";
|
|
for (var j = 0; j != r; ++j){
|
|
if (i < step || j != step-1){
|
|
out += "<td>";
|
|
if (gauss){
|
|
out += (i==j?"1":"0");
|
|
}
|
|
out += "</td>";
|
|
}
|
|
else{
|
|
out += "<td>";
|
|
if (!gauss)
|
|
out += "Row"+(i+1)+" - ";
|
|
out += "<input id='"+id+i+(step-1)+"' ";
|
|
out += "onFocus='reset_correctness(this)'/>";
|
|
if (!gauss)
|
|
out += " × Row "+step;
|
|
out += "</td>";
|
|
}
|
|
}
|
|
out += "</tr>";
|
|
}
|
|
out += "</table></td><td";
|
|
if (gauss)
|
|
out += " class='right'";
|
|
out += "> </td></tr></table></td><td>"+mtx+"</td></tr></table>";
|
|
return out;
|
|
}
|
|
|
|
function create_matrix(r, c, data, inout, appended, pre, post){
|
|
var out = "<table><tr><td class='left'> </td><td><table id='"+pre+post+"'>"
|
|
for (var i = 0; i != r; ++i){
|
|
out += "<tr>";
|
|
for (var j = 0; j != c; ++j){
|
|
out += "<td"+((j==c-1 && appended) ? " class='bar'": "")+">";
|
|
out += data[j*r+i];
|
|
out += "</td>";
|
|
}
|
|
out += "</tr>";
|
|
}
|
|
return out + "</table></td><td class='right'> </td></table>";
|
|
}
|
|
|
|
function compute_new_curA(cur_step){
|
|
// top cur_step rows are from U
|
|
for (var i = 0; i != cur_step; ++i)
|
|
for (var j = 0; j != DIM; ++j)
|
|
curA[j*DIM+i] = U[j*DIM+i];
|
|
// bottom DIM-cur_steps need to be computed
|
|
for (var i = cur_step; i != DIM; ++i){
|
|
var lambda = L[(cur_step-1)*DIM+i];
|
|
for (var j = cur_step-1; j != DIM; ++j)
|
|
curA[j*DIM+i] -= /*A[j*DIM+i] -*/ lambda*U[j*DIM+(cur_step-1)];
|
|
}
|
|
}
|
|
|
|
function next(btn){
|
|
if (correct_answers(cur_step)){
|
|
|
|
//update curA with the answers
|
|
compute_new_curA(cur_step);
|
|
|
|
//update curB
|
|
zero_array(DIM, curb);
|
|
multiply_matrix(/*NO_TRANS, NO_TRANS, */
|
|
DIM, 1, DIM,
|
|
/*1.0,*/ curA, DIM, x, 1,
|
|
/*1.0,*/ curb, 1);
|
|
|
|
//update curAB
|
|
appended_matrix(curA, curb, curAb);
|
|
|
|
if (btn)
|
|
btn.style.display="none";
|
|
|
|
//display next step
|
|
switch (take){
|
|
case 1:
|
|
with ( document.getElementById('Step'+cur_step+'-1') ){
|
|
innerHTML +=
|
|
create_multiplier_input(DIM, cur_step+1, "T1L",
|
|
create_equation(DIM, DIM,
|
|
cur_step, "eq", "-"+cur_step, curA, curb) );
|
|
style.display = 'block';
|
|
}
|
|
break;
|
|
case 2:
|
|
with ( document.getElementById('Step'+cur_step+'-2') ){
|
|
innerHTML +=
|
|
create_multiplier_input(DIM, cur_step+1, "T2L",
|
|
create_matrix(DIM, DIM+1,
|
|
curAb, false, true, "T2A", "-"+cur_step) );
|
|
style.display = 'block';
|
|
}
|
|
break;
|
|
case 3:
|
|
with ( document.getElementById('Step'+cur_step+'-3') ){
|
|
innerHTML +=
|
|
create_multiplier_input(DIM, cur_step+1, "T3L",
|
|
create_matrix(DIM, DIM+1,
|
|
curAb, false, true, "T3A", "-"+cur_step),
|
|
true );
|
|
style.display = 'block';
|
|
}
|
|
break;
|
|
case 4:
|
|
with ( document.getElementById('Step'+cur_step+'-4') ){
|
|
innerHTML +=
|
|
create_multiplier_input(DIM, cur_step+1, "T4L",
|
|
create_matrix(DIM, DIM,
|
|
curA, false, false, "T4A", "-"+cur_step),
|
|
true );
|
|
style.display = 'block';
|
|
}
|
|
|
|
make_gauss(DIM, DIM, L, cur_step+1, gaussL);
|
|
with (document.getElementById('Step'+cur_step+'b-4') ){
|
|
innerHTML +=
|
|
"<table><tr><td>" +
|
|
create_matrix(DIM, DIM,
|
|
gaussL, false, false, "", "") +
|
|
"</td><td>" +
|
|
create_matrix(DIM, 1,
|
|
curb, false, false, "T4b", "-"+cur_step) +
|
|
"</td></tr></table>" ;
|
|
}
|
|
break;
|
|
default:
|
|
document.getElementById('Step'+cur_step+'-eqn').innerHTML +=
|
|
create_equation(DIM, DIM,
|
|
cur_step, "eq", "-"+cur_step, curA, curb);
|
|
break;
|
|
|
|
}
|
|
|
|
if (take==4 && cur_step==DIM-1){
|
|
for (var i = 0; i != DIM; ++i){
|
|
document.getElementById('Step'+i+'b-4').style.display = "block";
|
|
}
|
|
}
|
|
if (cur_step==DIM-1){
|
|
document.getElementById('Step'+cur_step+'-'+take).innerHTML +=
|
|
create_ending(take);
|
|
|
|
}
|
|
|
|
cur_step += 1;
|
|
}
|
|
}
|
|
|
|
function reset_correctness(elmt){
|
|
elmt.className="";
|
|
}
|
|
|
|
function highlight_correctness(elmt, correct){
|
|
if (correct){
|
|
elmt.className="";
|
|
elmt.readOnly="T";
|
|
elmt.disabled="disabled";
|
|
}
|
|
else{
|
|
elmt.className="err";
|
|
elmt.readOnly=false;
|
|
elmt.disabled=false;
|
|
}
|
|
}
|
|
|
|
function correct_answers(step){
|
|
all_correct = true;
|
|
|
|
//check L
|
|
if (step == 0)
|
|
all_correct = true;
|
|
else {
|
|
for (var i = step; i != DIM; ++i){
|
|
var elmt = document.getElementById('T'+take+'L'+i+(step-1));
|
|
|
|
//multipliers for Gauss Transforms are negated values of L
|
|
var multiplier = parseInt(elmt.value,10) * (take>=3?-1:1);
|
|
all_correct &= (multiplier == L[(step-1)*DIM+i]);
|
|
|
|
highlight_correctness(elmt, (multiplier == L[(step-1)*DIM+i]));
|
|
|
|
}
|
|
}
|
|
|
|
return all_correct;
|
|
}
|
|
|
|
|
|
function create_equation(m, n, step, pre, post, mtx, vec){
|
|
var eqn = "<table>";
|
|
for (var i = 0; i != m; ++i){
|
|
eqn += "<tr>";
|
|
for (var j = 0; j != n; ++j){
|
|
eqn += "<td>";
|
|
if (j >= step || i<= j)
|
|
eqn += mtx[j*m+i]+ " χ<sub>"+j+"</sub>";
|
|
eqn += "</td>";
|
|
if (j >= step || i <= j){
|
|
if (j != n-1)
|
|
eqn += "<td>+</td>";
|
|
else
|
|
eqn += "<td>=</td>";
|
|
}
|
|
else{
|
|
eqn += "<td> </td>";
|
|
}
|
|
}
|
|
eqn += "<td>"+vec[i]+"</td>";
|
|
|
|
eqn += "</tr>";
|
|
}
|
|
eqn += "</table>";
|
|
|
|
return eqn;
|
|
}
|
|
|