48
48
class Solver::Private
55
Solver::Solver( QObject* parent, const QStringList& args )
56
: KParts::Plugin( parent ),
55
Solver::Solver(QObject* parent, const QStringList& args)
56
: KParts::Plugin(parent),
62
d->view = qobject_cast<View*>( parent );
65
kError() << "Solver: Parent object is not a KSpread::View! Quitting." << endl;
69
QAction* solver = actionCollection()->addAction("kspreadsolver");
70
solver->setText(i18n("Function Optimizer..."));
71
connect( solver, SIGNAL( triggered(bool) ), this, SLOT( showDialog() ) );
62
d->view = qobject_cast<View*>(parent);
64
kError() << "Solver: Parent object is not a KSpread::View! Quitting." << endl;
68
QAction* solver = actionCollection()->addAction("kspreadsolver");
69
solver->setText(i18n("Function Optimizer..."));
70
connect(solver, SIGNAL(triggered(bool)), this, SLOT(showDialog()));
79
78
void Solver::showDialog()
81
d->dialog = new SolverDialog( d->view->selection(), d->view );
82
connect( d->dialog, SIGNAL( okClicked() ), this, SLOT( optimize() ) );
80
d->dialog = new SolverDialog(d->view->selection(), d->view);
81
connect(d->dialog, SIGNAL(okClicked()), this, SLOT(optimize()));
86
85
void Solver::optimize()
88
register Sheet * const sheet = d->view->activeSheet();
92
if (d->dialog->function->textEdit()->toPlainText().isEmpty())
95
if (d->dialog->parameters->textEdit()->toPlainText().isEmpty())
98
Region region(d->dialog->function->textEdit()->toPlainText(), d->view->doc()->map(), d->view->activeSheet());
99
if (!region.isValid())
102
const QPoint point = (*region.constBegin())->rect().topLeft();
103
const Cell formulaCell = Cell( sheet, point.x(), point.y() );
104
if (!formulaCell.isFormula())
107
kDebug() << formulaCell.userInput();
108
s_formula = new Formula( sheet );
109
if (d->dialog->minimizeButton->isChecked())
111
s_formula->setExpression( formulaCell.userInput() );
113
else if (d->dialog->maximizeButton->isChecked())
115
// invert the formula
116
s_formula->setExpression( "=-(" + formulaCell.userInput().mid(1) + ')' );
118
else // if (d->dialog->valueButton->isChecked())
121
s_formula->setExpression( "=ABS(" + formulaCell.userInput().mid(1) + '-'
122
+ d->dialog->value->text() + ')' );
125
// Determine the parameters
127
Parameters* parameters = new Parameters;
128
region = Region(d->dialog->parameters->textEdit()->toPlainText(), d->view->doc()->map(), d->view->activeSheet());
129
Region::ConstIterator end( region.constEnd() );
130
for ( Region::ConstIterator it( region.constBegin() ); it != end; ++it )
132
QRect range = (*it)->rect();
133
for ( int col = range.left(); col <= range.right(); ++col )
135
for ( int row = range.top(); row <= range.bottom(); ++row )
137
parameters->cells.append( Cell( sheet, col, row ) );
143
/* Initial vertex size vector with a step size of 1 */
144
gsl_vector* stepSizes = gsl_vector_alloc( dimension );
145
gsl_vector_set_all(stepSizes, 1.0);
147
/* Initialize starting point */
149
gsl_vector* x = gsl_vector_alloc( dimension );
150
foreach (Cell cell, parameters->cells)
152
gsl_vector_set( x, index++, numToDouble(cell.value().asFloat()) );
155
/* Initialize method and iterate */
156
gsl_multimin_function functionInfo;
157
functionInfo.f = &function;
158
functionInfo.n = dimension;
159
functionInfo.params = static_cast<void*>( parameters );
161
// Use the simplex minimizer. The others depend on the first derivative.
162
const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
163
gsl_multimin_fminimizer* minimizer = gsl_multimin_fminimizer_alloc( T, dimension );
164
gsl_multimin_fminimizer_set( minimizer, &functionInfo, x, stepSizes );
168
const int maxIterations = d->dialog->iterations->value();
170
const double epsilon = d->dialog->precision->value();
174
status = gsl_multimin_fminimizer_iterate( minimizer );
179
size = gsl_multimin_fminimizer_size( minimizer );
180
status = gsl_multimin_test_size( size, epsilon );
182
if ( status == GSL_SUCCESS )
184
kDebug() <<"converged to minimum after" << iteration <<" iteration(s) at";
187
for ( int i = 0; i < dimension; ++i )
189
printf( "%10.3e ", gsl_vector_get( minimizer->x, i ) );
191
printf( "f() = %7.3f size = %.3f\n", minimizer->fval, size );
193
while ( status == GSL_CONTINUE && iteration < maxIterations );
196
// free allocated memory
198
gsl_vector_free(stepSizes);
199
gsl_multimin_fminimizer_free(minimizer);
87
register Sheet * const sheet = d->view->activeSheet();
91
if (d->dialog->function->textEdit()->toPlainText().isEmpty())
94
if (d->dialog->parameters->textEdit()->toPlainText().isEmpty())
97
Region region(d->dialog->function->textEdit()->toPlainText(), d->view->doc()->map(), d->view->activeSheet());
98
if (!region.isValid())
101
const QPoint point = (*region.constBegin())->rect().topLeft();
102
const Cell formulaCell = Cell(sheet, point.x(), point.y());
103
if (!formulaCell.isFormula())
106
kDebug() << formulaCell.userInput();
107
s_formula = new Formula(sheet);
108
if (d->dialog->minimizeButton->isChecked()) {
109
s_formula->setExpression(formulaCell.userInput());
110
} else if (d->dialog->maximizeButton->isChecked()) {
111
// invert the formula
112
s_formula->setExpression("=-(" + formulaCell.userInput().mid(1) + ')');
113
} else { // if (d->dialog->valueButton->isChecked())
115
s_formula->setExpression("=ABS(" + formulaCell.userInput().mid(1) + '-'
116
+ d->dialog->value->text() + ')');
119
// Determine the parameters
121
Parameters* parameters = new Parameters;
122
region = Region(d->dialog->parameters->textEdit()->toPlainText(), d->view->doc()->map(), d->view->activeSheet());
123
Region::ConstIterator end(region.constEnd());
124
for (Region::ConstIterator it(region.constBegin()); it != end; ++it) {
125
QRect range = (*it)->rect();
126
for (int col = range.left(); col <= range.right(); ++col) {
127
for (int row = range.top(); row <= range.bottom(); ++row) {
128
parameters->cells.append(Cell(sheet, col, row));
134
/* Initial vertex size vector with a step size of 1 */
135
gsl_vector* stepSizes = gsl_vector_alloc(dimension);
136
gsl_vector_set_all(stepSizes, 1.0);
138
/* Initialize starting point */
140
gsl_vector* x = gsl_vector_alloc(dimension);
141
foreach(Cell cell, parameters->cells) {
142
gsl_vector_set(x, index++, numToDouble(cell.value().asFloat()));
145
/* Initialize method and iterate */
146
gsl_multimin_function functionInfo;
147
functionInfo.f = &function;
148
functionInfo.n = dimension;
149
functionInfo.params = static_cast<void*>(parameters);
151
// Use the simplex minimizer. The others depend on the first derivative.
152
const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
153
gsl_multimin_fminimizer* minimizer = gsl_multimin_fminimizer_alloc(T, dimension);
154
gsl_multimin_fminimizer_set(minimizer, &functionInfo, x, stepSizes);
158
const int maxIterations = d->dialog->iterations->value();
160
const double epsilon = d->dialog->precision->value();
163
status = gsl_multimin_fminimizer_iterate(minimizer);
168
size = gsl_multimin_fminimizer_size(minimizer);
169
status = gsl_multimin_test_size(size, epsilon);
171
if (status == GSL_SUCCESS) {
172
kDebug() << "converged to minimum after" << iteration << " iteration(s) at";
175
for (int i = 0; i < dimension; ++i) {
176
printf("%10.3e ", gsl_vector_get(minimizer->x, i));
178
printf("f() = %7.3f size = %.3f\n", minimizer->fval, size);
179
} while (status == GSL_CONTINUE && iteration < maxIterations);
182
// free allocated memory
184
gsl_vector_free(stepSizes);
185
gsl_multimin_fminimizer_free(minimizer);
204
190
double Solver::evaluate(const gsl_vector* vector, void *parameters)
211
197
double function(const gsl_vector* vector, void *params)
213
Solver::Parameters* parameters = static_cast<Solver::Parameters*>( params );
215
for ( int i = 0; i < parameters->cells.count(); ++i )
217
parameters->cells[i].setValue( KSpread::Value( gsl_vector_get(vector, i) ) );
220
// TODO check for errors/correct type
221
return numToDouble(s_formula->eval().asFloat());
199
Solver::Parameters* parameters = static_cast<Solver::Parameters*>(params);
201
for (int i = 0; i < parameters->cells.count(); ++i) {
202
parameters->cells[i].setValue(KSpread::Value(gsl_vector_get(vector, i)));
205
// TODO check for errors/correct type
206
return numToDouble(s_formula->eval().asFloat());
224
209
#include "Solver.moc"