1function challengeResults({ 2 results: { 3 nb_s, 4 nb_p, 5 solvers, 6 fd_solvers, 7 free_solvers, 8 par_solvers, 9 open_solvers, 10 local_solvers, 11 problems, 12 kind, 13 instances, 14 benchmarks, 15 results, 16 times, 17 objectives, 18 first_objectives, 19 step_count, 20 step_obj, 21 step_times, 22 scores, 23 scores_loc 24 }, 25 locations: { 26 problems: loc_problems, 27 instances: loc_instances 28 } 29}) { 30 const max_time_in_ms = 1200000; 31 const pbox = {}; 32 const sbox = {}; 33 34 // Complete Scoring 35 let total = 0; 36 const total_solver = []; // Total overall score of a solver 37 const total_problem = []; 38 const total_instance = []; 39 const total_solver_instance = []; // Total score of a solver per instance 40 const total_solver_problem = []; // Total score of a solver per problem 41 42 // Incomplete Scoring 43 const hasIncompleteScoring = scores_loc !== undefined; 44 let total_inc = 0; 45 const total_solver_inc = []; // Total overall score of a solver 46 const total_problem_inc = []; 47 const total_instance_inc = []; 48 const total_solver_instance_inc = []; // Total score of a solver per instance 49 const total_solver_problem_inc = []; // Total score of a solver per problem 50 51 // Area Scoring 52 const hasAreaScoring = step_count !== undefined; 53 let total_area = 0; 54 const total_solver_area = []; // Total overall score of a solver 55 const total_problem_area = []; 56 const total_instance_area = []; 57 const total_solver_instance_area = []; // Total score of a solver per instance 58 const total_solver_problem_area = []; // Total score of a solver per problem 59 60 const rank_solver = []; 61 const rank_problem_solver = []; 62 const map_problem_solver_rank = []; 63 64 function init() { 65 const p1 = document.getElementById("solver_selection"); 66 while (p1.firstChild) { 67 p1.removeChild(p1.lastChild) 68 } 69 const f1 = document.createElement('form'); 70 f1.name = "solver_checked"; 71 for (let i = 0; i < nb_s; i++) { 72 sbox[i] = document.createElement("input"); 73 sbox[i].id = `solver-checkbox-${i}` 74 sbox[i].type = 'checkbox'; 75 sbox[i].name = solvers[i]; 76 sbox[i].defaultChecked = false; 77 sbox[i].value = i; 78 f1.appendChild(sbox[i]); 79 const label = document.createElement('label'); 80 label.htmlFor = `solver-checkbox-${i}`; 81 label.style.paddingLeft = '0.25rem'; 82 label.appendChild(document.createTextNode(solvers[i])); 83 f1.appendChild(label); 84 f1.appendChild(document.createElement('br')); 85 } 86 if (p1 != null) 87 p1.appendChild(f1); 88 const p2 = document.getElementById("problem_selection"); 89 while (p2.firstChild) { 90 p2.removeChild(p2.lastChild) 91 } 92 const f2 = document.createElement('form'); 93 f2.name = "problem_checked"; 94 for (let i = 0; i < nb_p; i++) { 95 pbox[i] = document.createElement("input"); 96 pbox[i].id = `problem-checkbox-${i}` 97 pbox[i].type = 'checkbox'; 98 pbox[i].name = problems[i]; 99 pbox[i].defaultChecked = false; 100 pbox[i].value = i; 101 f2.appendChild(pbox[i]); 102 const label = document.createElement('label'); 103 label.htmlFor = `problem-checkbox-${i}`; 104 label.style.paddingLeft = '0.25rem'; 105 label.appendChild(document.createTextNode(problems[i])); 106 f2.appendChild(label) 107 f2.appendChild(document.createElement('br')); 108 } 109 if (p2 != null) 110 p2.appendChild(f2); 111 for (let i = 0; i < nb_s; i++) { 112 total_solver_problem[i] = []; 113 total_solver_instance[i] = []; 114 total_solver_problem_inc[i] = []; 115 total_solver_instance_inc[i] = []; 116 total_solver_problem_area[i] = []; 117 total_solver_instance_area[i] = []; 118 } 119 120 const classControls = [ 121 [fd_solvers, document.getElementById("control-fd")], 122 [free_solvers, document.getElementById("control-free")], 123 [par_solvers, document.getElementById("control-par")], 124 [open_solvers, document.getElementById("control-open")], 125 [local_solvers, document.getElementById("control-local")] 126 ]; 127 let prevSolvers = null; 128 for (const [s, e] of classControls) { 129 if (s.every(x => !x) || prevSolvers && prevSolvers.every((x, i) => (s[i] === x))) { 130 e.style.display = 'none'; 131 } 132 prevSolvers = s; 133 } 134 if (!hasIncompleteScoring) { 135 for (const el of document.getElementsByClassName('score-incomplete')) { 136 el.style.display = 'none'; 137 } 138 } 139 if (!hasAreaScoring) { 140 for (const el of document.getElementsByClassName('score-area')) { 141 el.style.display = 'none'; 142 } 143 } 144 } 145 146 function selectCategory(category) { 147 for (let i = 0; i < nb_s; i++) { 148 if (category[i] && !sbox[i].disabled) { 149 sbox[i].checked = true; 150 } 151 } 152 } 153 154 function selectFD() { 155 selectCategory(fd_solvers); 156 } 157 158 function selectFree() { 159 selectCategory(free_solvers); 160 } 161 162 function selectPar() { 163 selectCategory(par_solvers); 164 } 165 166 function selectOpen() { 167 selectCategory(open_solvers); 168 } 169 170 function selectLocal() { 171 selectCategory(local_solvers); 172 } 173 174 function selectAll() { 175 for (let i = 0; i < nb_p; i++) { 176 pbox[i].checked = true; 177 } 178 } 179 180 function clearAll() { 181 for (let i = 0; i < nb_p; i++) 182 pbox[i].checked = false;
183 for (let i = 0; i < nb_s; i++) 184 sbox[i].checked = false; 185 } 186 187 function computeSelected() { 188 document.getElementById('results-section').style.display = 'block'; 189 const prob = []; 190 const solv = []; 191 for (let i = 0; i < nb_p; i++) { 192 prob[i] = pbox[i].checked; 193 } 194 for (let i = 0; i < nb_s; i++) { 195 solv[i] = sbox[i].checked; 196 } 197 computeScores(solv, prob); 198 if (hasIncompleteScoring) { 199 computeScoresInc(solv, prob); 200 } 201 if (hasAreaScoring) { 202 computeScoresArea(solv, prob); 203 } 204 rankSolvers(solv, prob); 205 modifyTables(solv, prob); 206 } 207 208 function computeScores(selected_s, selected_p) { 209 total = 0.0; 210 for (let s = 0; s < nb_s; s++) { 211 if (!selected_s[s]) 212 continue; 213 let ts = 0.0; 214 for (let p = 0; p < nb_p; p++) { 215 if (!selected_p[p]) 216 continue; 217 let tsp = 0.0; 218 for (let k = 0; k < instances[p].length; k++) { 219 const i = instances[p][k]; 220 let tsi = 0.0; 221 for (let s2 = 0; s2 < nb_s; s2++) { 222 if (selected_s[s2]) 223 tsi += scores[s][s2][i] 224 } 225 total_solver_instance[s][i] = tsi; 226 tsp += tsi; 227 } 228 total_solver_problem[s][p] = tsp; 229 ts += tsp; 230 } 231 total_solver[s] = ts; 232 total += ts; 233 }; 234 for (let p = 0; p < nb_p; p++) { 235 if (selected_p[p]) { 236 let tp = 0.0; 237 for (let k = 0; k < instances[p].length; k++) { 238 const i = instances[p][k]; 239 let ti = 0.0; 240 for (let s = 0; s < nb_s; s++) { 241 if (selected_s[s]) 242 ti += total_solver_instance[s][i]; 243 } 244 total_instance[i] = ti; 245 tp += ti; 246 } 247 total_problem[p] = tp; 248 } 249 } 250 } 251 252 function computeScoresInc(selected_s, selected_p) { 253 total_inc = 0.0; 254 for (let s = 0; s < nb_s; s++) { 255 if (!selected_s[s]) 256 continue; 257 let ts = 0.0; 258 for (let p = 0; p < nb_p; p++) { 259 if (!selected_p[p]) 260 continue; 261 let tsp = 0.0; 262 for (let k = 0; k < instances[p].length; k++) { 263 const i = instances[p][k]; 264 let tsi = 0.0; 265 for (let s2 = 0; s2 < nb_s; s2++) { 266 if (selected_s[s2]) 267 tsi += scores_loc[s][s2][i] 268 } 269 total_solver_instance_inc[s][i] = tsi; 270 tsp += tsi; 271 } 272 total_solver_problem_inc[s][p] = tsp; 273 ts += tsp; 274 } 275 total_solver_inc[s] = ts; 276 total_inc += ts; 277 }; 278 for (let p = 0; p < nb_p; p++) { 279 if (selected_p[p]) { 280 let tp = 0.0; 281 for (let k = 0; k < instances[p].length; k++) { 282 const i = instances[p][k]; 283 let ti = 0.0; 284 for (let s = 0; s < nb_s; s++) { 285 if (selected_s[s]) 286 ti += total_solver_instance_inc[s][i]; 287 } 288 total_instance_inc[i] = ti; 289 tp += ti; 290 } 291 total_problem_inc[p] = tp; 292 } 293 } 294 } 295 296 // Area scoring 297 // 298 function computeScoresArea(selected_s, selected_p) { 299 total_area = 0.0; 300 let normalise = false; 301 if (document.getElementById("area_scoring").checked) { 302 normalise = true; 303 } 304 // Iterating over the problems 305 for (let p = 0; p < nb_p; p++) { 306 // Check if the problem is selected 307 if (!selected_p[p]) 308 continue; 309 // Problem is selected 310 311 // Iterating over the instances 312 for (let ii = 0;
312 ii < instances[p].length; ii++) { 313 const i = instances[p][ii]; 314 315 // Computing the scores for the instance for each solver 316 if (kind[p] == "SAT") { 317 computeScoresArea_for_instance_sat(selected_s, p, i, normalise); 318 } else if (kind[p] == "MIN") { 319 computeScoresArea_for_instance_min(selected_s, p, i, normalise); 320 } else if (kind[p] == "MAX") { 321 computeScoresArea_for_instance_max(selected_s, p, i, normalise); 322 } 323 324 // Aggregate results for the instance 325 let ti = 0; 326 for (let s = 0; s < nb_s; s++) { 327 if (selected_s[s]) { 328 ti += total_solver_instance_area[s][i]; 329 } 330 } 331 total_instance_area[i] = ti; 332 } 333 334 // Aggregate results for the problem 335 let tp = 0; 336 for (let ii = 0; ii < instances[p].length; ii++) { 337 const i = instances[p][ii]; 338 tp += total_instance_area[i]; 339 } 340 total_problem_area[p] = tp; 341 } 342 343 // Aggregate remaining results for the solvers 344 for (let s = 0; s < nb_s; s++) { 345 if (selected_s[s]) { 346 let ts = 0; 347 for (let p = 0; p < nb_p; p++) { 348 if (selected_p[p]) { 349 let tsp = 0; 350 for (let ii = 0; ii < instances[p].length; ii++) { 351 const i = instances[p][ii]; 352 tsp += total_solver_instance_area[s][i]; 353 } 354 total_solver_problem_area[s][p] = tsp; 355 ts += tsp; 356 } 357 } 358 total_solver_area[s] = ts; 359 total_area += ts; 360 } 361 } 362 } 363 364 // Computation of the area score for an instance that is unsatisfiable or 365 // belongs to sat problem 366 // 367 function computeScoresArea_for_instance_sat(selected_s, p, i, normalise) { 368 for (let s = 0; s < nb_s; s++) { 369 let area = 0; 370 // Check if the solver is selected 371 if (selected_s[s]) { 372 // Solver is selected 373 374 // Compute the area below the two step function 375 area = 1 * times[s][i] + 0 * (max_time_in_ms - times[s][i]); 376 if (normalise) { 377 area = area / max_time_in_ms; 378 } 379 // Saving the value 380 total_solver_instance_area[s][i] = area; 381 } 382 } 383 } 384 385 // Computation of the area score for an instance that belongs to a minimisation problem 386 // 387 function computeScoresArea_for_instance_min(selected_s, p, i, normalise) { 388 let min_obj = 0; 389 let max_obj = 0; 390 let sol = false; 391 const scale_unsol = 0.25; 392 const scale_proof = 0.25; 393 const scale_sol = 1 - scale_unsol - scale_proof; 394 // Computing the minimal and maximal objective value 395 for (let s = 0; s < nb_s; s++) { 396 // Check if the solver is selected 397 if (selected_s[s]) { 398 // Solver is selected 399 if (step_count[s][i] > 0) { 400 if (sol) { 401 min_obj = Math.min(min_obj, objectives[s][i]); 402 max_obj = Math.max(max_obj, first_objectives[s][i]); 403 } else { 404 min_obj = objectives[s][i]; 405 max_obj = first_objectives[s][i]; 406 sol = true; 407 } 408 } 409 } 410 } 411 // Computng the area score 412 if (sol) { 413 // At least one solver found a feasible solution 414 for (let s = 0; s < nb_s; s++) { 415 let area = 0; 416 // Check if the solver is selected 417 if (selected_s[s]) { 418 // Solver is selected 419 if (step_count[s][i] > 0) { 420 // Solver has found at least one solution 421 422 // First (solution) step 423 area += scale_unsol * step_times[s][i][0]; 424 // Intermediate steps 425 let prev_time = 0; 426 let prev_obj = max_obj; 427 const scale_obj = max_obj - min_obj; 428 if (scale_obj > 0) { 429 for (let k = 0; k < step_count[s][i]; k++) { 430 area += scale_sol * (((prev_obj - min_obj) / scale_obj) * (step_times[s][i][k] - prev_time)); 431 prev_time = step_times[s][i][k]; 432 prev_obj = step_obj[s][i][k]; 433 } 434 area += scale_sol * (((prev_obj - min_obj) / scale_obj) * (times[s][i] - prev_time)); 435 } else { 436 area += scale_sol * step_times[s][i][0]; 437 } 438 // Last (optimal proof) step 439 area += scale_proof * times[s][i]; 440 } else { 441 // Solver has not found any solution 442 area = 1 * max_time_in_ms; 443 } 444 // Normalise area scoring 445 if (normalise) { 446 area = area / max_time_in_ms; 447 } 448 // Storing area scoring 449 total_solver_instance_area[s][i] = area; 450 } 451 } 452 } else { 453 // Use the scoring for sat (unsat) instances 454 computeScoresArea_for_instance_sat(selected_s, p, i, normalise); 455 } 456 } 457 458 // Computation of the area score for an instance that belongs to a maximisation problem 459 // 460 function computeScoresArea_for_instance_max(selected_s, p, i, normalise) { 461 let min_obj = 0; 462 let max_obj = 0; 463 let sol = false;
464 const scale_unsol = 0.25; 465 const scale_proof = 0.25; 466 const scale_sol = 1 - scale_unsol - scale_proof; 467 // Computing the minimal and maximal objective value 468 for (let s = 0; s < nb_s; s++) { 469 // Check if the solver is selected 470 if (selected_s[s]) { 471 // Solver is selected 472 if (step_count[s][i] > 0) { 473 if (sol) { 474 min_obj = Math.min(min_obj, first_objectives[s][i]); 475 max_obj = Math.max(max_obj, objectives[s][i]); 476 } else { 477 min_obj = first_objectives[s][i]; 478 max_obj = objectives[s][i]; 479 sol = true; 480 } 481 } 482 } 483 } 484 // Computng the area score 485 if (sol) { 486 // At least one solver found a feasible solution 487 for (let s = 0; s < nb_s; s++) { 488 let area = 0; 489 // Check if the solver is selected 490 if (selected_s[s]) { 491 // Solver is selected 492 if (step_count[s][i] > 0) { 493 // Solver has found at least one solution 494 495 // First (solution) step 496 area += scale_unsol * step_times[s][i][0]; 497 // Intermediate steps 498 let prev_time = 0; 499 let prev_obj = min_obj; 500 const scale_obj = max_obj - min_obj; 501 if (scale_obj > 0) { 502 for (let k = 0; k < step_count[s][i]; k++) { 503 area += scale_sol * (((max_obj - prev_obj) / scale_obj) * (step_times[s][i][k] - prev_time)); 504 prev_time = step_times[s][i][k]; 505 prev_obj = step_obj[s][i][k]; 506 } 507 area += scale_sol * (((max_obj - prev_obj) / scale_obj) * (times[s][i] - prev_time)); 508 } else { 509 area += scale_sol * step_times[s][i][0]; 510 } 511 // Last (optimal proof) step 512 area += scale_proof * times[s][i]; 513 } else { 514 // Solver has not found any solution 515 area = 1 * max_time_in_ms; 516 } 517 // Normalise area scoring 518 if (normalise) { 519 area = area / max_time_in_ms; 520 } 521 total_solver_instance_area[s][i] = area; 522 } 523 } 524 } else { 525 // Use the scoring for sat (unsat) instances 526 computeScoresArea_for_instance_sat(selected_s, p, i, normalise); 527 } 528 } 529 530 // Ranking of the solvers corresponding their score 531 // 532 function rankSolvers(selected_s, selected_p) { 533 for (let p = 0; p < nb_p; p++) { 534 rank_problem_solver[p] = []; 535 map_problem_solver_rank[p] = []; 536 } 537 // Initialise arrays 538 for (let s = 0; s < nb_s; s++) { 539 if (selected_s[s]) { 540 rank_solver[s] = { 541 id: s, 542 score: total_solver[s] 543 }; 544 for (let p = 0; p < nb_p; p++) { 545 if (selected_p[p]) 546 rank_problem_solver[p][s] = { 547 id: s, 548 score: total_solver_problem[s][p], 549 color: "none" 550 }; 551 } 552 } else { 553 rank_solver[s] = { 554 id: s, 555 score: -1.0 556 }; 557 for (let p = 0; p < nb_p; p++) { 558 if (selected_p[p]) 559 rank_problem_solver[p][s] = { 560 id: s, 561 score: -1.0, 562 color: "none" 563 }; 564 } 565 } 566 } 567 // Sorting of the arrays 568 rank_solver.sort((a, b) => b.score - a.score); 569 for (let p = 0; p < nb_p; p++) { 570 if (!selected_p[p]) 571 continue; 572 rank_problem_solver[p].sort((a, b) => b.score - a.score);
573 rank_problem_solver[p][0].color = "gold"; 574 for (let r = 1; r < nb_s; r++) { 575 if (rank_problem_solver[p][r].score < 0.0) 576 break; 577 if (rank_problem_solver[p][r - 1].score == rank_problem_solver[p][r].score) { 578 rank_problem_solver[p][r].color = rank_problem_solver[p][r - 1].color; 579 } else if (r == 1) { 580 rank_problem_solver[p][r].color = "silver"; 581 } else if (r == 2) { 582 rank_problem_solver[p][r].color = "#cd7f32"; 583 } else { 584 break; 585 } 586 } 587 for (let r = 0; r < nb_s; r++) { 588 var s = rank_problem_solver[p][r].id; 589 map_problem_solver_rank[p][s] = r; 590 } 591 } 592 } 593 594 function createLinkCol(text, loc) { 595 const link = document.createElement('a'); 596 link.href = `../${loc}`; 597 link.target = "_blank"; 598 link.appendChild(document.createTextNode(text)); 599 const col = document.createElement('td'); 600 col.appendChild(link); 601 return col; 602 } 603 604 function createTxtCol(text, al) { 605 const col = document.createElement('td'); 606 col.align = al; 607 const txt = document.createTextNode(text); 608 col.appendChild(txt); 609 return col; 610 } 611 612 function createTxtColWithColor(text, al, color) { 613 const col = document.createElement('td'); 614 col.align = al; 615 col.style.backgroundColor = color; 616 const txt = document.createTextNode(text); 617 col.appendChild(txt); 618 return col; 619 } 620 621 622 // The first n left elements are left aligned, the rest is right aligned 623 function addRowText(table, rowtext, n) { 624 const row = document.createElement('tr'); 625 let k = n; 626 for (const i in rowtext) { 627 let al = "right"; 628 if (k > 0) { 629 k--; 630 al = "left"; 631 } 632 row.appendChild(createTxtCol(` ${rowtext[i]} `, al)); 633 } 634 table.appendChild(row); 635 } 636 637 // The first n left elements are left aligned, the rest is right aligned. 638 // The first m elements have no background color. 639 function addRowTextWithColor(table, rowtext, n, color, m) { 640 const row = document.createElement('tr'); 641 let k = n; 642 let l = m; 643 //row.style.backgroundColor = color; 644 for (const i in rowtext) { 645 let al = "right"; 646 if (k > 0) { 647 k--; 648 al = "left"; 649 } 650 if (l > 0) { 651 row.appendChild(createTxtCol(` ${rowtext[i]} `, al)); 652 l--; 653 } else { 654 row.appendChild(createTxtColWithColor(` ${rowtext[i]} `, al, color)); 655 } 656 } 657 table.appendChild(row); 658 } 659 660 function modifyToTal(selected_solver) { 661 const tbl = document.getElementsByName('total_table')[0]; 662 let bd = document.createElement('tbody'); 663 const tr = ["TOTAL", total.toFixed(0)]; 664 if (hasIncompleteScoring) { 665 tr.push(total_inc.toFixed(0)); 666 } 667 if (hasAreaScoring) { 668 tr.push(total_area.toFixed(3)); 669 } 670 addRowText(bd, tr, 1); 671 tbl.appendChild(bd); 672 bd = document.createElement('tbody'); 673 for (let i = 0; i < nb_s; i++) { 674 if (selected_solver[i]) { 675 let color = "none"; 676 if (rank_solver[0].id == i) 677 color = "gold"; 678 if (rank_solver[1].id == i) 679 color = "silver"; 680 if (rank_solver[2].id == i) 681 color = "#cd7f32"; 682 const tr = [solvers[i], total_solver[i].toFixed(2)]; 683 if (hasIncompleteScoring) { 684 tr.push(total_solver_inc[i].toFixed(2)); 685 } 686 if (hasAreaScoring) { 687 tr.push(total_solver_area[i].toFixed(2)); 688 } 689 if (color == "none") { 690 addRowText(bd, tr, 1); 691 } else { 692 addRowTextWithColor(bd, tr, 1, color, 0); 693 } 694 } 695 } 696 tbl.appendChild(bd); 697 } 698 699 function modifyProblem(selected_solver, selected_problem) { 700 const tbl = document.getElementsByName('problem_table')[0]; 701 for (let i = 0; i < nb_p; i++) { 702 if (!selected_problem[i]) 703 continue; 704 let bd = document.createElement('tbody');
705 const row = document.createElement('tr'); 706 if (loc_problems[i] != 'null') { 707 row.appendChild(createLinkCol( 708 `${problems[i]} (${kind[i]} x${instances[i].length})`, loc_problems[i] 709 )); 710 } else { 711 row.appendChild(createTxtCol( 712 `${problems[i]} (${kind[i]} x${instances[i].length})` 713 )); 714 } 715 row.appendChild(createTxtCol("TOTAL", "left")); 716 row.appendChild(createTxtCol(total_problem[i].toFixed(0), "right")); 717 if (hasIncompleteScoring) { 718 row.appendChild(createTxtCol(total_problem_inc[i].toFixed(0), "right")); 719 } 720 if (hasAreaScoring) { 721 row.appendChild(createTxtCol(total_problem_area[i].toFixed(3), "right")); 722 } 723 bd.appendChild(row); 724 tbl.appendChild(bd); 725 bd = document.createElement('tbody'); 726 for (let j = 0; j < nb_s; j++) { 727 if (!selected_solver[j]) 728 continue; 729 const rank = map_problem_solver_rank[i][j]; 730 const color = rank_problem_solver[i][rank].color; 731 const tr = [" ", solvers[j], total_solver_problem[j][i].toFixed(2)]; 732 if (hasIncompleteScoring) { 733 tr.push(total_solver_problem_inc[j][i].toFixed(2)); 734 } 735 if (hasAreaScoring) { 736 tr.push(total_solver_problem_area[j][i].toFixed(2)); 737 } 738 if (color == "none") { 739 addRowText(bd, tr, 2); 740 } else { 741 addRowTextWithColor(bd, tr, 2, color, 1); 742 } 743 } 744 tbl.appendChild(bd); 745 } 746 } 747 748 function rankAndMap(ranking, map) { 749 // Sort the array 750 ranking.sort((a, b) => b.score - a.score); 751 // Compute the colors 752 ranking[0].color = "gold"; 753 for (let r = 1; r < nb_s; r++) { 754 if (ranking[r].score < 0.0) 755 break; 756 if (ranking[r - 1].score == ranking[r].score) { 757 ranking[r].color = ranking[r - 1].color; 758 } else if (r == 1) { 759 ranking[r].color = "silver"; 760 } else if (r == 2) { 761 ranking[r].color = "#cd7f32"; 762 } else { 763 break; 764 } 765 } 766 // Create the mapping 767 for (let r = 0; r < nb_s; r++) 768 map[ranking[r].id] = r; 769 } 770 771 772 function modifyInstance(selected_solver, selected_problem) { 773 const tbl = document.getElementsByName('instance_table')[0]; 774 775 for (let p = 0; p < nb_p; p++) { 776 if (selected_problem[p]) { 777 for (let k = 0; k < instances[p].length; k++) { 778 const i = instances[p][k]; 779 780 // Compute the solver ranking 781 const ranking = []; 782 const map = []; 783 for (let s = 0; s < nb_s; s++) { 784 if (selected_solver[s]) { 785 ranking[s] = { 786 id: s, 787 score: total_solver_instance[s][i], 788 color: "none" 789 }; 790 } else { 791 ranking[s] = { 792 id: s, 793 score: -1.0, 794 color: "none" 795 }; 796 } 797 } 798 799 // Generate the ranking and mapping 800 rankAndMap(ranking, map); 801 802 let bd = document.createElement('tbody'); 803 const row = document.createElement('tr'); 804 if (loc_problems[p] != 'null') { 805 row.appendChild(createLinkCol( 806 `${problems[p]} (${kind[p]})`, loc_problems[p] 807 )); 808 } else { 809 row.appendChild(createTxtCol( 810 `${problems[p]} (${kind[p]})` 811 )); 812 } 813 row.appendChild(createLinkCol(benchmarks[i], loc_instances[i])); 814 row.appendChild(createTxtCol("TOTAL", "left")); 815 row.appendChild(createTxtCol(" ", "left")); 816 row.appendChild(createTxtCol(" ", "left")); 817 row.appendChild(createTxtCol(" ", "left")); 818 row.appendChild(createTxtCol(total_instance[i].toFixed(0), "right")); 819 if (hasIncompleteScoring) { 820 row.appendChild(createTxtCol(total_instance_inc[i].toFixed(0), "right")); 821 } 822 if (hasAreaScoring) { 823 row.appendChild(createTxtCol(total_instance_area[i].toFixed(3), "right")); 824 } 825 bd.appendChild(row); 826 tbl.appendChild(bd); 827 bd = document.createElement('tbody'); 828 let p_string = problems[p]; 829 let i_string = benchmarks[i]; 830 for (let s = 0; s < nb_s; s++) { 831 if (selected_solver[s]) { 832 const tr = [p_string, i_string, solvers[s], 833 results[s][i], times[s][i], objectives[s][i], 834 total_solver_instance[s][i].toFixed(2), 835 ] 836 if (hasIncompleteScoring) { 837 tr.push(total_solver_instance_inc[s][i].toFixed(2)); 838 } 839 if (hasAreaScoring) { 840 tr.push(total_solver_instance_area[s][i].toFixed(2)); 841 } 842 if (ranking[map[s]].color == "none" || ranking[map[s]].score <= 0.0) { 843 addRowText(bd, tr, 4); 844 } else { 845 addRowTextWithColor(bd, tr, 4, ranking[map[s]].color, 2); 846 } 847 p_string = " "; 848 i_string = " "; 849 } 850 } 851 tbl.appendChild(bd); 852 } 853 } 854 } 855 } 856 857 function modifyInstancePlots(selected_solver, selected_problem, xaxis_type, lineshape) { 858 const tbl = document.getElementsByName('objective_plots')[0]; 859 for (let p = 0; p < nb_p; p++) { 860 if (selected_problem[p]) { 861 for (let k = 0;
861 k < instances[p].length; k++) { 862 const i = instances[p][k]; 863 let bd = document.createElement('tbody'); 864 let row = document.createElement('tr'); 865 if (loc_problems[p] != 'null') { 866 row.appendChild( 867 createLinkCol(`${problems[p]} (${kind[p]})`, loc_problems[p]) 868 ); 869 } else { 870 row.appendChild( 871 createTxtCol(`${problems[p]} (${kind[p]})`) 872 ); 873 } 874 row.appendChild(createLinkCol(benchmarks[i], loc_instances[i])); 875 row.appendChild(createTxtCol("Plot", "left")); 876 bd.appendChild(row); 877 tbl.appendChild(bd); 878 879 bd = document.createElement('tbody'); 880 881 row = document.createElement('tr'); 882 // First column 883 let col = document.createElement('td'); 884 let txt = document.createTextNode(problems[p]); 885 col.align = "left"; 886 col.appendChild(txt); 887 row.appendChild(col); 888 889 // Second column 890 col = document.createElement('td'); 891 txt = document.createTextNode(benchmarks[i]); 892 col.align = "left"; 893 col.appendChild(txt); 894 row.appendChild(col); 895 896 // Third column 897 col = document.createElement('td'); 898 const div = document.createElement('div'); 899 div.id = p + benchmarks[i]; 900 col.appendChild(div); 901 row.appendChild(col); 902 903 bd.appendChild(row); 904 905 tbl.appendChild(bd); 906 } 907 } 908 } 909 // Plotting 910 for (let p = 0; p < nb_p; p++) { 911 //Check if the problem was selected 912 if (!selected_problem[p]) 913 continue; 914 // Problem is selected 915 for (let k = 0; k < instances[p].length; k++) { 916 const i = instances[p][k]; 917 const data = getDataForObjectivePlot(selected_solver, p, i, lineshape); 918 const layout = { 919 title: `${problems[p]} ${benchmarks[i]}`, 920 xaxis: { 921 title: 'time in ms', 922 type: xaxis_type 923 }, 924 yaxis: { 925 title: 'objective value' 926 }, 927 showlegend: true, 928 height: 700, 929 legend: { 930 orientation: 'h' 931 } 932 }; 933 //console.log(data); 934 Plotly.newPlot(p + benchmarks[i], data, layout); 935 } 936 } 937 } 938 939 function getDataForObjectivePlot(selected_s, p, i, lineshape) { 940 const data = []; 941 let index = 0; 942 let min_obj = 0; 943 let max_obj = 0; 944 let sol = false; 945 // Compute minimal and maximal objective 946 for (let s = 0; s < nb_s; s++) { 947 if (!selected_s[s]) 948 continue; 949 if (step_count[s][i] > 0) { 950 if (sol) { 951 min_obj = Math.min(min_obj, objectives[s][i]); 952 max_obj = Math.max(max_obj, objectives[s][i]); 953 min_obj = Math.min(min_obj, first_objectives[s][i]); 954 max_obj = Math.max(max_obj, first_objectives[s][i]); 955 } else { 956 sol = true; 957 min_obj = Math.min(objectives[s][i], first_objectives[s][i]); 958 max_obj = Math.max(objectives[s][i], first_objectives[s][i]); 959 } 960 } 961 } 962 // Generate data 963 if (sol) { 964 for (let s = 0; s < nb_s; s++) { 965 if (!selected_s[s]) 966 continue; 967 if (step_count[s][i] > 0) { 968 let trace = {}; 969 if (lineshape == 'lines') { 970 trace = { 971 x: step_times[s][i], 972 y: step_obj[s][i], 973 type: 'scatter', 974 name: solvers[s] 975 }; 976 } else { 977 trace = { 978 x: step_times[s][i], 979 y: step_obj[s][i], 980 type: 'scatter', 981 line: { 982 shape: lineshape 983 }, 984 name: solvers[s] 985 }; 986 } 987 data[index] = trace; 988 index++; 989 } 990 } 991 } 992 return data; 993 } 994 995 996 function modifyTables(selected_solver, selected_problem) { 997 const tables = ["total_table", "problem_table", "instance_table", "objective_plots"]; 998 for (const i in tables) { 999 const tbl_l = document.getElementsByName(tables[i]); 1000 const tbl = tbl_l[0]; 1001 while (tbl.tBodies.length > 0) 1002 tbl.removeChild(tbl.tBodies[0]); 1003 } 1004 modifyToTal(selected_solver, selected_problem); 1005 modifyProblem(selected_solver, selected_problem); 1006 modifyInstance(selected_solver, selected_problem); 1007 1008 // Retrieve parameters for plotting 1009 1010 // x-axis type 1011 let xaxis_type = '-'; 1012 if (document.getElementById("xaxis_linear").checked) { 1013 xaxis_type = 'linear'; 1014 } else if (document.getElementById("xaxis_log").checked) { 1015 xaxis_type = 'log'; 1016 } 1017 // lineshape type 1018 let lineshape = 'hv'; 1019 if (document.getElementById("lineshape_lines").checked) { 1020 lineshape = 'lines'; 1021 } 1022 // Draw plots for each instance 1023 if (document.getElementById("plot_instance").checked) { 1024 modifyInstancePlots(selected_solver, selected_problem, xaxis_type, lineshape); 1025 document.getElementById('plots-section').style.display = 'block'; 1026 } else { 1027 document.getElementById('plots-section').style.display = 'none'; 1028 } 1029 // Draw plot for the total score 1030 // XXX Disable it, because it is not finished yet 1031 //if (document.getElementById("plot_totalscore").checked) { 1032 // draw_scores_over_time(selected_solver, selected_problem, xaxis_type, lineshape, timestep); 1033 //} 1034 } 1035 1036 function sortTotalTable(col, sort_criteria) { 1037 console.log(`column: ${col}`); 1038 sortTable("total_table", col, 2, sort_criteria); 1039 } 1040 1041 // Adapted from https://www.w3schools.com/howto/howto_js_sort_table.asp 1042 function sortTable(name, col, col_start, sort_criteria) { 1043 let table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0; 1044 table = document.getElementById(name); 1045 switching = true; 1046 // Set the sorting direction to ascending: 1047 dir = "asc"; 1048 console.log(table); 1049 // Make a loop that will continue until no switching has been done: 1050 while (switching) { 1051 //start by saying: no switching is done: 1052 switching = false;
1053 rows = table.getElementsByTagName("tr"); 1054 /*Loop through all table rows (except the 1055 first, which contains table headers):*/ 1056 for (i = col_start; i < (rows.length - 1); i++) { 1057 //start by saying there should be no switching: 1058 shouldSwitch = false; 1059 /*Get the two elements you want to compare, 1060 one from current row and one from the next:*/ 1061 x = rows[i].getElementsByTagName("td")[col]; 1062 y = rows[i + 1].getElementsByTagName("td")[col]; 1063 /*check if the two rows should switch place, 1064 based on the direction, asc or desc:*/ 1065 if (dir == "asc") { 1066 if ( 1067 (sort_criteria == "string" && x.innerHTML.toLowerCase() > y.innerHTML.toLowerCase()) || 1068 (sort_criteria == "number" && parseFloat(x.innerHTML) > parseFloat(y.innerHTML)) 1069 ) { 1070 //if so, mark as a switch and break the loop: 1071 shouldSwitch = true; 1072 break; 1073 } 1074 } else if (dir == "desc") { 1075 if ( 1076 (sort_criteria == "string" && x.innerHTML.toLowerCase() < y.innerHTML.toLowerCase()) || 1077 (sort_criteria == "number" && parseFloat(x.innerHTML) < parseFloat(y.innerHTML)) 1078 ) { 1079 //if so, mark as a switch and break the loop: 1080 shouldSwitch = true; 1081 break; 1082 } 1083 } 1084 } 1085 if (shouldSwitch) { 1086 /*If a switch has been marked, make the switch 1087 and mark that a switch has been done:*/ 1088 rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); 1089 switching = true; 1090 //Each time a switch is done, increase this count by 1: 1091 switchcount++; 1092 } else { 1093 /*If no switching has been done AND the direction is "asc", 1094 set the direction to "desc" and run the while loop again.*/ 1095 if (switchcount == 0 && dir == "asc") { 1096 dir = "desc"; 1097 switching = true; 1098 } 1099 } 1100 } 1101 } 1102 1103 function downloadResults() { 1104 const prob = []; 1105 const solv = []; 1106 for (let i = 0; i < nb_p; i++) { 1107 prob[i] = pbox[i].checked; 1108 } 1109 for (let i = 0; i < nb_s; i++) { 1110 solv[i] = sbox[i].checked; 1111 } 1112 computeScores(solv, prob); 1113 if (hasIncompleteScoring) { 1114 computeScoresInc(solv, prob); 1115 } 1116 if (hasAreaScoring) { 1117 computeScoresArea(solv, prob); 1118 } 1119 const headings = ["Problem", "Kind", "Instance", "Solver", "Status", "Time", "Objective", "Score"]; 1120 if (hasIncompleteScoring) { 1121 headings.push("Score Incomplete"); 1122 } 1123 if (hasAreaScoring) { 1124 headings.push("Score Area"); 1125 } 1126 const csv = [headings]; 1127 for (let p = 0; p < nb_p; p++) { 1128 if (prob[p]) { 1129 for (let k = 0; k < instances[p].length; k++) { 1130 const i = instances[p][k]; 1131 const p_string = problems[p]; 1132 const k_string = kind[p]; 1133 const i_string = benchmarks[i]; 1134 for (let s = 0; s < nb_s; s++) { 1135 if (solv[s]) { 1136 const row = [p_string, k_string, i_string, solvers[s], 1137 results[s][i], times[s][i], objectives[s][i], 1138 total_solver_instance[s][i], 1139 ] 1140 if (hasIncompleteScoring) { 1141 row.push(total_solver_instance_inc[s][i]); 1142 } 1143 if (hasAreaScoring) { 1144 row.push(total_solver_instance_area[s][i]); 1145 } 1146 csv.push(row); 1147 } 1148 } 1149 } 1150 } 1151 } 1152 // Export as CSV 1153 let csvContent = "data:text/csv;charset=utf-8,"; 1154 csv.forEach(function (rowArray) { 1155 let row = rowArray.join(","); 1156 csvContent += row + "\r\n"; 1157 }); 1158 const encodedUri = encodeURI(csvContent); 1159 const link = document.createElement("a"); 1160 link.setAttribute("href", encodedUri); 1161 link.setAttribute("download", "results.csv"); 1162 document.body.appendChild(link); 1163 link.click(); 1164 } 1165 1166 function downloadSteps() { 1167 if (!hasAreaScoring) { 1168 return; 1169 } 1170 const prob = []; 1171 const solv = []; 1172 for (let i = 0; i < nb_p; i++) { 1173 prob[i] = pbox[i].checked; 1174 } 1175 for (let i = 0; i < nb_s; i++) { 1176 solv[i] = sbox[i].checked; 1177 } 1178 const headings = ["Problem", "Instance", "Solver", "Time", "Objective"]; 1179 const csv = [headings]; 1180 for (let p = 0; p < nb_p; p++) { 1181 if (prob[p]) { 1182 for (let k = 0;
1182 k < instances[p].length; k++) { 1183 const i = instances[p][k]; 1184 const p_string = problems[p]; 1185 const i_string = benchmarks[i]; 1186 for (let s = 0; s < nb_s; s++) { 1187 if (solv[s]) { 1188 for (let j = 0; j < step_count[s][i]; j++) { 1189 const row = [p_string, i_string, solvers[s], step_times[s][i][j]]; 1190 const obj = step_obj[s][i][j]; 1191 row.push(obj === ' ' ? '' : obj); 1192 csv.push(row); 1193 } 1194 } 1195 } 1196 } 1197 } 1198 } 1199 // Export as CSV 1200 let csvContent = "data:text/csv;charset=utf-8,"; 1201 csv.forEach(function (rowArray) { 1202 let row = rowArray.join(","); 1203 csvContent += row + "\r\n"; 1204 }); 1205 const encodedUri = encodeURI(csvContent); 1206 const link = document.createElement("a"); 1207 link.setAttribute("href", encodedUri); 1208 link.setAttribute("download", "objectives.csv"); 1209 document.body.appendChild(link); 1210 link.click(); 1211 } 1212 1213 init(); 1214 1215 return { 1216 selectFD, 1217 selectFree, 1218 selectPar, 1219 selectOpen, 1220 selectLocal, 1221 selectAll, 1222 clearAll, 1223 computeSelected, 1224 sortTotalTable, 1225 downloadResults, 1226 downloadSteps 1227 } 1228}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.