study-update / index.html
raayraay's picture
Add 2 files
3b16b3a verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Linear Programming Study Guide</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.tab-content {
display: none;
}
.tab-content.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.modal {
display: none;
position: fixed;
z-index: 100;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
}
.modal-content {
background-color: #f8fafc;
margin: 10% auto;
padding: 20px;
border-radius: 0.5rem;
max-width: 600px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
}
.flashcard {
perspective: 1000px;
cursor: pointer;
}
.flashcard-inner {
position: relative;
width: 100%;
height: 100%;
transition: transform 0.6s;
transform-style: preserve-3d;
}
.flashcard.flipped .flashcard-inner {
transform: rotateY(180deg);
}
.flashcard-front, .flashcard-back {
position: absolute;
width: 100%;
height: 100%;
backface-visibility: hidden;
padding: 1.5rem;
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.flashcard-back {
transform: rotateY(180deg);
background-color: #e2e8f0;
}
.constraint-line {
stroke-width: 2;
stroke-dasharray: 5,5;
}
.feasible-region {
fill: rgba(56, 178, 172, 0.2);
stroke: rgba(56, 178, 172, 0.8);
stroke-width: 2;
}
.objective-line {
stroke-width: 2;
stroke: #6b46c1;
}
.optimal-point {
fill: #e53e3e;
stroke: #63171b;
stroke-width: 2;
}
</style>
</head>
<body class="bg-gray-50 font-sans">
<div class="container mx-auto px-4 py-8 max-w-6xl">
<!-- Header -->
<header class="mb-8 text-center">
<h1 class="text-4xl font-bold text-indigo-800 mb-2">Linear Programming Study Guide</h1>
<p class="text-lg text-gray-600">Mastering ECE 580 Exam 2 Concepts (Chapters 15-17)</p>
<!-- Progress Bar -->
<div class="mt-6 mb-4">
<div class="flex justify-between mb-1">
<span class="text-sm font-medium text-gray-700" id="progress-text">0% Complete</span>
<span class="text-sm font-medium text-gray-700" id="points">0 Points</span>
</div>
<div class="w-full bg-gray-200 rounded-full h-4">
<div id="progress-bar" class="bg-teal-500 h-4 rounded-full" style="width: 0%"></div>
</div>
</div>
</header>
<!-- Navigation Tabs -->
<div class="flex flex-wrap border-b border-gray-200 mb-6">
<button class="tab-btn px-4 py-2 font-medium text-gray-600 hover:text-indigo-600 transition-colors border-b-2 border-transparent hover:border-indigo-300 active" data-tab="formulating">Formulating Problems</button>
<button class="tab-btn px-4 py-2 font-medium text-gray-600 hover:text-indigo-600 transition-colors border-b-2 border-transparent hover:border-indigo-300" data-tab="graphical">Graphical Solutions</button>
<button class="tab-btn px-4 py-2 font-medium text-gray-600 hover:text-indigo-600 transition-colors border-b-2 border-transparent hover:border-indigo-300" data-tab="standard">Standard Form</button>
<button class="tab-btn px-4 py-2 font-medium text-gray-600 hover:text-indigo-600 transition-colors border-b-2 border-transparent hover:border-indigo-300" data-tab="simplex">Simplex Method</button>
<button class="tab-btn px-4 py-2 font-medium text-gray-600 hover:text-indigo-600 transition-colors border-b-2 border-transparent hover:border-indigo-300" data-tab="duality">Duality</button>
</div>
<!-- Toolbar -->
<div class="flex justify-between mb-6">
<div class="flex space-x-2">
<button id="flashcards-btn" class="bg-indigo-100 hover:bg-indigo-200 text-indigo-800 px-4 py-2 rounded-lg flex items-center transition-colors">
<i class="fas fa-layer-group mr-2"></i> Flashcards
</button>
<button id="quiz-btn" class="bg-purple-100 hover:bg-purple-200 text-purple-800 px-4 py-2 rounded-lg flex items-center transition-colors">
<i class="fas fa-question-circle mr-2"></i> Pop Quiz
</button>
</div>
<div class="flex items-center">
<span class="bg-yellow-100 text-yellow-800 px-3 py-1 rounded-full text-sm font-medium flex items-center">
<i class="fas fa-star mr-1"></i> <span id="badge-count">0</span> Badges
</span>
</div>
</div>
<!-- Tab Contents -->
<div class="bg-white rounded-xl shadow-md p-6 mb-8">
<!-- Formulating Problems Tab -->
<div id="formulating" class="tab-content active">
<h2 class="text-2xl font-bold text-gray-800 mb-4">Formulating Linear Programming Problems</h2>
<div class="grid md:grid-cols-2 gap-6 mb-6">
<!-- Content Block 1 -->
<div class="bg-blue-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-blue-800 mb-2">What is Linear Programming?</h3>
<p class="text-gray-700 mb-3">Linear programming (LP) is a mathematical method for determining the best outcome in a mathematical model whose requirements are represented by linear relationships.</p>
<p class="text-gray-700">Key components:</p>
<ul class="list-disc pl-5 text-gray-700 space-y-1 mt-2">
<li><strong>Objective Function:</strong> What we want to maximize or minimize</li>
<li><strong>Decision Variables:</strong> Variables that represent choices</li>
<li><strong>Constraints:</strong> Limitations on the decision variables</li>
</ul>
</div>
<!-- Content Block 2 -->
<div class="bg-green-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-green-800 mb-2">Example: Taco & Burger Stand</h3>
<p class="text-gray-700 mb-3">A food stand sells tacos ($2 profit each) and burgers ($3 profit each). They have limited ingredients:</p>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>Meat: 20 lbs (taco: 0.25 lb, burger: 0.5 lb)</li>
<li>Cheese: 15 lbs (taco: 0.1 lb, burger: 0.3 lb)</li>
<li>Time: 8 hours (taco: 2 min, burger: 5 min)</li>
</ul>
<button id="taco-animation-btn" class="mt-3 bg-blue-500 hover:bg-blue-600 text-white px-3 py-1 rounded text-sm transition-colors">
<i class="fas fa-play mr-1"></i> Show Animation
</button>
</div>
</div>
<!-- Animation Placeholder -->
<div id="taco-animation" class="hidden bg-gray-100 p-4 rounded-lg mb-6">
<div class="flex justify-between items-center mb-2">
<h4 class="font-medium text-gray-700">Formulating the LP Problem</h4>
<button id="close-animation" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="bg-white p-3 rounded border border-gray-200">
<div class="flex items-center mb-2">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center mr-2">
<span class="text-blue-600 font-bold">1</span>
</div>
<p class="text-gray-700">Define decision variables: Let x = number of tacos, y = number of burgers</p>
</div>
<div class="flex items-center mb-2">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center mr-2">
<span class="text-blue-600 font-bold">2</span>
</div>
<p class="text-gray-700">Objective function: Maximize profit = 2x + 3y</p>
</div>
<div class="flex items-center mb-2">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center mr-2">
<span class="text-blue-600 font-bold">3</span>
</div>
<p class="text-gray-700">Constraints:</p>
</div>
<div class="ml-10">
<p class="text-gray-700">0.25x + 0.5y ≤ 20 (Meat constraint)</p>
<p class="text-gray-700">0.1x + 0.3y ≤ 15 (Cheese constraint)</p>
<p class="text-gray-700">2x + 5y ≤ 480 (Time constraint in minutes)</p>
<p class="text-gray-700">x ≥ 0, y ≥ 0 (Non-negativity)</p>
</div>
</div>
</div>
<!-- Interactive Practice -->
<div class="bg-yellow-50 p-4 rounded-lg mb-6">
<h3 class="text-lg font-semibold text-yellow-800 mb-3">Practice: Pizza & Wings</h3>
<p class="text-gray-700 mb-3">A restaurant sells pizza ($8 profit) and wings ($5 profit). They have:</p>
<ul class="list-disc pl-5 text-gray-700 mb-4">
<li>Dough: 50 lbs (pizza: 1 lb, wings: 0.2 lb)</li>
<li>Sauce: 20 lbs (pizza: 0.5 lb, wings: 0.1 lb)</li>
<li>Oven time: 12 hours (pizza: 15 min, wings: 10 min)</li>
</ul>
<div class="grid md:grid-cols-2 gap-4">
<div>
<label class="block text-gray-700 mb-1">Objective Function:</label>
<input type="text" id="pizza-objective" class="w-full px-3 py-2 border border-gray-300 rounded" placeholder="e.g., Maximize 8x + 5y">
</div>
<div>
<label class="block text-gray-700 mb-1">Constraints:</label>
<textarea id="pizza-constraints" class="w-full px-3 py-2 border border-gray-300 rounded" rows="4" placeholder="Enter each constraint on a new line"></textarea>
</div>
</div>
<div class="flex justify-between mt-4">
<button id="check-pizza" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check mr-2"></i> Check Answer
</button>
<button id="show-pizza-solution" class="text-blue-600 hover:text-blue-800 flex items-center">
<i class="fas fa-lightbulb mr-2"></i> Show Solution
</button>
</div>
<div id="pizza-feedback" class="hidden mt-4 p-3 rounded"></div>
</div>
<!-- Quick Review -->
<div class="bg-purple-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-purple-800 mb-2">Quick Review</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>LP problems have an objective to maximize or minimize</li>
<li>Decision variables represent quantities to be determined</li>
<li>Constraints limit the possible values of variables</li>
<li>All relationships must be linear (no exponents, no products of variables)</li>
<li>Non-negativity constraints are usually required</li>
</ul>
<div class="mt-4">
<button class="mark-complete bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check-circle mr-2"></i> Mark Complete
</button>
</div>
</div>
</div>
<!-- Graphical Solutions Tab -->
<div id="graphical" class="tab-content">
<h2 class="text-2xl font-bold text-gray-800 mb-4">Graphical Solutions</h2>
<div class="grid md:grid-cols-2 gap-6 mb-6">
<!-- Content Block 1 -->
<div class="bg-blue-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-blue-800 mb-2">Graphical Method Basics</h3>
<p class="text-gray-700 mb-3">For problems with two variables, we can solve LP problems graphically:</p>
<ol class="list-decimal pl-5 text-gray-700 space-y-1">
<li>Plot each constraint as an equation</li>
<li>Identify the feasible region (area satisfying all constraints)</li>
<li>Plot the objective function for different values</li>
<li>Find the optimal solution at a corner point of the feasible region</li>
</ol>
</div>
<!-- Content Block 2 -->
<div class="bg-green-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-green-800 mb-2">Special Cases</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li><strong>Multiple Solutions:</strong> Objective function parallel to a constraint</li>
<li><strong>Unbounded:</strong> Feasible region extends infinitely</li>
<li><strong>Infeasible:</strong> No points satisfy all constraints</li>
</ul>
</div>
</div>
<!-- Interactive Graph -->
<div class="bg-gray-100 p-4 rounded-lg mb-6">
<h3 class="text-lg font-semibold text-gray-800 mb-3">Interactive Graph</h3>
<div class="grid md:grid-cols-3 gap-4 mb-4">
<div>
<label class="block text-gray-700 mb-1">Objective:</label>
<select id="graph-objective" class="w-full px-3 py-2 border border-gray-300 rounded">
<option value="max">Maximize</option>
<option value="min">Minimize</option>
</select>
</div>
<div>
<label class="block text-gray-700 mb-1">Function:</label>
<input type="text" id="graph-function" class="w-full px-3 py-2 border border-gray-300 rounded" placeholder="e.g., 3x + 2y">
</div>
<div>
<label class="block text-gray-700 mb-1">Value:</label>
<input type="number" id="graph-value" class="w-full px-3 py-2 border border-gray-300 rounded" placeholder="e.g., 30" value="30">
</div>
</div>
<div class="grid md:grid-cols-2 gap-4 mb-4">
<div>
<label class="block text-gray-700 mb-1">Add Constraint:</label>
<div class="flex">
<input type="text" id="new-constraint" class="flex-1 px-3 py-2 border border-gray-300 rounded-l" placeholder="e.g., x + y ≤ 10">
<button id="add-constraint" class="bg-blue-500 hover:bg-blue-600 text-white px-3 py-2 rounded-r">
<i class="fas fa-plus"></i>
</button>
</div>
</div>
<div>
<label class="block text-gray-700 mb-1">Constraints:</label>
<select id="constraint-list" class="w-full px-3 py-2 border border-gray-300 rounded" size="3">
<!-- Constraints will be added here -->
</select>
</div>
</div>
<div class="flex space-x-2 mb-4">
<button id="find-optimal" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-bullseye mr-2"></i> Find Optimal
</button>
<button id="reset-graph" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-redo mr-2"></i> Reset
</button>
</div>
<div class="bg-white p-2 rounded border border-gray-300">
<svg id="graph" width="100%" height="400" viewBox="0 0 500 400" class="border border-gray-200">
<!-- Graph elements will be added here -->
</svg>
</div>
</div>
<!-- Quick Review -->
<div class="bg-purple-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-purple-800 mb-2">Quick Review</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>Graphical method works for 2-variable problems</li>
<li>Feasible region is the intersection of all constraints</li>
<li>Optimal solution is at a corner point (vertex)</li>
<li>Objective function is moved parallel until it touches the feasible region</li>
</ul>
<div class="mt-4">
<button class="mark-complete bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check-circle mr-2"></i> Mark Complete
</button>
</div>
</div>
</div>
<!-- Standard Form Tab -->
<div id="standard" class="tab-content">
<h2 class="text-2xl font-bold text-gray-800 mb-4">Standard Form</h2>
<div class="grid md:grid-cols-2 gap-6 mb-6">
<!-- Content Block 1 -->
<div class="bg-blue-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-blue-800 mb-2">Standard Form Requirements</h3>
<p class="text-gray-700 mb-3">All LP problems must be converted to standard form for the simplex method:</p>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>Maximization problem (convert minimization by multiplying objective by -1)</li>
<li>All constraints are equations (not inequalities)</li>
<li>All variables are non-negative</li>
<li>Right-hand side constants are non-negative</li>
</ul>
</div>
<!-- Content Block 2 -->
<div class="bg-green-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-green-800 mb-2">Conversion Rules</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li><strong>≤ constraints:</strong> Add slack variable (s ≥ 0)</li>
<li><strong>≥ constraints:</strong> Subtract surplus variable (s ≥ 0) and add artificial variable (a ≥ 0)</li>
<li><strong>= constraints:</strong> Add artificial variable (a ≥ 0)</li>
<li><strong>Unrestricted variables:</strong> Replace x with x⁺ - x⁻ where x⁺, x⁻ ≥ 0</li>
</ul>
</div>
</div>
<!-- Example Conversion -->
<div class="bg-yellow-50 p-4 rounded-lg mb-6">
<h3 class="text-lg font-semibold text-yellow-800 mb-3">Example Conversion</h3>
<div class="grid md:grid-cols-2 gap-4 mb-4">
<div>
<h4 class="font-medium text-gray-700 mb-2">Original Problem:</h4>
<div class="bg-white p-3 rounded border border-gray-200">
<p>Minimize: -x₁ + 2x₂</p>
<p>Subject to:</p>
<p>x₁ + x₂ ≤ 6</p>
<p>x₁ - x₂ ≥ 2</p>
<p>x₁ + 2x₂ = 10</p>
<p>x₁ ≥ 0, x₂ unrestricted</p>
</div>
</div>
<div>
<h4 class="font-medium text-gray-700 mb-2">Standard Form:</h4>
<div class="bg-white p-3 rounded border border-gray-200">
<p>Maximize: x₁ - 2x₂⁺ + 2x₂⁻</p>
<p>Subject to:</p>
<p>x₁ + x₂⁺ - x₂⁻ + s₁ = 6</p>
<p>x₁ - x₂⁺ + x₂⁻ - s₂ + a₁ = 2</p>
<p>x₁ + 2x₂⁺ - 2x₂⁻ + a₂ = 10</p>
<p>All variables ≥ 0</p>
</div>
</div>
</div>
<button id="show-conversion-animation" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-play mr-2"></i> Show Conversion Steps
</button>
</div>
<!-- Practice Section -->
<div class="bg-orange-50 p-4 rounded-lg mb-6">
<h3 class="text-lg font-semibold text-orange-800 mb-3">Practice Conversion</h3>
<div class="mb-4">
<label class="block text-gray-700 mb-1">Original Problem:</label>
<textarea id="original-problem" class="w-full px-3 py-2 border border-gray-300 rounded" rows="4" placeholder="Enter the original LP problem"></textarea>
</div>
<div class="mb-4">
<label class="block text-gray-700 mb-1">Converted Standard Form:</label>
<textarea id="standard-form" class="w-full px-3 py-2 border border-gray-300 rounded" rows="4" placeholder="Enter your converted standard form"></textarea>
</div>
<div class="flex justify-between">
<button id="check-standard" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check mr-2"></i> Check Answer
</button>
<button id="show-standard-solution" class="text-blue-600 hover:text-blue-800 flex items-center">
<i class="fas fa-lightbulb mr-2"></i> Show Solution
</button>
</div>
<div id="standard-feedback" class="hidden mt-4 p-3 rounded"></div>
</div>
<!-- Quick Review -->
<div class="bg-purple-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-purple-800 mb-2">Quick Review</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>Standard form requires maximization, equality constraints, and non-negative variables</li>
<li>Slack variables are added for ≤ constraints</li>
<li>Surplus and artificial variables are added for ≥ constraints</li>
<li>Artificial variables are needed for = constraints</li>
<li>Unrestricted variables are split into positive and negative parts</li>
</ul>
<div class="mt-4">
<button class="mark-complete bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check-circle mr-2"></i> Mark Complete
</button>
</div>
</div>
</div>
<!-- Simplex Method Tab -->
<div id="simplex" class="tab-content">
<h2 class="text-2xl font-bold text-gray-800 mb-4">Simplex Method</h2>
<div class="grid md:grid-cols-2 gap-6 mb-6">
<!-- Content Block 1 -->
<div class="bg-blue-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-blue-800 mb-2">Simplex Algorithm Steps</h3>
<ol class="list-decimal pl-5 text-gray-700 space-y-1">
<li>Convert problem to standard form</li>
<li>Set up initial simplex tableau</li>
<li>Identify entering variable (most negative coefficient in objective row)</li>
<li>Identify departing variable (minimum ratio test)</li>
<li>Pivot to create new tableau</li>
<li>Repeat until all coefficients in objective row are non-negative</li>
</ol>
</div>
<!-- Content Block 2 -->
<div class="bg-green-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-green-800 mb-2">Special Cases</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li><strong>Degeneracy:</strong> Minimum ratio test has a tie</li>
<li><strong>Unbounded:</strong> No positive denominators in ratio test</li>
<li><strong>Multiple Solutions:</strong> Zero coefficient in objective row for non-basic variable</li>
<li><strong>Infeasible:</strong> Artificial variable remains in basis</li>
</ul>
</div>
</div>
<!-- Simplex Practice -->
<div class="bg-gray-100 p-4 rounded-lg mb-6">
<h3 class="text-lg font-semibold text-gray-800 mb-3">Simplex Practice</h3>
<div class="mb-4">
<label class="block text-gray-700 mb-1">Initial Tableau:</label>
<div class="overflow-x-auto">
<table id="simplex-tableau" class="w-full border-collapse">
<thead>
<tr>
<th class="border px-4 py-2">Basic</th>
<th class="border px-4 py-2">x₁</th>
<th class="border px-4 py-2">x₂</th>
<th class="border px-4 py-2">s₁</th>
<th class="border px-4 py-2">s₂</th>
<th class="border px-4 py-2">RHS</th>
</tr>
</thead>
<tbody>
<tr>
<td class="border px-4 py-2">s₁</td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="1"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="1"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="1"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="0"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="6"></td>
</tr>
<tr>
<td class="border px-4 py-2">s₂</td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="2"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="1"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="0"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="1"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="8"></td>
</tr>
<tr class="bg-gray-100">
<td class="border px-4 py-2">z</td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="-3"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="-2"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="0"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="0"></td>
<td class="border px-4 py-2"><input type="number" class="w-16 px-2 py-1 border" value="0"></td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="flex flex-wrap gap-2 mb-4">
<button id="next-step" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-forward mr-2"></i> Next Step
</button>
<button id="reset-simplex" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-redo mr-2"></i> Reset
</button>
<button id="hint-simplex" class="bg-yellow-500 hover:bg-yellow-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-question mr-2"></i> Hint
</button>
<button id="auto-solve" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-robot mr-2"></i> Auto Solve
</button>
</div>
<div id="simplex-feedback" class="hidden p-3 bg-white rounded border border-gray-300 mb-4"></div>
<div id="simplex-steps" class="hidden">
<h4 class="font-medium text-gray-700 mb-2">Solution Steps:</h4>
<div class="space-y-2" id="steps-container"></div>
</div>
</div>
<!-- Quick Review -->
<div class="bg-purple-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-purple-800 mb-2">Quick Review</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>Simplex method moves from one basic feasible solution to another</li>
<li>Entering variable has most negative coefficient in objective row</li>
<li>Departing variable is chosen by minimum ratio test</li>
<li>Pivot operation updates the tableau</li>
<li>Process continues until optimality is reached</li>
</ul>
<div class="mt-4">
<button class="mark-complete bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check-circle mr-2"></i> Mark Complete
</button>
</div>
</div>
</div>
<!-- Duality Tab -->
<div id="duality" class="tab-content">
<h2 class="text-2xl font-bold text-gray-800 mb-4">Duality</h2>
<div class="grid md:grid-cols-2 gap-6 mb-6">
<!-- Content Block 1 -->
<div class="bg-blue-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-blue-800 mb-2">Duality Concepts</h3>
<p class="text-gray-700 mb-3">Every LP problem (primal) has a corresponding dual problem:</p>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>Primal maximization becomes dual minimization (and vice versa)</li>
<li>Primal constraints become dual variables</li>
<li>Primal variables become dual constraints</li>
<li>Constraint coefficients become constraint coefficients in transposed form</li>
</ul>
</div>
<!-- Content Block 2 -->
<div class="bg-green-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-green-800 mb-2">Duality Theorems</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li><strong>Weak Duality:</strong> Value of any feasible dual solution ≥ value of any feasible primal solution</li>
<li><strong>Strong Duality:</strong> If one problem has optimal solution, so does the other, with equal objective values</li>
<li><strong>Complementary Slackness:</strong> At optimality, either primal slack or dual variable is zero for each constraint</li>
</ul>
</div>
</div>
<!-- Example Conversion -->
<div class="bg-yellow-50 p-4 rounded-lg mb-6">
<h3 class="text-lg font-semibold text-yellow-800 mb-3">Example: Primal to Dual</h3>
<div class="grid md:grid-cols-2 gap-4 mb-4">
<div>
<h4 class="font-medium text-gray-700 mb-2">Primal Problem:</h4>
<div class="bg-white p-3 rounded border border-gray-200">
<p>Maximize: 3x₁ + 2x₂</p>
<p>Subject to:</p>
<p>x₁ + x₂ ≤ 4</p>
<p>2x₁ + x₂ ≤ 6</p>
<p>x₁ ≥ 0, x₂ ≥ 0</p>
</div>
</div>
<div>
<h4 class="font-medium text-gray-700 mb-2">Dual Problem:</h4>
<div class="bg-white p-3 rounded border border-gray-200">
<p>Minimize: 4y₁ + 6y₂</p>
<p>Subject to:</p>
<p>y₁ + 2y₂ ≥ 3</p>
<p>y₁ + y₂ ≥ 2</p>
<p>y₁ ≥ 0, y₂ ≥ 0</p>
</div>
</div>
</div>
<button id="show-duality-animation" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-play mr-2"></i> Show Conversion Steps
</button>
</div>
<!-- Practice Section -->
<div class="bg-orange-50 p-4 rounded-lg mb-6">
<h3 class="text-lg font-semibold text-orange-800 mb-3">Practice Duality</h3>
<div class="mb-4">
<label class="block text-gray-700 mb-1">Primal Problem:</label>
<textarea id="primal-problem" class="w-full px-3 py-2 border border-gray-300 rounded" rows="4" placeholder="Enter the primal LP problem"></textarea>
</div>
<div class="mb-4">
<label class="block text-gray-700 mb-1">Dual Problem:</label>
<textarea id="dual-problem" class="w-full px-3 py-2 border border-gray-300 rounded" rows="4" placeholder="Enter your dual formulation"></textarea>
</div>
<div class="flex justify-between">
<button id="check-dual" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check mr-2"></i> Check Answer
</button>
<button id="show-dual-solution" class="text-blue-600 hover:text-blue-800 flex items-center">
<i class="fas fa-lightbulb mr-2"></i> Show Solution
</button>
</div>
<div id="dual-feedback" class="hidden mt-4 p-3 rounded"></div>
</div>
<!-- Quick Review -->
<div class="bg-purple-50 p-4 rounded-lg">
<h3 class="text-lg font-semibold text-purple-800 mb-2">Quick Review</h3>
<ul class="list-disc pl-5 text-gray-700 space-y-1">
<li>Dual of a maximization problem is a minimization problem</li>
<li>Number of dual variables = number of primal constraints</li>
<li>Number of dual constraints = number of primal variables</li>
<li>Constraint coefficients are transposed</li>
<li>Weak duality provides bounds, strong duality provides exact equality at optimality</li>
</ul>
<div class="mt-4">
<button class="mark-complete bg-indigo-500 hover:bg-indigo-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check-circle mr-2"></i> Mark Complete
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Flashcards Modal -->
<div id="flashcards-modal" class="modal">
<div class="modal-content">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold text-gray-800">Linear Programming Flashcards</h3>
<button id="close-flashcards" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="bg-white p-4 rounded-lg border border-gray-200 mb-4">
<div id="flashcard-container" class="flex flex-col items-center">
<div class="flashcard w-full h-64 mb-4" id="current-flashcard">
<div class="flashcard-inner">
<div class="flashcard-front bg-indigo-100 flex items-center justify-center">
<p class="text-xl font-medium text-indigo-800" id="flashcard-question">Click to flip</p>
</div>
<div class="flashcard-back">
<p class="text-lg text-gray-700" id="flashcard-answer">Answer will appear here</p>
</div>
</div>
</div>
<div class="flex justify-between w-full">
<button id="prev-flashcard" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded">
<i class="fas fa-arrow-left"></i>
</button>
<span id="flashcard-count" class="text-gray-700">1/10</span>
<button id="next-flashcard" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded">
<i class="fas fa-arrow-right"></i>
</button>
</div>
</div>
</div>
<div class="flex justify-center">
<button id="shuffle-flashcards" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-random mr-2"></i> Shuffle
</button>
</div>
</div>
</div>
<!-- Quiz Modal -->
<div id="quiz-modal" class="modal">
<div class="modal-content">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-bold text-gray-800">Linear Programming Pop Quiz</h3>
<button id="close-quiz" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<div class="bg-white p-4 rounded-lg border border-gray-200 mb-4">
<div id="quiz-container">
<div class="mb-4">
<h4 class="text-lg font-medium text-gray-700 mb-2" id="quiz-question">Question will appear here</h4>
<div class="space-y-2" id="quiz-options">
<!-- Options will be added here -->
</div>
</div>
<div id="quiz-feedback" class="hidden p-3 rounded mb-4"></div>
<div class="flex justify-between">
<button id="prev-question" class="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded">
<i class="fas fa-arrow-left"></i> Previous
</button>
<span id="quiz-count" class="text-gray-700">1/5</span>
<button id="next-question" class="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">
Next <i class="fas fa-arrow-right"></i>
</button>
</div>
</div>
</div>
<div class="flex justify-center">
<button id="submit-quiz" class="bg-green-500 hover:bg-green-600 text-white px-4 py-2 rounded flex items-center">
<i class="fas fa-check-circle mr-2"></i> Submit Quiz
</button>
</div>
</div>
</div>
<script>
// Tab switching functionality
document.querySelectorAll('.tab-btn').forEach(button => {
button.addEventListener('click', () => {
// Remove active class from all buttons and content
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(content => content.classList.remove('active'));
// Add active class to clicked button
button.classList.add('active');
// Show corresponding content
const tabId = button.getAttribute('data-tab');
document.getElementById(tabId).classList.add('active');
});
});
// Formulating Problems Animation
document.getElementById('taco-animation-btn').addEventListener('click', () => {
document.getElementById('taco-animation').classList.remove('hidden');
});
document.getElementById('close-animation').addEventListener('click', () => {
document.getElementById('taco-animation').classList.add('hidden');
});
// Pizza Practice
document.getElementById('check-pizza').addEventListener('click', () => {
const objective = document.getElementById('pizza-objective').value.trim();
const constraints = document.getElementById('pizza-constraints').value.trim();
const feedback = document.getElementById('pizza-feedback');
if (!objective || !constraints) {
feedback.innerHTML = '<div class="bg-red-100 text-red-800 p-3 rounded">Please enter both the objective function and constraints.</div>';
feedback.classList.remove('hidden');
return;
}
// Simple validation (would be more robust in a real implementation)
const expectedObjective = "Maximize 8x + 5y";
const expectedConstraints = [
"1x + 0.2y ≤ 50",
"0.5x + 0.1y ≤ 20",
"15x + 10y ≤ 720",
"x ≥ 0",
"y ≥ 0"
];
let correct = true;
let message = '';
if (!objective.toLowerCase().includes(expectedObjective.toLowerCase())) {
correct = false;
message += '<p>Objective function should be similar to: ' + expectedObjective + '</p>';
}
const constraintLines = constraints.split('\n').map(c => c.trim());
if (constraintLines.length < expectedConstraints.length) {
correct = false;
message += '<p>You seem to be missing some constraints. Expected ' + expectedConstraints.length + ' constraints.</p>';
}
if (correct) {
feedback.innerHTML = '<div class="bg-green-100 text-green-800 p-3 rounded">Correct! Well done.</div>';
addPoints(10);
} else {
feedback.innerHTML = '<div class="bg-yellow-100 text-yellow-800 p-3 rounded">' +
'<p>Almost there! Here are some suggestions:</p>' + message + '</div>';
}
feedback.classList.remove('hidden');
});
document.getElementById('show-pizza-solution').addEventListener('click', () => {
document.getElementById('pizza-objective').value = "Maximize 8x + 5y";
document.getElementById('pizza-constraints').value =
"1x + 0.2y ≤ 50\n" +
"0.5x + 0.1y ≤ 20\n" +
"15x + 10y ≤ 720\n" +
"x ≥ 0\n" +
"y ≥ 0";
});
// Graphical Solutions
// Initialize SVG graph
const svg = document.getElementById('graph');
const svgNS = "http://www.w3.org/2000/svg";
// Draw axes
const xAxis = document.createElementNS(svgNS, 'line');
xAxis.setAttribute('x1', '50');
xAxis.setAttribute('y1', '350');
xAxis.setAttribute('x2', '450');
xAxis.setAttribute('y2', '350');
xAxis.setAttribute('stroke', 'black');
xAxis.setAttribute('stroke-width', '2');
svg.appendChild(xAxis);
const yAxis = document.createElementNS(svgNS, 'line');
yAxis.setAttribute('x1', '50');
yAxis.setAttribute('y1', '350');
yAxis.setAttribute('x2', '50');
yAxis.setAttribute('y2', '50');
yAxis.setAttribute('stroke', 'black');
yAxis.setAttribute('stroke-width', '2');
svg.appendChild(yAxis);
// Add axis labels
const xLabel = document.createElementNS(svgNS, 'text');
xLabel.setAttribute('x', '440');
xLabel.setAttribute('y', '340');
xLabel.setAttribute('font-size', '14');
xLabel.setAttribute('text-anchor', 'end');
xLabel.textContent = 'x';
svg.appendChild(xLabel);
const yLabel = document.createElementNS(svgNS, 'text');
yLabel.setAttribute('x', '60');
yLabel.setAttribute('y', '60');
yLabel.setAttribute('font-size', '14');
yLabel.textContent = 'y';
svg.appendChild(yLabel);
// Add tick marks
for (let i = 1; i <= 8; i++) {
const xTick = document.createElementNS(svgNS, 'line');
xTick.setAttribute('x1', 50 + i * 50);
xTick.setAttribute('y1', '345');
xTick.setAttribute('x2', 50 + i * 50);
xTick.setAttribute('y2', '355');
xTick.setAttribute('stroke', 'black');
xTick.setAttribute('stroke-width', '1');
svg.appendChild(xTick);
const xTickLabel = document.createElementNS(svgNS, 'text');
xTickLabel.setAttribute('x', 50 + i * 50);
xTickLabel.setAttribute('y', '370');
xTickLabel.setAttribute('font-size', '12');
xTickLabel.setAttribute('text-anchor', 'middle');
xTickLabel.textContent = i;
svg.appendChild(xTickLabel);
const yTick = document.createElementNS(svgNS, 'line');
yTick.setAttribute('x1', '45');
yTick.setAttribute('y1', 350 - i * 50);
yTick.setAttribute('x2', '55');
yTick.setAttribute('y2', 350 - i * 50);
yTick.setAttribute('stroke', 'black');
yTick.setAttribute('stroke-width', '1');
svg.appendChild(yTick);
const yTickLabel = document.createElementNS(svgNS, 'text');
yTickLabel.setAttribute('x', '35');
yTickLabel.setAttribute('y', 355 - i * 50);
yTickLabel.setAttribute('font-size', '12');
yTickLabel.setAttribute('text-anchor', 'end');
yTickLabel.textContent = i;
svg.appendChild(yTickLabel);
}
// Store graph elements for later manipulation
const graphElements = {
constraints: [],
feasibleRegion: null,
objectiveLine: null,
optimalPoint: null
};
// Add constraint functionality
document.getElementById('add-constraint').addEventListener('click', () => {
const constraintText = document.getElementById('new-constraint').value.trim();
if (!constraintText) return;
// Add to constraint list
const option = document.createElement('option');
option.textContent = constraintText;
document.getElementById('constraint-list').appendChild(option);
// Clear input
document.getElementById('new-constraint').value = '';
// Plot constraint (simplified for demo)
const parts = constraintText.split(/(<=|>=|=)/);
if (parts.length !== 3) return;
const left = parts[0].trim();
const op = parts[1].trim();
const right = parts[2].trim();
// Parse constraint (very simplified parsing for demo)
let a, b, c;
if (left.includes('x') && left.includes('y')) {
const xyParts = left.split(/x|y/);
a = parseFloat(xyParts[0]) || 1;
b = parseFloat(xyParts[1]) || 1;
} else if (left.includes('x')) {
a = parseFloat(left.replace('x', '')) || 1;
b = 0;
} else if (left.includes('y')) {
a = 0;
b = parseFloat(left.replace('y', '')) || 1;
}
c = parseFloat(right);
// Plot the line ax + by = c
if (a !== 0 && b !== 0) {
// Find two points to draw the line
const x1 = 0, y1 = c / b;
const x2 = c / a, y2 = 0;
const line = document.createElementNS(svgNS, 'line');
line.setAttribute('x1', 50 + x1 * 50);
line.setAttribute('y1', 350 - y1 * 50);
line.setAttribute('x2', 50 + x2 * 50);
line.setAttribute('y2', 350 - y2 * 50);
line.setAttribute('stroke', 'blue');
line.setAttribute('stroke-width', '2');
line.setAttribute('stroke-dasharray', '5,5');
line.classList.add('constraint-line');
svg.appendChild(line);
// Store for later reference
graphElements.constraints.push(line);
}
});
// Find optimal solution (simplified for demo)
document.getElementById('find-optimal').addEventListener('click', () => {
// In a real implementation, this would solve the LP problem
// For demo purposes, we'll just show a point at (4,2)
// Remove previous optimal point if exists
if (graphElements.optimalPoint) {
svg.removeChild(graphElements.optimalPoint);
}
// Add optimal point
const point = document.createElementNS(svgNS, 'circle');
point.setAttribute('cx', '250');
point.setAttribute('cy', '250');
point.setAttribute('r', '6');
point.setAttribute('fill', 'red');
point.setAttribute('stroke', 'darkred');
point.setAttribute('stroke-width', '2');
point.classList.add('optimal-point');
svg.appendChild(point);
graphElements.optimalPoint = point;
// Add label
const label = document.createElementNS(svgNS, 'text');
label.setAttribute('x', '265');
label.setAttribute('y', '255');
label.setAttribute('font-size', '14');
label.textContent = 'Optimal (4,2)';
svg.appendChild(label);
// Store for removal
graphElements.optimalLabel = label;
// Add points for finding the solution
addPoints(15);
});
// Reset graph
document.getElementById('reset-graph').addEventListener('click', () => {
// Remove all constraints
graphElements.constraints.forEach(line => {
svg.removeChild(line);
});
graphElements.constraints = [];
// Remove feasible region if exists
if (graphElements.feasibleRegion) {
svg.removeChild(graphElements.feasibleRegion);
graphElements.feasibleRegion = null;
}
// Remove objective line if exists
if (graphElements.objectiveLine) {
svg.removeChild(graphElements.objectiveLine);
graphElements.objectiveLine = null;
}
// Remove optimal point if exists
if (graphElements.optimalPoint) {
svg.removeChild(graphElements.optimalPoint);
graphElements.optimalPoint = null;
}
if (graphElements.optimalLabel) {
svg.removeChild(graphElements.optimalLabel);
graphElements.optimalLabel = null;
}
// Clear constraint list
document.getElementById('constraint-list').innerHTML = '';
});
// Standard Form Practice
document.getElementById('check-standard').addEventListener('click', () => {
const original = document.getElementById('original-problem').value.trim();
const standard = document.getElementById('standard-form').value.trim();
const feedback = document.getElementById('standard-feedback');
if (!original || !standard) {
feedback.innerHTML = '<div class="bg-red-100 text-red-800 p-3 rounded">Please enter both the original problem and your standard form conversion.</div>';
feedback.classList.remove('hidden');
return;
}
// Simple validation (would be more robust in a real implementation)
if (standard.toLowerCase().includes('slack') || standard.toLowerCase().includes('surplus') ||
standard.toLowerCase().includes('artificial') || standard.toLowerCase().includes('maximize')) {
feedback.innerHTML = '<div class="bg-green-100 text-green-800 p-3 rounded">Good job! Your conversion looks correct.</div>';
addPoints(10);
} else {
feedback.innerHTML = '<div class="bg-yellow-100 text-yellow-800 p-3 rounded">' +
'<p>Check your conversion. Standard form should:</p>' +
'<ul class="list-disc pl-5"><li>Be a maximization problem</li>' +
'<li>Have equality constraints</li>' +
'<li>Include slack/surplus/artificial variables as needed</li></ul></div>';
}
feedback.classList.remove('hidden');
});
document.getElementById('show-standard-solution').addEventListener('click', () => {
document.getElementById('original-problem').value =
"Minimize: -x₁ + 2x₂\n" +
"Subject to:\n" +
"x₁ + x₂ ≤ 6\n" +
"x₁ - x₂ ≥ 2\n" +
"x₁ + 2x₂ = 10\n" +
"x₁ ≥ 0, x₂ unrestricted";
document.getElementById('standard-form').value =
"Maximize: x₁ - 2x₂⁺ + 2x₂⁻\n" +
"Subject to:\n" +
"x₁ + x₂⁺ - x₂⁻ + s₁ = 6\n" +
"x₁ - x₂⁺ + x₂⁻ - s₂ + a₁ = 2\n" +
"x₁ + 2x₂⁺ - 2x₂⁻ + a₂ = 10\n" +
"All variables ≥ 0";
});
// Simplex Method Practice
document.getElementById('next-step').addEventListener('click', () => {
const feedback = document.getElementById('simplex-feedback');
feedback.innerHTML = '<div class="bg-blue-100 text-blue-800 p-3 rounded">Next step: Pivot on x₁ column (most negative in objective row) and s₂ row (minimum ratio test).</div>';
feedback.classList.remove('hidden');
// In a real implementation, this would perform the actual pivot operation
});
document.getElementById('hint-simplex').addEventListener('click', () => {
const feedback = document.getElementById('simplex-feedback');
feedback.innerHTML = '<div class="bg-yellow-100 text-yellow-800 p-3 rounded">Hint: Look for the most negative number in the objective row to choose the entering variable.</div>';
feedback.classList.remove('hidden');
});
document.getElementById('auto-solve').addEventListener('click', () => {
const stepsContainer = document.getElementById('steps-container');
stepsContainer.innerHTML = `
<div class="bg-white p-3 rounded border border-gray-200">
<p class="font-medium">Step 1: Initial Tableau</p>
<p>Entering variable: x₁ (most negative in objective row)</p>
<p>Departing variable: s₂ (minimum ratio test: 6/1=6, 8/2=4)</p>
</div>
<div class="bg-white p-3 rounded border border-gray-200">
<p class="font-medium">Step 2: Pivot Operation</p>
<p>Divide pivot row by 2 to make pivot element 1</p>
<p>Update other rows to zero out x₁ column</p>
</div>
<div class="bg-white p-3 rounded border border-gray-200">
<p class="font-medium">Step 3: Second Tableau</p>
<p>Entering variable: x₂ (most negative in objective row)</p>
<p>Departing variable: s₁ (minimum ratio test)</p>
</div>
<div class="bg-white p-3 rounded border border-gray-200">
<p class="font-medium">Step 4: Final Tableau</p>
<p>All coefficients in objective row are non-negative</p>
<p>Optimal solution: x₁=2, x₂=4, z=14</p>
</div>
`;
document.getElementById('simplex-steps').classList.remove('hidden');
addPoints(20);
});
// Duality Practice
document.getElementById('check-dual').addEventListener('click', () => {
const primal = document.getElementById('primal-problem').value.trim();
const dual = document.getElementById('dual-problem').value.trim();
const feedback = document.getElementById('dual-feedback');
if (!primal || !dual) {
feedback.innerHTML = '<div class="bg-red-100 text-red-800 p-3 rounded">Please enter both the primal problem and your dual formulation.</div>';
feedback.classList.remove('hidden');
return;
}
// Simple validation (would be more robust in a real implementation)
if (dual.toLowerCase().includes('min') && dual.toLowerCase().includes('y') &&
(dual.toLowerCase().includes('≥') || dual.toLowerCase().includes('>='))) {
feedback.innerHTML = '<div class="bg-green-100 text-green-800 p-3 rounded">Correct! Your dual formulation looks good.</div>';
addPoints(10);
} else {
feedback.innerHTML = '<div class="bg-yellow-100 text-yellow-800 p-3 rounded">' +
'<p>Check your dual formulation. Remember:</p>' +
'<ul class="list-disc pl-5"><li>Primal max becomes dual min</li>' +
'<li>Primal constraints become dual variables</li>' +
'<li>Constraint coefficients are transposed</li></ul></div>';
}
feedback.classList.remove('hidden');
});
document.getElementById('show-dual-solution').addEventListener('click', () => {
document.getElementById('primal-problem').value =
"Maximize: 4x₁ + 6x₂\n" +
"Subject to:\n" +
"x₁ + 2x₂ ≤ 3\n" +
"x₁ + x₂ ≤ 2\n" +
"x₁ ≥ 0, x₂ ≥ 0";
document.getElementById('dual-problem').value =
"Minimize: 3y₁ + 2y₂\n" +
"Subject to:\n" +
"y₁ + y₂ ≥ 4\n" +
"2y₁ + y₂ ≥ 6\n" +
"y₁ ≥ 0, y₂ ≥ 0";
});
// Mark Complete buttons
document.querySelectorAll('.mark-complete').forEach(button => {
button.addEventListener('click', function() {
// Update progress
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');
let currentWidth = parseFloat(progressBar.style.width) || 0;
currentWidth += 20; // Each topic is 20%
if (currentWidth > 100) currentWidth = 100;
progressBar.style.width = currentWidth + '%';
progressText.textContent = Math.round(currentWidth) + '% Complete';
// Add points
addPoints(5);
// Show completion message
const parentDiv = this.parentNode.parentNode;
const completeMsg = document.createElement('div');
completeMsg.className = 'bg-green-100 text-green-800 p-2 rounded text-sm mt-2';
completeMsg.innerHTML = '<i class="fas fa-check-circle mr-1"></i> Topic marked as complete!';
parentDiv.appendChild(completeMsg);
// Disable button
this.disabled = true;
this.classList.remove('bg-indigo-500', 'hover:bg-indigo-600');
this.classList.add('bg-gray-400', 'cursor-not-allowed');
});
});
// Flashcards
const flashcards = [
{ question: "What is linear programming?", answer: "A mathematical method for determining the best outcome in a model with linear relationships." },
{ question: "What are the three main components of an LP problem?", answer: "Objective function, decision variables, and constraints." },
{ question: "What is the feasible region?", answer: "The set of all points that satisfy all constraints simultaneously." },
{ question: "What is standard form in LP?", answer: "Maximization problem with equality constraints and non-negative variables." },
{ question: "What is a slack variable?", answer: "A variable added to a ≤ constraint to convert it to an equation." },
{ question: "What is the simplex method?", answer: "An algorithm that moves from one basic feasible solution to another to find the optimal solution." },
{ question: "How do you choose the entering variable in simplex?", answer: "The non-basic variable with the most negative coefficient in the objective row." },
{ question: "What is the minimum ratio test?", answer: "Used to determine the departing variable by finding the smallest non-negative ratio of RHS to pivot column coefficient." },
{ question: "What is duality in LP?", answer: "Every LP problem has a corresponding dual problem with important theoretical relationships." },
{ question: "What does the weak duality theorem state?", answer: "The value of any feasible dual solution is ≥ the value of any feasible primal solution." }
];
let currentFlashcardIndex = 0;
// Open flashcards modal
document.getElementById('flashcards-btn').addEventListener('click', () => {
document.getElementById('flashcards-modal').style.display = 'block';
showFlashcard(currentFlashcardIndex);
});
// Close flashcards modal
document.getElementById('close-flashcards').addEventListener('click', () => {
document.getElementById('flashcards-modal').style.display = 'none';
});
// Show flashcard
function showFlashcard(index) {
const flashcard = document.getElementById('current-flashcard');
flashcard.classList.remove('flipped');
document.getElementById('flashcard-question').textContent = flashcards[index].question;
document.getElementById('flashcard-answer').textContent = flashcards[index].answer;
document.getElementById('flashcard-count').textContent = (index + 1) + '/' + flashcards.length;
}
// Flip flashcard
document.getElementById('current-flashcard').addEventListener('click', function() {
this.classList.toggle('flipped');
});
// Previous flashcard
document.getElementById('prev-flashcard').addEventListener('click', () => {
currentFlashcardIndex = (currentFlashcardIndex - 1 + flashcards.length) % flashcards.length;
showFlashcard(currentFlashcardIndex);
});
// Next flashcard
document.getElementById('next-flashcard').addEventListener('click', () => {
currentFlashcardIndex = (currentFlashcardIndex + 1) % flashcards.length;
showFlashcard(currentFlashcardIndex);
});
// Shuffle flashcards
document.getElementById('shuffle-flashcards').addEventListener('click', () => {
for (let i = flashcards.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[flashcards[i], flashcards[j]] = [flashcards[j], flashcards[i]];
}
currentFlashcardIndex = 0;
showFlashcard(currentFlashcardIndex);
addPoints(5);
});
// Quiz
const quizQuestions = [
{
question: "Which of the following is NOT a requirement for standard form in LP?",
options: [
"Maximization problem",
"Equality constraints",
"Non-negative variables",
"At least three variables"
],
answer: 3
},
{
question: "In the simplex method, how is the entering variable chosen?",
options: [
"Largest coefficient in objective row",
"Most negative coefficient in objective row",
"Random selection",
"Variable with smallest index"
],
answer: 1
},
{
question: "What does the strong duality theorem state?",
options: [
"Primal and dual problems always have the same number of variables",
"If one problem has an optimal solution, so does the other with equal objective values",
"Dual problems are always easier to solve than primal problems",
"All LP problems have multiple optimal solutions"
],
answer: 1
},
{
question: "What is added to convert a ≥ constraint to standard form?",
options: [
"Only a slack variable",
"Only a surplus variable",
"A surplus variable and an artificial variable",
"Only an artificial variable"
],
answer: 2
},
{
question: "Where is the optimal solution found in graphical LP?",
options: [
"At the center of the feasible region",
"At a corner point of the feasible region",
"At the point closest to the origin",
"At the intersection of the first two constraints"
],
answer: 1
}
];
let currentQuizIndex
</html>