finst version done, no steps tho
This commit is contained in:
256
src/app.rs
Normal file
256
src/app.rs
Normal file
@@ -0,0 +1,256 @@
|
||||
use std::iter::zip;
|
||||
|
||||
use yew::{Component, html};
|
||||
|
||||
use crate::{
|
||||
constraint_input::ConstraintInput, simplex::Simplex, target_input::TargetInput,
|
||||
variable_input::VariableInput,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct App {
|
||||
current_variable: String,
|
||||
target_inputs: Vec<String>,
|
||||
constraint_inputs: Vec<String>,
|
||||
simplex: Simplex,
|
||||
solution: Option<f32>,
|
||||
final_values: Vec<(String, f32)>,
|
||||
}
|
||||
|
||||
pub enum Msg {
|
||||
VariableChange(String),
|
||||
ConstraintChange((String, usize)),
|
||||
TargetChange((String, usize)),
|
||||
AddVariable,
|
||||
ClearVariables,
|
||||
AddConstraint,
|
||||
ClearConstraints,
|
||||
RunSimplex,
|
||||
}
|
||||
|
||||
impl App {}
|
||||
|
||||
impl Default for App {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
current_variable: Default::default(),
|
||||
target_inputs: vec![],
|
||||
constraint_inputs: vec!["".to_string()],
|
||||
simplex: Default::default(),
|
||||
solution: None,
|
||||
final_values: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for App {
|
||||
type Message = Msg;
|
||||
|
||||
type Properties = ();
|
||||
|
||||
fn create(_ctx: &yew::Context<Self>) -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
fn update(&mut self, _ctx: &yew::Context<Self>, msg: Self::Message) -> bool {
|
||||
match msg {
|
||||
Msg::VariableChange(text) => self.current_variable = text,
|
||||
Msg::ConstraintChange((text, i)) => {
|
||||
self.constraint_inputs[i] = text;
|
||||
web_sys::console::log_1(&format!("{:?}", self.constraint_inputs).into());
|
||||
}
|
||||
Msg::TargetChange((text, i)) => self.target_inputs[i] = text,
|
||||
Msg::AddVariable => {
|
||||
if self.current_variable != "".to_string()
|
||||
&& !self
|
||||
.simplex
|
||||
.get_variables()
|
||||
.contains(&self.current_variable)
|
||||
{
|
||||
self.simplex.add_variable(self.current_variable.clone());
|
||||
self.current_variable = "".to_string();
|
||||
for _ in
|
||||
0..(1 + self.simplex.get_variables().len() - self.constraint_inputs.len())
|
||||
{
|
||||
self.constraint_inputs.push("".to_string());
|
||||
}
|
||||
|
||||
for _ in 0..(1 + self.simplex.get_variables().len() - self.target_inputs.len())
|
||||
{
|
||||
self.target_inputs.push("".to_string());
|
||||
}
|
||||
web_sys::console::log_1(&format!("{:?}", self.simplex.get_variables()).into());
|
||||
web_sys::console::log_1(&format!("{:?}", self.constraint_inputs).into());
|
||||
}
|
||||
}
|
||||
Msg::ClearVariables => self.simplex.clear_variables(),
|
||||
Msg::AddConstraint => {
|
||||
let mut constraint = vec![0_f32; self.constraint_inputs.len()];
|
||||
let mut is_ok = true;
|
||||
for (i, input) in self.constraint_inputs.iter().enumerate() {
|
||||
if *input == "".to_string() {
|
||||
constraint[i] = 0_f32;
|
||||
continue;
|
||||
}
|
||||
if let Ok(v) = input.parse::<f32>() {
|
||||
constraint[i] = v;
|
||||
} else {
|
||||
is_ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if is_ok {
|
||||
self.simplex.add_constraint(constraint);
|
||||
}
|
||||
}
|
||||
Msg::ClearConstraints => self.simplex.clear_constraint(), //self.simplex.clear_constraint(),
|
||||
Msg::RunSimplex => {
|
||||
let mut target = vec![0_f32; self.target_inputs.len()];
|
||||
let mut is_ok = true;
|
||||
for (i, input) in self.target_inputs.iter().enumerate() {
|
||||
if *input == "".to_string() {
|
||||
target[i] = 0_f32;
|
||||
continue;
|
||||
}
|
||||
if let Ok(v) = input.parse::<f32>() {
|
||||
target[i] = v;
|
||||
} else {
|
||||
is_ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if is_ok {
|
||||
self.simplex.set_target(target);
|
||||
}
|
||||
|
||||
let (sol, values) = self.simplex.run_simplex();
|
||||
self.solution = Some(sol);
|
||||
self.final_values = values;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn view(&self, ctx: &yew::Context<Self>) -> yew::Html {
|
||||
let on_change_variable = ctx.link().callback(Msg::VariableChange);
|
||||
let on_change_constraint = ctx.link().callback(Msg::ConstraintChange);
|
||||
let on_change_target = ctx.link().callback(Msg::TargetChange);
|
||||
let add_variable = ctx.link().callback(|_| Msg::AddVariable);
|
||||
let clear_variables = ctx.link().callback(|_| Msg::ClearVariables);
|
||||
let clear_constraint = ctx.link().callback(|_| Msg::ClearConstraints);
|
||||
let add_constraint = ctx.link().callback(|_| Msg::AddConstraint);
|
||||
let run_simplex = ctx.link().callback(|_| Msg::RunSimplex);
|
||||
|
||||
html! {
|
||||
<div class="container">
|
||||
|
||||
// <!-- Top: Input Section -->
|
||||
<div class="input-section">
|
||||
|
||||
// <!-- Left: Variables & Constraints -->
|
||||
<div class="input-box">
|
||||
<h2>{"Inputs"}</h2>
|
||||
|
||||
// <!-- Variables -->
|
||||
<div class="sub-section">
|
||||
<h3>{"Variables"}</h3>
|
||||
<div class="input-row">
|
||||
|
||||
<VariableInput {on_change_variable} value={self.current_variable.clone()} placeholder="Enter variable (e.g., x)"/>
|
||||
<button onclick={add_variable}>{"Add"}</button>
|
||||
<button onclick={clear_variables}>{"Clear"}</button>
|
||||
</div>
|
||||
<ul>
|
||||
{
|
||||
for self.simplex.get_variables().iter().map(|v| {
|
||||
html! {
|
||||
<li>{v}</li>
|
||||
}
|
||||
})
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
// <!-- Constraints -->
|
||||
<div class="sub-section">
|
||||
<h3>{"Constraints"}</h3>
|
||||
<div class="input-row">
|
||||
<ConstraintInput {on_change_constraint} variables={self.simplex.get_variables()}/>
|
||||
<button onclick={add_constraint}>{"Add"}</button>
|
||||
<button onclick={clear_constraint}>{"Clear"}</button>
|
||||
</div>
|
||||
<ul>
|
||||
{
|
||||
for self.simplex.get_constraints().iter().map(|c| {
|
||||
html! {
|
||||
<li>{
|
||||
for zip(c, self.simplex.get_variables()).take(c.len() - 1).enumerate().map(|(i, (v, var))| {
|
||||
let v_2 = if i > 0 { v.abs() } else { *v };
|
||||
html! {
|
||||
{ format!("{}{} {} ", if v_2 == 1_f32 { "".to_string() } else {if v_2 == -1_f32 {" -".to_string()} else { format!("{}", v_2) }}, var, {if i < c.len() - 2 {if c[i + 1] < 0_f32 {" - "} else {" + "}} else { " " }} ) }
|
||||
}
|
||||
}
|
||||
)}
|
||||
{
|
||||
format!(" ≤ {}", c[c.len() - 1])
|
||||
}
|
||||
</li>
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="sub-section objective">
|
||||
<div>
|
||||
<h3>{"Target Function"}</h3>
|
||||
<TargetInput {on_change_target} variables={self.simplex.get_variables()}/>
|
||||
</div>
|
||||
<button onclick={run_simplex}>{"Run Simplex"}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
// <!-- Right: Objective Function -->
|
||||
|
||||
</div>
|
||||
|
||||
// <!-- Bottom: Output Section -->
|
||||
<div class="output-section">
|
||||
<div class="steps">
|
||||
<h3>{"Steps"}</h3>
|
||||
<ul>
|
||||
<li>{"Step 1: Initial Tableau"}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="final-result">
|
||||
<h3>{"Solution"}</h3>
|
||||
// {" Final Result: Z = 50 at (x=10, y=5)"}
|
||||
{
|
||||
if let Some(solution) = self.solution {
|
||||
html! {
|
||||
<>
|
||||
{format!("Z = {} at ", solution)}
|
||||
{for self.final_values.iter().map(|(var, val)|{
|
||||
html!{
|
||||
<>
|
||||
{format!("{}={} ", var, val)}
|
||||
</>
|
||||
}
|
||||
})}
|
||||
</>
|
||||
}
|
||||
} else {
|
||||
html!{
|
||||
{"Run the algorithm to find the solution"}
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user