Merge pull request #475 from prxnvt:pr/solver-extras
This commit is contained in:
commit
591040ce09
File diff suppressed because it is too large
Load Diff
|
|
@ -2399,9 +2399,13 @@ fn solver(ui: &mut egui::Ui, d: &mut Dialog, confirm: &mut bool, open: &mut bool
|
|||
let method = text(d, "method");
|
||||
ui.horizontal(|ui| {
|
||||
ui.label("Select a Solving Method:");
|
||||
let label = |m: &str| if m == "simplex" { "Simplex LP" } else { "GRG Nonlinear" };
|
||||
let label = |m: &str| match m {
|
||||
"simplex" => "Simplex LP",
|
||||
"evolutionary" => "Evolutionary",
|
||||
_ => "GRG Nonlinear",
|
||||
};
|
||||
egui::ComboBox::from_id_salt("solverMethod").selected_text(label(&method)).show_ui(ui, |ui| {
|
||||
for m in ["grg", "simplex"] {
|
||||
for m in ["grg", "simplex", "evolutionary"] {
|
||||
if ui.selectable_label(method == m, label(m)).clicked() {
|
||||
d.values.insert("method".into(), json!(m));
|
||||
}
|
||||
|
|
@ -2409,10 +2413,10 @@ fn solver(ui: &mut egui::Ui, d: &mut Dialog, confirm: &mut bool, open: &mut bool
|
|||
});
|
||||
});
|
||||
ui.label(
|
||||
egui::RichText::new(if method == "simplex" {
|
||||
"Simplex LP: for linear models; integer and binary constraints by branch and bound."
|
||||
} else {
|
||||
"GRG Nonlinear: a local optimum of a smooth model, from the current values."
|
||||
egui::RichText::new(match method.as_str() {
|
||||
"simplex" => "Simplex LP: for linear models; integer and binary constraints by branch and bound.",
|
||||
"evolutionary" => "Evolutionary: a genetic search for models that aren't smooth; every variable cell needs bounds.",
|
||||
_ => "GRG Nonlinear: a local optimum of a smooth model, from the current values.",
|
||||
})
|
||||
.small(),
|
||||
);
|
||||
|
|
@ -2444,6 +2448,18 @@ fn solver_results(app: &mut SheetApp, ui: &mut egui::Ui, d: &mut Dialog, open: &
|
|||
d.values.insert("restore".into(), json!(true));
|
||||
}
|
||||
}
|
||||
// Reports describe the solution whether it is kept or not.
|
||||
let solved = d.values.get("values").and_then(Json::as_object).is_some_and(|v| !v.is_empty());
|
||||
if solved {
|
||||
ui.add_space(4.0);
|
||||
ui.label("Reports:");
|
||||
for (key, label) in [("answerReport", "Answer"), ("limitsReport", "Limits")] {
|
||||
let mut on = d.values.get(key).and_then(Json::as_bool).unwrap_or(false);
|
||||
if ui.checkbox(&mut on, label).changed() {
|
||||
d.values.insert(key.into(), json!(on));
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut confirm = false;
|
||||
ok_cancel(ui, &mut confirm, open);
|
||||
if confirm {
|
||||
|
|
@ -2451,6 +2467,16 @@ fn solver_results(app: &mut SheetApp, ui: &mut egui::Ui, d: &mut Dialog, open: &
|
|||
if changed && restore {
|
||||
app.run_or_alert("edit.undo", json!({}));
|
||||
}
|
||||
let reports: Vec<&str> = [("answerReport", "answer"), ("limitsReport", "limits")]
|
||||
.into_iter()
|
||||
.filter(|(key, _)| d.values.get(*key).and_then(Json::as_bool) == Some(true))
|
||||
.map(|(_, kind)| kind)
|
||||
.collect();
|
||||
if solved && !reports.is_empty() {
|
||||
let field = |k: &str| d.values.get(k).cloned().unwrap_or(Json::Null);
|
||||
let params = json!({"reports": reports, "model": field("model"), "values": field("values"), "original": field("original"), "message": field("message")});
|
||||
app.run_or_alert("data.solverReport", params);
|
||||
}
|
||||
*open = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -460,6 +460,33 @@ fn solver_dialog_loads_the_saved_model_and_results_can_restore() {
|
|||
assert_eq!(value(&h, "B1"), Value::Number(0.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn solver_results_write_the_chosen_reports() {
|
||||
let mut s = blank();
|
||||
for (c, v) in [("A1", "0"), ("A2", "0"), ("B1", "=3*A1+5*A2"), ("B2", "=2*A2"), ("B3", "=3*A1+2*A2")] {
|
||||
s.execute("cell.set", json!({"cell": c, "input": v})).unwrap();
|
||||
}
|
||||
let r = s
|
||||
.execute(
|
||||
"data.solver",
|
||||
json!({"objective": "B1", "variables": "A1:A2", "constraints": ["A1 <= 4", "B2 <= 12", "B3 <= 18"], "method": "simplex"}),
|
||||
)
|
||||
.unwrap();
|
||||
let mut h = harness(s);
|
||||
// Restore Original Values with the Answer and Limits reports: the cells go back, the reports stay.
|
||||
h.state_mut().open_dialog("solverResults", r);
|
||||
for key in ["restore", "answerReport", "limitsReport"] {
|
||||
h.state_mut().dialog.as_mut().unwrap().values.insert(key.into(), json!(true));
|
||||
}
|
||||
h.run_steps(2);
|
||||
key(&mut h, Key::Enter, Modifiers::NONE);
|
||||
assert!(h.state().dialog.is_none());
|
||||
assert!(h.state().message.is_none(), "{:?}", h.state().message);
|
||||
let names: Vec<String> = h.state().session.active().unwrap().wb.sheets.iter().map(|s| s.name.clone()).collect();
|
||||
assert_eq!(names, ["Answer Report 1", "Limits Report 1", "Sheet1"]);
|
||||
assert_eq!(value(&h, "B1"), Value::Number(0.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn about_renders_every_tab() {
|
||||
let mut h = harness(blank());
|
||||
|
|
|
|||
|
|
@ -105,8 +105,12 @@ No alpha blockers: every core workflow passes the [alpha gate](roadmap.md#alpha-
|
|||
data model (`data.fromWeb`, `data.relationships` missing). **Estimate:** 60–100 h.
|
||||
|
||||
### 13. Analysis tools: Solver, Analysis ToolPak, Forecast Sheet (F)
|
||||
- `data.solver`, `data.analysisToolPak` missing. Forecast Sheet (`data.forecastSheet`) and the
|
||||
FORECAST.ETS family are in; the sheet has no Forecast Start (hindcast) option yet. **Estimate:** 15–25 h.
|
||||
- Solver (`data.solver`, #327) has Simplex LP with integer/binary branch and bound, a local
|
||||
nonlinear method (augmented Lagrangian, not GRG), the Evolutionary method, and Answer and
|
||||
Limits reports; AllDifferent constraints, the Solver Options dialog, the Sensitivity and
|
||||
Population reports and Load/Save Model remain. The Analysis ToolPak
|
||||
(`data.analysisToolPak`) has 13 of 19 tools. Forecast Sheet (`data.forecastSheet`) and the
|
||||
FORECAST.ETS family are in; the sheet has no Forecast Start (hindcast) option yet. **Estimate:** 12–20 h.
|
||||
|
||||
### 14. Page Layout view and print polish (U, F)
|
||||
- Page Layout view landed (#329): paper view with rulers and in-place header/footer editing.
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ performance 8, stability 8, localization 4, hardware 2, platforms 2, ecosystem 2
|
|||
| PivotTables | 7 | ~65% | ~45% | 25–40 | Insert/Recommended, field list, three layouts, date grouping, show-values-as, refresh, calculated fields, XLSX round-trip. Missing: slicers, timelines, calculated items, PivotCharts, value/label filters, number grouping, GETPIVOTDATA, data-model pivots. Round-trip never checked in Excel |
|
||||
| Charts and sparklines | 8 | ~50% | ~30% | 40–60 | 25 chart kinds, all 2-D. The chart model holds title, legend position, a data-labels flag, gridlines flag and axis titles; no axis scaling, trendlines, error bars, per-point formatting, chart sheets, 3-D, surface, map, Pareto. Several kinds don't survive XLSX round trip (open PRs #158, #161). [chart-parity.md](chart-parity.md) |
|
||||
| Page layout, print, PDF | 5 | ~80% | ~55% | 12–20 | Page setup, print titles, breaks, Page Break Preview, headers/footers, PDF export and printing. No true Page Layout view; the PDF writer uses only the 14 standard fonts without embedding (no CJK or other non-Latin text in PDF); web print only exports (#141, #143) |
|
||||
| What-if and analysis | 4 | ~50% | ~40% | 22–35 | Goal Seek, Scenario Manager, data tables, Analysis ToolPak (13 of 19 tools, no charts). Missing: Solver, Forecast Sheet, Analyze Data |
|
||||
| What-if and analysis | 4 | ~50% | ~40% | 22–35 | Goal Seek, Scenario Manager, data tables, Analysis ToolPak (13 of 19 tools, no charts), Solver (Simplex LP, a local nonlinear method and Evolutionary; Answer and Limits reports; no Sensitivity report or options dialog). Missing: Forecast Sheet, Analyze Data |
|
||||
| Get & Transform, external data, data model | 5 | ~15% | ~10% | 60–100 | Import of CSV/TSV, JSON, HTML. No Power Query editor, no From Web, database or folder sources, no connections or refresh, no relationships or data model, no external workbook links (dropped with a warning) |
|
||||
| Insert objects | 3 | ~55% | ~45% | 25–40 | Pictures, 8 shape kinds (Excel has ~170), text boxes, own icon set, ink with Ink to Shape, hyperlinks, checkboxes. Missing: SmartArt, WordArt, equations, signature line, objects, 3-D models, screenshot, pictures in cells (PR #105) |
|
||||
| Review, comments, protection, collaboration | 4 | ~55% | ~40% | 35–55 | Threaded comments, notes, spelling (system dictionary), thesaurus, sheet and workbook protection, Allow Edit Ranges with Excel-compatible password hashes (#307). Missing: comment navigation, Show Changes, notes-to-comments conversion, accessibility checker, co-authoring, opening password-encrypted files (refused with a message since #17) |
|
||||
|
|
|
|||
Loading…
Reference in New Issue