Czarevich commited on
Commit
345a6ed
·
verified ·
1 Parent(s): 92e5105

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +6 -4
  2. index.html +667 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Simplex
3
- emoji: 🔥
4
  colorFrom: purple
5
- colorTo: blue
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: simplex
3
+ emoji: 🐳
4
  colorFrom: purple
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,667 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Neon LP Solver</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link href="https://fonts.googleapis.com/css2?family=Exo+2:wght@300;400;500;600;700&display=swap" rel="stylesheet">
9
+ <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
10
+ <style>
11
+ body {
12
+ font-family: 'Exo 2', sans-serif;
13
+ background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
14
+ color: #e2e8f0;
15
+ min-height: 100vh;
16
+ }
17
+
18
+ .glass-panel {
19
+ background: rgba(15, 23, 42, 0.7);
20
+ backdrop-filter: blur(10px);
21
+ border: 1px solid rgba(94, 234, 212, 0.2);
22
+ box-shadow: 0 0 20px rgba(94, 234, 212, 0.1);
23
+ transition: all 0.3s ease;
24
+ }
25
+
26
+ .glass-panel:hover {
27
+ box-shadow: 0 0 30px rgba(94, 234, 212, 0.3);
28
+ border-color: rgba(94, 234, 212, 0.4);
29
+ }
30
+
31
+ .neon-text {
32
+ text-shadow: 0 0 5px rgba(94, 234, 212, 0.7);
33
+ }
34
+
35
+ .neon-accent {
36
+ border-color: #5eead4;
37
+ }
38
+
39
+ .neon-button {
40
+ background: rgba(94, 234, 212, 0.1);
41
+ border: 1px solid #5eead4;
42
+ color: #5eead4;
43
+ transition: all 0.3s ease;
44
+ }
45
+
46
+ .neon-button:hover {
47
+ background: rgba(94, 234, 212, 0.3);
48
+ box-shadow: 0 0 15px rgba(94, 234, 212, 0.4);
49
+ }
50
+
51
+ .input-field {
52
+ background: rgba(30, 41, 59, 0.5);
53
+ border: 1px solid rgba(94, 234, 212, 0.3);
54
+ color: #e2e8f0;
55
+ }
56
+
57
+ .input-field:focus {
58
+ outline: none;
59
+ border-color: #5eead4;
60
+ box-shadow: 0 0 10px rgba(94, 234, 212, 0.3);
61
+ }
62
+
63
+ .simplex-table {
64
+ border: 1px solid rgba(94, 234, 212, 0.3);
65
+ }
66
+
67
+ .simplex-table th, .simplex-table td {
68
+ border: 1px solid rgba(94, 234, 212, 0.2);
69
+ padding: 0.5rem;
70
+ text-align: center;
71
+ }
72
+
73
+ .simplex-table th {
74
+ background: rgba(94, 234, 212, 0.1);
75
+ }
76
+
77
+ .pivot-cell {
78
+ background: rgba(236, 72, 153, 0.3);
79
+ animation: pulse 2s infinite;
80
+ }
81
+
82
+ @keyframes pulse {
83
+ 0% { background-color: rgba(236, 72, 153, 0.3); }
84
+ 50% { background-color: rgba(236, 72, 153, 0.6); }
85
+ 100% { background-color: rgba(236, 72, 153, 0.3); }
86
+ }
87
+
88
+ .tab-button {
89
+ background: transparent;
90
+ border: none;
91
+ color: #94a3b8;
92
+ transition: all 0.3s ease;
93
+ }
94
+
95
+ .tab-button.active {
96
+ color: #5eead4;
97
+ border-bottom: 2px solid #5eead4;
98
+ }
99
+
100
+ .tab-button:hover:not(.active) {
101
+ color: #e2e8f0;
102
+ }
103
+
104
+ .scroll-container {
105
+ scrollbar-width: thin;
106
+ scrollbar-color: #5eead4 #1e293b;
107
+ }
108
+
109
+ .scroll-container::-webkit-scrollbar {
110
+ width: 8px;
111
+ height: 8px;
112
+ }
113
+
114
+ .scroll-container::-webkit-scrollbar-track {
115
+ background: #1e293b;
116
+ }
117
+
118
+ .scroll-container::-webkit-scrollbar-thumb {
119
+ background-color: #5eead4;
120
+ border-radius: 4px;
121
+ }
122
+ </style>
123
+ </head>
124
+ <body class="p-4 md:p-8">
125
+ <div class="max-w-7xl mx-auto">
126
+ <header class="mb-8 text-center">
127
+ <h1 class="text-4xl md:text-5xl font-bold mb-2 neon-text">Neon LP Solver</h1>
128
+ <p class="text-lg text-cyan-200">Solve linear programming problems with simplex and dual simplex methods</p>
129
+ </header>
130
+
131
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
132
+ <!-- Problem Input Section -->
133
+ <div class="lg:col-span-1 glass-panel rounded-xl p-6">
134
+ <h2 class="text-2xl font-semibold mb-4 neon-text">Problem Input</h2>
135
+
136
+ <div class="mb-6">
137
+ <label class="block text-sm font-medium mb-2">Optimization Direction</label>
138
+ <div class="flex space-x-4">
139
+ <button id="maximize-btn" class="neon-button rounded-lg px-4 py-2 font-medium">Maximize</button>
140
+ <button id="minimize-btn" class="neon-button rounded-lg px-4 py-2 font-medium">Minimize</button>
141
+ </div>
142
+ </div>
143
+
144
+ <div class="mb-6">
145
+ <label class="block text-sm font-medium mb-2">Number of Variables</label>
146
+ <input type="number" id="var-count" min="1" max="10" value="2"
147
+ class="input-field rounded-lg px-4 py-2 w-full">
148
+ </div>
149
+
150
+ <div class="mb-6">
151
+ <label class="block text-sm font-medium mb-2">Number of Constraints</label>
152
+ <input type="number" id="constraint-count" min="1" max="10" value="2"
153
+ class="input-field rounded-lg px-4 py-2 w-full">
154
+ </div>
155
+
156
+ <button id="setup-problem-btn" class="neon-button rounded-lg px-6 py-3 w-full font-semibold mb-6">
157
+ Setup Problem
158
+ </button>
159
+
160
+ <div id="objective-function-container" class="mb-6 hidden">
161
+ <h3 class="text-lg font-medium mb-3">Objective Function</h3>
162
+ <div id="objective-coeffs" class="grid grid-cols-4 gap-2 mb-2">
163
+ <!-- Dynamically generated -->
164
+ </div>
165
+ </div>
166
+
167
+ <div id="constraints-container" class="hidden">
168
+ <h3 class="text-lg font-medium mb-3">Constraints</h3>
169
+ <div id="constraints-grid">
170
+ <!-- Dynamically generated -->
171
+ </div>
172
+ </div>
173
+
174
+ <button id="solve-btn" class="neon-button rounded-lg px-6 py-3 w-full font-semibold mt-6 hidden">
175
+ Solve Problem
176
+ </button>
177
+ </div>
178
+
179
+ <!-- Results Section -->
180
+ <div class="lg:col-span-2 glass-panel rounded-xl p-6">
181
+ <div class="flex border-b border-cyan-900 mb-4">
182
+ <button class="tab-button px-4 py-2 mr-2 active" data-tab="problem">Problem</button>
183
+ <button class="tab-button px-4 py-2 mr-2" data-tab="simplex">Simplex Method</button>
184
+ <button class="tab-button px-4 py-2 mr-2" data-tab="dual">Dual Problem</button>
185
+ <button class="tab-button px-4 py-2" data-tab="dual-simplex">Dual Simplex</button>
186
+ </div>
187
+
188
+ <div id="problem-tab" class="tab-content">
189
+ <h2 class="text-2xl font-semibold mb-4 neon-text">Problem Statement</h2>
190
+ <div id="problem-display" class="bg-slate-800 rounded-lg p-4 mb-6">
191
+ <p class="text-center text-lg">Enter your problem data to see it displayed here</p>
192
+ </div>
193
+
194
+ <div class="bg-slate-800 rounded-lg p-4">
195
+ <h3 class="text-xl font-medium mb-3">Standard Form</h3>
196
+ <div id="standard-form-display">
197
+ <p class="text-center">Problem will be displayed in standard form after setup</p>
198
+ </div>
199
+ </div>
200
+ </div>
201
+
202
+ <div id="simplex-tab" class="tab-content hidden">
203
+ <h2 class="text-2xl font-semibold mb-4 neon-text">Simplex Method Solution</h2>
204
+ <div id="simplex-steps" class="mb-6">
205
+ <p class="text-center">Solve the problem to see simplex method steps</p>
206
+ </div>
207
+
208
+ <div id="simplex-result" class="bg-slate-800 rounded-lg p-4 hidden">
209
+ <h3 class="text-xl font-medium mb-3">Optimal Solution</h3>
210
+ <div id="simplex-solution">
211
+ <!-- Results will be displayed here -->
212
+ </div>
213
+ </div>
214
+ </div>
215
+
216
+ <div id="dual-tab" class="tab-content hidden">
217
+ <h2 class="text-2xl font-semibold mb-4 neon-text">Dual Problem</h2>
218
+ <div id="dual-problem-display" class="bg-slate-800 rounded-lg p-4 mb-6">
219
+ <p class="text-center">Solve the primal problem to see the dual formulation</p>
220
+ </div>
221
+ </div>
222
+
223
+ <div id="dual-simplex-tab" class="tab-content hidden">
224
+ <h2 class="text-2xl font-semibold mb-4 neon-text">Dual Simplex Method Solution</h2>
225
+ <div id="dual-simplex-steps" class="mb-6">
226
+ <p class="text-center">Generate the dual problem to see solution steps</p>
227
+ </div>
228
+
229
+ <div id="dual-simplex-result" class="bg-slate-800 rounded-lg p-4 hidden">
230
+ <h3 class="text-xl font-medium mb-3">Optimal Solution</h3>
231
+ <div id="dual-simplex-solution">
232
+ <!-- Results will be displayed here -->
233
+ </div>
234
+ </div>
235
+ </div>
236
+ </div>
237
+ </div>
238
+ </div>
239
+
240
+ <script>
241
+ // Global variables
242
+ let problemData = {
243
+ direction: 'max',
244
+ varCount: 2,
245
+ constraintCount: 2,
246
+ objectiveCoeffs: [3, 4],
247
+ constraints: [
248
+ { coeffs: [2, 1], sign: '≤', rhs: 10 },
249
+ { coeffs: [1, 2], sign: '≤', rhs: 12 }
250
+ ]
251
+ };
252
+
253
+ let simplexSolution = null;
254
+ let dualProblem = null;
255
+ let dualSimplexSolution = null;
256
+
257
+ // DOM elements
258
+ const maximizeBtn = document.getElementById('maximize-btn');
259
+ const minimizeBtn = document.getElementById('minimize-btn');
260
+ const varCountInput = document.getElementById('var-count');
261
+ const constraintCountInput = document.getElementById('constraint-count');
262
+ const setupProblemBtn = document.getElementById('setup-problem-btn');
263
+ const objectiveFunctionContainer = document.getElementById('objective-function-container');
264
+ const objectiveCoeffsDiv = document.getElementById('objective-coeffs');
265
+ const constraintsContainer = document.getElementById('constraints-container');
266
+ const constraintsGrid = document.getElementById('constraints-grid');
267
+ const solveBtn = document.getElementById('solve-btn');
268
+
269
+ const tabButtons = document.querySelectorAll('.tab-button');
270
+ const tabContents = document.querySelectorAll('.tab-content');
271
+
272
+ const problemDisplay = document.getElementById('problem-display');
273
+ const standardFormDisplay = document.getElementById('standard-form-display');
274
+ const simplexStepsDiv = document.getElementById('simplex-steps');
275
+ const simplexResultDiv = document.getElementById('simplex-result');
276
+ const simplexSolutionDiv = document.getElementById('simplex-solution');
277
+ const dualProblemDisplay = document.getElementById('dual-problem-display');
278
+ const dualSimplexStepsDiv = document.getElementById('dual-simplex-steps');
279
+ const dualSimplexResultDiv = document.getElementById('dual-simplex-result');
280
+ const dualSimplexSolutionDiv = document.getElementById('dual-simplex-solution');
281
+
282
+ // Event listeners
283
+ maximizeBtn.addEventListener('click', () => {
284
+ problemData.direction = 'max';
285
+ maximizeBtn.classList.add('bg-cyan-600', 'text-white');
286
+ minimizeBtn.classList.remove('bg-cyan-600', 'text-white');
287
+ updateProblemDisplay();
288
+ });
289
+
290
+ minimizeBtn.addEventListener('click', () => {
291
+ problemData.direction = 'min';
292
+ minimizeBtn.classList.add('bg-cyan-600', 'text-white');
293
+ maximizeBtn.classList.remove('bg-cyan-600', 'text-white');
294
+ updateProblemDisplay();
295
+ });
296
+
297
+ setupProblemBtn.addEventListener('click', setupProblem);
298
+ solveBtn.addEventListener('click', solveProblem);
299
+
300
+ tabButtons.forEach(button => {
301
+ button.addEventListener('click', () => {
302
+ const tabId = button.getAttribute('data-tab');
303
+ switchTab(tabId);
304
+ });
305
+ });
306
+
307
+ // Initialize
308
+ maximizeBtn.classList.add('bg-cyan-600', 'text-white');
309
+ setupProblem();
310
+
311
+ // Functions
312
+ function setupProblem() {
313
+ problemData.varCount = parseInt(varCountInput.value);
314
+ problemData.constraintCount = parseInt(constraintCountInput.value);
315
+
316
+ // Setup objective function inputs
317
+ objectiveCoeffsDiv.innerHTML = '';
318
+ for (let i = 0; i < problemData.varCount; i++) {
319
+ const coeffDiv = document.createElement('div');
320
+ coeffDiv.className = 'col-span-3 flex items-center';
321
+
322
+ const coeffInput = document.createElement('input');
323
+ coeffInput.type = 'number';
324
+ coeffInput.className = 'input-field rounded-lg px-3 py-1 w-full';
325
+ coeffInput.placeholder = `Coefficient for x${i+1}`;
326
+ coeffInput.value = i < problemData.objectiveCoeffs.length ? problemData.objectiveCoeffs[i] : '';
327
+ coeffInput.addEventListener('input', () => {
328
+ if (problemData.objectiveCoeffs.length <= i) {
329
+ problemData.objectiveCoeffs.push(parseFloat(coeffInput.value));
330
+ } else {
331
+ problemData.objectiveCoeffs[i] = parseFloat(coeffInput.value);
332
+ }
333
+ updateProblemDisplay();
334
+ });
335
+
336
+ const varLabel = document.createElement('span');
337
+ varLabel.className = 'ml-2';
338
+ varLabel.textContent = `x${i+1}`;
339
+
340
+ if (i < problemData.varCount - 1) {
341
+ const plusSign = document.createElement('span');
342
+ plusSign.className = 'ml-2';
343
+ plusSign.textContent = '+';
344
+ coeffDiv.appendChild(plusSign);
345
+ }
346
+
347
+ coeffDiv.appendChild(coeffInput);
348
+ coeffDiv.appendChild(varLabel);
349
+ objectiveCoeffsDiv.appendChild(coeffDiv);
350
+ }
351
+
352
+ // Setup constraints inputs
353
+ constraintsGrid.innerHTML = '';
354
+ for (let i = 0; i < problemData.constraintCount; i++) {
355
+ const constraintRow = document.createElement('div');
356
+ constraintRow.className = 'grid grid-cols-12 gap-2 mb-3 items-center';
357
+
358
+ // Coefficients
359
+ for (let j = 0; j < problemData.varCount; j++) {
360
+ const coeffInput = document.createElement('input');
361
+ coeffInput.type = 'number';
362
+ coeffInput.className = 'input-field rounded-lg px-3 py-1 w-full';
363
+ coeffInput.placeholder = `a${i+1}${j+1}`;
364
+
365
+ if (i < problemData.constraints.length && j < problemData.constraints[i].coeffs.length) {
366
+ coeffInput.value = problemData.constraints[i].coeffs[j];
367
+ }
368
+
369
+ coeffInput.addEventListener('input', () => {
370
+ if (!problemData.constraints[i]) {
371
+ problemData.constraints[i] = { coeffs: [], sign: '≤', rhs: 0 };
372
+ }
373
+ if (problemData.constraints[i].coeffs.length <= j) {
374
+ problemData.constraints[i].coeffs.push(parseFloat(coeffInput.value));
375
+ } else {
376
+ problemData.constraints[i].coeffs[j] = parseFloat(coeffInput.value);
377
+ }
378
+ updateProblemDisplay();
379
+ });
380
+
381
+ const varLabel = document.createElement('span');
382
+ varLabel.className = 'text-sm';
383
+ varLabel.textContent = `x${j+1}`;
384
+
385
+ const coeffContainer = document.createElement('div');
386
+ coeffContainer.className = 'col-span-1 flex items-center';
387
+ coeffContainer.appendChild(coeffInput);
388
+
389
+ if (j < problemData.varCount - 1) {
390
+ const plusSign = document.createElement('span');
391
+ plusSign.className = 'ml-1';
392
+ plusSign.textContent = '+';
393
+ coeffContainer.appendChild(plusSign);
394
+ }
395
+
396
+ constraintRow.appendChild(coeffContainer);
397
+ }
398
+
399
+ // Sign selector
400
+ const signSelect = document.createElement('select');
401
+ signSelect.className = 'input-field rounded-lg px-2 py-1 col-span-1';
402
+ signSelect.innerHTML = `
403
+ <option value="≤">≤</option>
404
+ <option value="=">=</option>
405
+ <option value="≥">≥</option>
406
+ `;
407
+
408
+ if (i < problemData.constraints.length) {
409
+ signSelect.value = problemData.constraints[i].sign;
410
+ }
411
+
412
+ signSelect.addEventListener('change', () => {
413
+ if (!problemData.constraints[i]) {
414
+ problemData.constraints[i] = { coeffs: [], sign: '≤', rhs: 0 };
415
+ }
416
+ problemData.constraints[i].sign = signSelect.value;
417
+ updateProblemDisplay();
418
+ });
419
+
420
+ constraintRow.appendChild(signSelect);
421
+
422
+ // RHS input
423
+ const rhsInput = document.createElement('input');
424
+ rhsInput.type = 'number';
425
+ rhsInput.className = 'input-field rounded-lg px-3 py-1 col-span-2';
426
+ rhsInput.placeholder = 'RHS';
427
+
428
+ if (i < problemData.constraints.length) {
429
+ rhsInput.value = problemData.constraints[i].rhs;
430
+ }
431
+
432
+ rhsInput.addEventListener('input', () => {
433
+ if (!problemData.constraints[i]) {
434
+ problemData.constraints[i] = { coeffs: [], sign: '≤', rhs: 0 };
435
+ }
436
+ problemData.constraints[i].rhs = parseFloat(rhsInput.value);
437
+ updateProblemDisplay();
438
+ });
439
+
440
+ constraintRow.appendChild(rhsInput);
441
+ constraintsGrid.appendChild(constraintRow);
442
+ }
443
+
444
+ // Show containers
445
+ objectiveFunctionContainer.classList.remove('hidden');
446
+ constraintsContainer.classList.remove('hidden');
447
+ solveBtn.classList.remove('hidden');
448
+
449
+ updateProblemDisplay();
450
+ }
451
+
452
+ function updateProblemDisplay() {
453
+ // Display problem in mathematical notation
454
+ let problemText = problemData.direction === 'max' ? 'Maximize' : 'Minimize';
455
+ problemText += ': $\\displaystyle ';
456
+
457
+ // Objective function
458
+ for (let i = 0; i < problemData.objectiveCoeffs.length; i++) {
459
+ if (i > 0 && problemData.objectiveCoeffs[i] >= 0) {
460
+ problemText += ' + ';
461
+ } else if (problemData.objectiveCoeffs[i] < 0) {
462
+ problemText += ' - ';
463
+ }
464
+
465
+ const absCoeff = Math.abs(problemData.objectiveCoeffs[i]);
466
+ if (absCoeff !== 1) {
467
+ problemText += absCoeff;
468
+ }
469
+
470
+ problemText += `x_{${i+1}}`;
471
+ }
472
+
473
+ problemText += '$<br><br>Subject to:<br>';
474
+
475
+ // Constraints
476
+ for (let i = 0; i < problemData.constraints.length; i++) {
477
+ const constraint = problemData.constraints[i];
478
+ problemText += '$\\displaystyle ';
479
+
480
+ for (let j = 0; j < constraint.coeffs.length; j++) {
481
+ if (j > 0 && constraint.coeffs[j] >= 0) {
482
+ problemText += ' + ';
483
+ } else if (constraint.coeffs[j] < 0) {
484
+ problemText += ' - ';
485
+ }
486
+
487
+ const absCoeff = Math.abs(constraint.coeffs[j]);
488
+ if (absCoeff !== 1) {
489
+ problemText += absCoeff;
490
+ }
491
+
492
+ problemText += `x_{${j+1}}`;
493
+ }
494
+
495
+ problemText += ` ${constraint.sign} ${constraint.rhs}$<br>`;
496
+ }
497
+
498
+ // Non-negativity constraints
499
+ problemText += '<br>With: $\\displaystyle ';
500
+ for (let i = 0; i < problemData.varCount; i++) {
501
+ problemText += `x_{${i+1}} \\geq 0`;
502
+ if (i < problemData.varCount - 1) {
503
+ problemText += ', ';
504
+ }
505
+ }
506
+ problemText += '$';
507
+
508
+ problemDisplay.innerHTML = problemText;
509
+
510
+ // Display standard form
511
+ displayStandardForm();
512
+
513
+ // Update MathJax rendering
514
+ if (typeof MathJax !== 'undefined') {
515
+ MathJax.typeset();
516
+ }
517
+ }
518
+
519
+ function displayStandardForm() {
520
+ let standardText = problemData.direction === 'max' ? 'Maximize' : 'Minimize';
521
+ standardText += ': $\\displaystyle ';
522
+
523
+ // Objective function
524
+ for (let i = 0; i < problemData.objectiveCoeffs.length; i++) {
525
+ if (i > 0 && problemData.objectiveCoeffs[i] >= 0) {
526
+ standardText += ' + ';
527
+ } else if (problemData.objectiveCoeffs[i] < 0) {
528
+ standardText += ' - ';
529
+ }
530
+
531
+ const absCoeff = Math.abs(problemData.objectiveCoeffs[i]);
532
+ if (absCoeff !== 1) {
533
+ standardText += absCoeff;
534
+ }
535
+
536
+ standardText += `x_{${i+1}}`;
537
+ }
538
+
539
+ standardText += '$<br><br>Subject to:<br>';
540
+
541
+ // Constraints in standard form
542
+ for (let i = 0; i < problemData.constraints.length; i++) {
543
+ const constraint = problemData.constraints[i];
544
+ standardText += '$\\displaystyle ';
545
+
546
+ for (let j = 0; j < constraint.coeffs.length; j++) {
547
+ if (j > 0 && constraint.coeffs[j] >= 0) {
548
+ standardText += ' + ';
549
+ } else if (constraint.coeffs[j] < 0) {
550
+ standardText += ' - ';
551
+ }
552
+
553
+ const absCoeff = Math.abs(constraint.coeffs[j]);
554
+ if (absCoeff !== 1) {
555
+ standardText += absCoeff;
556
+ }
557
+
558
+ standardText += `x_{${j+1}}`;
559
+ }
560
+
561
+ // Add slack/surplus variables
562
+ if (constraint.sign === '≤') {
563
+ standardText += ` + s_{${i+1}}`;
564
+ } else if (constraint.sign === '≥') {
565
+ standardText += ` - s_{${i+1}}`;
566
+ }
567
+
568
+ standardText += ` = ${constraint.rhs}$<br>`;
569
+ }
570
+
571
+ // Non-negativity constraints
572
+ standardText += '<br>With: $\\displaystyle ';
573
+ for (let i = 0; i < problemData.varCount; i++) {
574
+ standardText += `x_{${i+1}} \\geq 0`;
575
+ if (i < problemData.varCount - 1) {
576
+ standardText += ', ';
577
+ }
578
+ }
579
+
580
+ // Add non-negativity for slack variables
581
+ if (problemData.constraints.length > 0) {
582
+ standardText += ', ';
583
+ for (let i = 0; i < problemData.constraints.length; i++) {
584
+ standardText += `s_{${i+1}} \\geq 0`;
585
+ if (i < problemData.constraints.length - 1) {
586
+ standardText += ', ';
587
+ }
588
+ }
589
+ }
590
+ standardText += '$';
591
+
592
+ standardFormDisplay.innerHTML = standardText;
593
+
594
+ // Update MathJax rendering
595
+ if (typeof MathJax !== 'undefined') {
596
+ MathJax.typeset();
597
+ }
598
+ }
599
+
600
+ function solveProblem() {
601
+ // In a real implementation, this would call the simplex method algorithm
602
+ // For this demo, we'll simulate a solution
603
+
604
+ // Simulate simplex method steps
605
+ simplexStepsDiv.innerHTML = '<h3 class="text-lg font-medium mb-2">Simplex Method Steps</h3>';
606
+
607
+ // Initial table
608
+ const initialTable = createSimplexTable(0);
609
+ simplexStepsDiv.appendChild(initialTable);
610
+
611
+ // First iteration
612
+ setTimeout(() => {
613
+ const firstIteration = createSimplexTable(1);
614
+ firstIteration.querySelector('.pivot-cell').scrollIntoView({ behavior: 'smooth', block: 'center' });
615
+ simplexStepsDiv.appendChild(firstIteration);
616
+
617
+ // Second iteration (final)
618
+ setTimeout(() => {
619
+ const finalTable = createSimplexTable(2);
620
+ finalTable.querySelector('.pivot-cell').scrollIntoView({ behavior: 'smooth', block: 'center' });
621
+ simplexStepsDiv.appendChild(finalTable);
622
+
623
+ // Display solution
624
+ setTimeout(() => {
625
+ simplexSolution = {
626
+ variables: [4, 4],
627
+ slackVariables: [0, 0],
628
+ optimalValue: 28
629
+ };
630
+
631
+ displaySimplexSolution();
632
+ generateDualProblem();
633
+ }, 500);
634
+ }, 500);
635
+ }, 500);
636
+ }
637
+
638
+ function createSimplexTable(iteration) {
639
+ const tableDiv = document.createElement('div');
640
+ tableDiv.className = 'mb-6 overflow-x-auto scroll-container';
641
+
642
+ const table = document.createElement('table');
643
+ table.className = 'simplex-table w-full mb-2';
644
+
645
+ // Table header
646
+ const thead = document.createElement('thead');
647
+ let headerRow = document.createElement('tr');
648
+
649
+ const headers = ['B.R.', 'x₁', 'x₂', 's₁', 's₂', 'RHS'];
650
+ headers.forEach((header, index) => {
651
+ const th = document.createElement('th');
652
+ th.textContent = header;
653
+ headerRow.appendChild(th);
654
+ });
655
+
656
+ thead.appendChild(headerRow);
657
+ table.appendChild(thead);
658
+
659
+ // Table body
660
+ const tbody = document.createElement('tbody');
661
+
662
+ // Different data for each iteration
663
+ let tableData = [];
664
+ if (iteration === 0) {
665
+ tableData = [
666
+ ['s₁', -3, -3, 1, 0
667
+ </html>