mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
[solver] Add a interval parameter controller for approximate solutions
This commit is contained in:
@@ -6,6 +6,7 @@ app_objs += $(addprefix apps/solver/,\
|
||||
equation_models_parameter_controller.o\
|
||||
equation.o\
|
||||
equation_store.o\
|
||||
interval_controller.o\
|
||||
list_controller.o\
|
||||
solutions_controller.o\
|
||||
)
|
||||
|
||||
@@ -45,6 +45,7 @@ void App::Snapshot::tidy() {
|
||||
App::App(Container * container, Snapshot * snapshot) :
|
||||
ExpressionFieldDelegateApp(container, snapshot, &m_inputViewController),
|
||||
m_solutionsController(&m_alternateEmptyViewController, snapshot->equationStore()),
|
||||
m_intervalController(nullptr, snapshot->equationStore()),
|
||||
m_alternateEmptyViewController(nullptr, &m_solutionsController, &m_solutionsController),
|
||||
m_listController(&m_listFooter, snapshot->equationStore(), &m_listFooter),
|
||||
m_listFooter(&m_stackViewController, &m_listController, &m_listController, ButtonRowController::Position::Bottom, ButtonRowController::Style::EmbossedGrey),
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../shared/expression_field_delegate_app.h"
|
||||
#include "list_controller.h"
|
||||
#include "equation_store.h"
|
||||
#include "interval_controller.h"
|
||||
#include "solutions_controller.h"
|
||||
|
||||
namespace Solver {
|
||||
@@ -30,11 +31,13 @@ public:
|
||||
};
|
||||
InputViewController * inputViewController() { return &m_inputViewController; }
|
||||
ViewController * solutionsControllerStack() { return &m_alternateEmptyViewController; }
|
||||
ViewController * intervalController() { return &m_intervalController; }
|
||||
void willBecomeInactive() override;
|
||||
const char * XNT() override;
|
||||
private:
|
||||
App(Container * container, Snapshot * snapshot);
|
||||
SolutionsController m_solutionsController;
|
||||
IntervalController m_intervalController;
|
||||
AlternateEmptyViewController m_alternateEmptyViewController;
|
||||
ListController m_listController;
|
||||
ButtonRowController m_listFooter;
|
||||
|
||||
@@ -10,3 +10,5 @@ Solution = "Solution"
|
||||
ApproximateSolution = "Solution approchée"
|
||||
NoSolution = "Le systeme n'admet aucune solution"
|
||||
InfiniteNumberOfSolutions = "Le systeme admet une infinite de solutions"
|
||||
ApproximateSolutionIntervalInstruction0= "Entrez l'intervalle dans lequel"
|
||||
ApproximateSolutionIntervalInstruction1= "rechercher une solution approchée."
|
||||
|
||||
@@ -10,3 +10,5 @@ Solution = "Solution"
|
||||
ApproximateSolution = "Solution approchée"
|
||||
NoSolution = "Le systeme n'admet aucune solution"
|
||||
InfiniteNumberOfSolutions = "Le systeme admet une infinite de solutions"
|
||||
ApproximateSolutionIntervalInstruction0= "Entrez l'intervalle dans lequel"
|
||||
ApproximateSolutionIntervalInstruction1= "rechercher une solution approchée."
|
||||
|
||||
@@ -10,3 +10,5 @@ Solution = "Solution"
|
||||
ApproximateSolution = "Solution approchée"
|
||||
NoSolution = "Le systeme n'admet aucune solution"
|
||||
InfiniteNumberOfSolutions = "Le systeme admet une infinite de solutions"
|
||||
ApproximateSolutionIntervalInstruction0= "Entrez l'intervalle dans lequel"
|
||||
ApproximateSolutionIntervalInstruction1= "rechercher une solution approchée."
|
||||
|
||||
@@ -10,3 +10,5 @@ Solution = "Solution"
|
||||
ApproximateSolution = "Solution approchée"
|
||||
NoSolution = "Le systeme n'admet aucune solution"
|
||||
InfiniteNumberOfSolutions = "Le systeme admet une infinite de solutions"
|
||||
ApproximateSolutionIntervalInstruction0= "Entrez l'intervalle dans lequel"
|
||||
ApproximateSolutionIntervalInstruction1= "rechercher une solution approchée."
|
||||
|
||||
@@ -10,3 +10,5 @@ Solution = "Solution"
|
||||
ApproximateSolution = "Solution approchée"
|
||||
NoSolution = "Le systeme n'admet aucune solution"
|
||||
InfiniteNumberOfSolutions = "Le systeme admet une infinite de solutions"
|
||||
ApproximateSolutionIntervalInstruction0= "Entrez l'intervalle dans lequel"
|
||||
ApproximateSolutionIntervalInstruction1= "rechercher une solution approchée."
|
||||
|
||||
@@ -40,6 +40,16 @@ Poincare::ExpressionLayout * EquationStore::exactSolutionLayoutAtIndex(int i, bo
|
||||
}
|
||||
}
|
||||
|
||||
double EquationStore::intervalBound(int index) const {
|
||||
assert(m_type == Type::Monovariable && index >= 0 && index < 2);
|
||||
return m_intervalApproximateSolutions[index];
|
||||
}
|
||||
|
||||
void EquationStore::setIntervalBound(int index, double value) {
|
||||
assert(m_type == Type::Monovariable && index >= 0 && index < 2);
|
||||
m_intervalApproximateSolutions[index] = value;
|
||||
}
|
||||
|
||||
double EquationStore::approximateSolutionAtIndex(int i) {
|
||||
assert(m_type == Type::Monovariable && i >= 0 && i < m_numberOfSolutions);
|
||||
return m_approximateSolutions[i];
|
||||
@@ -101,6 +111,8 @@ EquationStore::Error EquationStore::exactSolve(Poincare::Context * context) {
|
||||
if (degree < 0) {
|
||||
/* 3- Monovariable non-polynomial */
|
||||
m_type = Type::Monovariable;
|
||||
m_intervalApproximateSolutions[0] = -10;
|
||||
m_intervalApproximateSolutions[1] = 10;
|
||||
return Error::RequireApproximateSolution;
|
||||
} else {
|
||||
m_type = Type::PolynomialMonovariable;
|
||||
|
||||
@@ -38,6 +38,8 @@ public:
|
||||
return m_numberOfSolutions;
|
||||
}
|
||||
Poincare::ExpressionLayout * exactSolutionLayoutAtIndex(int i, bool exactLayout);
|
||||
double intervalBound(int index) const;
|
||||
void setIntervalBound(int index, double value);
|
||||
double approximateSolutionAtIndex(int i);
|
||||
void tidy() override;
|
||||
Error exactSolve(Poincare::Context * context);
|
||||
@@ -61,6 +63,7 @@ private:
|
||||
int m_numberOfSolutions;
|
||||
Poincare::ExpressionLayout * m_exactSolutionExactLayouts[k_maxNumberOfApproximateSolutions];
|
||||
Poincare::ExpressionLayout * m_exactSolutionApproximateLayouts[k_maxNumberOfExactSolutions];
|
||||
double m_intervalApproximateSolutions[2];
|
||||
double m_approximateSolutions[k_maxNumberOfApproximateSolutions];
|
||||
};
|
||||
|
||||
|
||||
133
apps/solver/interval_controller.cpp
Normal file
133
apps/solver/interval_controller.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "interval_controller.h"
|
||||
#include "app.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Solver {
|
||||
|
||||
IntervalController::ContentView::ContentView(Responder * parentResponder, SelectableTableView * selectableTableView) :
|
||||
m_instructions0(KDText::FontSize::Small, I18n::Message::ApproximateSolutionIntervalInstruction0, 0.5f, 0.5f, KDColorBlack, Palette::WallScreen),
|
||||
m_instructions1(KDText::FontSize::Small, I18n::Message::ApproximateSolutionIntervalInstruction1, 0.5f, 0.5f, KDColorBlack, Palette::WallScreen),
|
||||
m_selectableTableView(selectableTableView)
|
||||
{
|
||||
}
|
||||
|
||||
void IntervalController::ContentView::drawRect(KDContext * ctx, KDRect rect) const {
|
||||
ctx->fillRect(KDRect(0, 0, bounds().width(), k_topMargin), Palette::WallScreen);
|
||||
}
|
||||
|
||||
int IntervalController::ContentView::numberOfSubviews() const {
|
||||
return 3;
|
||||
}
|
||||
|
||||
View * IntervalController::ContentView::subviewAtIndex(int index) {
|
||||
assert(index >= 0 && index < 5);
|
||||
if (index == 0) {
|
||||
return &m_instructions0;
|
||||
}
|
||||
if (index == 1) {
|
||||
return &m_instructions1;
|
||||
}
|
||||
return m_selectableTableView;
|
||||
}
|
||||
|
||||
void IntervalController::ContentView::layoutSubviews() {
|
||||
KDCoordinate textHeight = KDText::charSize(KDText::FontSize::Small).height();
|
||||
m_instructions0.setFrame(KDRect(0, k_topMargin/2-textHeight, bounds().width(), textHeight));
|
||||
m_instructions1.setFrame(KDRect(0, k_topMargin/2, bounds().width(), textHeight));
|
||||
m_selectableTableView->setFrame(KDRect(0, k_topMargin, bounds().width(), bounds().height()-k_topMargin));
|
||||
}
|
||||
|
||||
/* IntervalController Controller */
|
||||
|
||||
IntervalController::IntervalController(Responder * parentResponder, EquationStore * equationStore) :
|
||||
FloatParameterController(parentResponder),
|
||||
m_selectableTableView(nullptr),
|
||||
m_intervalCell{},
|
||||
m_equationStore(equationStore)
|
||||
{
|
||||
}
|
||||
|
||||
const char * IntervalController::title() {
|
||||
return I18n::translate(I18n::Message::ApproximateSolution);
|
||||
}
|
||||
|
||||
int IntervalController::numberOfRows() {
|
||||
return k_maxNumberOfCells+1;
|
||||
}
|
||||
|
||||
void IntervalController::willDisplayCellForIndex(HighlightCell * cell, int index) {
|
||||
if (index == numberOfRows()-1) {
|
||||
return;
|
||||
}
|
||||
I18n::Message labels[k_maxNumberOfCells] = {I18n::Message::XMin, I18n::Message::XMax};
|
||||
MessageTableCellWithEditableText * myCell = (MessageTableCellWithEditableText *) cell;
|
||||
myCell->setMessage(labels[index]);
|
||||
FloatParameterController::willDisplayCellForIndex(cell, index);
|
||||
}
|
||||
|
||||
HighlightCell * IntervalController::reusableParameterCell(int index, int type) {
|
||||
assert(index >= 0);
|
||||
assert(index < 2);
|
||||
return m_intervalCell[index];
|
||||
}
|
||||
|
||||
int IntervalController::reusableParameterCellCount(int type) {
|
||||
return k_maxNumberOfCells;
|
||||
}
|
||||
|
||||
double IntervalController::parameterAtIndex(int index) {
|
||||
return m_equationStore->intervalBound(index);
|
||||
}
|
||||
|
||||
bool IntervalController::setParameterAtIndex(int parameterIndex, double f) {
|
||||
m_equationStore->setIntervalBound(parameterIndex, f);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IntervalController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
|
||||
if (FloatParameterController::textFieldDidFinishEditing(textField, text, event)) {
|
||||
m_selectableTableView->reloadData();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void IntervalController::buttonAction() {
|
||||
StackViewController * stack = stackController();
|
||||
App * solverApp = static_cast<App *>(app());
|
||||
stack->pop();
|
||||
stack->push(solverApp->solutionsControllerStack(), KDColorWhite, Palette::PurpleBright, Palette::PurpleBright);
|
||||
}
|
||||
|
||||
I18n::Message IntervalController::okButtonText() {
|
||||
return I18n::Message::Resolve;
|
||||
}
|
||||
|
||||
View * IntervalController::loadView() {
|
||||
m_selectableTableView = (SelectableTableView *)FloatParameterController::loadView();
|
||||
m_selectableTableView->setTopMargin(0);
|
||||
for (int i = 0; i < k_maxNumberOfCells; i++) {
|
||||
m_intervalCell[i] = new MessageTableCellWithEditableText(m_selectableTableView, this, m_draftTextBuffer);
|
||||
}
|
||||
ContentView * contentView = (ContentView *)new ContentView(this, m_selectableTableView);
|
||||
return contentView;
|
||||
}
|
||||
|
||||
void IntervalController::unloadView(View * view) {
|
||||
delete m_selectableTableView;
|
||||
m_selectableTableView = nullptr;
|
||||
for (int i = 0; i < k_maxNumberOfCells; i++) {
|
||||
delete m_intervalCell[i];
|
||||
m_intervalCell[i] = nullptr;
|
||||
}
|
||||
FloatParameterController::unloadView(view);
|
||||
}
|
||||
|
||||
SelectableTableView * IntervalController::selectableTableView() {
|
||||
return m_selectableTableView;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
49
apps/solver/interval_controller.h
Normal file
49
apps/solver/interval_controller.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef SOLVER_INTERVAL_CONTROLLER_H
|
||||
#define SOLVER_INTERVAL_CONTROLLER_H
|
||||
|
||||
#include <escher.h>
|
||||
#include "equation_store.h"
|
||||
#include "../shared/float_parameter_controller.h"
|
||||
|
||||
namespace Solver {
|
||||
|
||||
class IntervalController : public Shared::FloatParameterController {
|
||||
public:
|
||||
IntervalController(Responder * parentResponder, EquationStore * equationStore);
|
||||
const char * title() override;
|
||||
int numberOfRows() override;
|
||||
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
|
||||
private:
|
||||
HighlightCell * reusableParameterCell(int index, int type) override;
|
||||
int reusableParameterCellCount(int type) override;
|
||||
void buttonAction() override;
|
||||
double parameterAtIndex(int index) override;
|
||||
bool setParameterAtIndex(int parameterIndex, double f) override;
|
||||
bool textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) override;
|
||||
I18n::Message okButtonText() override;
|
||||
View * loadView() override;
|
||||
void unloadView(View * view) override;
|
||||
class ContentView : public View {
|
||||
public:
|
||||
ContentView(Responder * parentResponder, SelectableTableView * selectableTableView);
|
||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||
private:
|
||||
constexpr static KDCoordinate k_topMargin = 50;
|
||||
int numberOfSubviews() const override;
|
||||
View * subviewAtIndex(int index) override;
|
||||
void layoutSubviews() override;
|
||||
MessageTextView m_instructions0;
|
||||
MessageTextView m_instructions1;
|
||||
SelectableTableView * m_selectableTableView;
|
||||
};
|
||||
SelectableTableView * selectableTableView() override;
|
||||
SelectableTableView * m_selectableTableView;
|
||||
constexpr static int k_maxNumberOfCells = 2;
|
||||
char m_draftTextBuffer[MessageTableCellWithEditableText::k_bufferLength];
|
||||
MessageTableCellWithEditableText * m_intervalCell[k_maxNumberOfCells];
|
||||
EquationStore * m_equationStore;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -150,7 +150,12 @@ void ListController::resolveEquations() {
|
||||
app()->displayWarning(I18n::Message::NonLinearSystem);
|
||||
return;
|
||||
case EquationStore::Error::RequireApproximateSolution:
|
||||
{
|
||||
StackViewController * stack = stackController();
|
||||
App * solverApp = static_cast<App *>(app());
|
||||
stack->push(solverApp->intervalController(), KDColorWhite, Palette::PurpleBright, Palette::PurpleBright);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(e == EquationStore::Error::NoError);
|
||||
|
||||
Reference in New Issue
Block a user