~ubuntu-branches/ubuntu/precise/koffice/precise

« back to all changes in this revision

Viewing changes to kspread/plugins/solver/Solver.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2010-09-21 15:36:35 UTC
  • mfrom: (1.4.1 upstream) (60.2.11 maverick)
  • Revision ID: james.westby@ubuntu.com-20100921153635-6tejqkiro2u21ydi
Tags: 1:2.2.2-0ubuntu3
Add kubuntu_03_fix-crash-on-closing-sqlite-connection-2.2.2.diff and
kubuntu_04_support-large-memo-values-for-msaccess-2.2.2.diff as
recommended by upstream http://kexi-
project.org/wiki/wikiview/index.php@Kexi2.2_Patches.html#sqlite_stab
ility

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
 
39
39
// make the plugin available
40
40
typedef KGenericFactory<KSpread::Plugins::Solver> SolverFactory;
41
 
K_EXPORT_COMPONENT_FACTORY( libkspreadsolver, SolverFactory("kspreadsolver") )
 
41
K_EXPORT_COMPONENT_FACTORY(libkspreadsolver, SolverFactory("kspreadsolver"))
42
42
 
43
43
KSpread::View* s_view = 0;
44
44
KSpread::Formula* s_formula = 0;
48
48
class Solver::Private
49
49
{
50
50
public:
51
 
  SolverDialog* dialog;
52
 
  View* view;
 
51
    SolverDialog* dialog;
 
52
    View* view;
53
53
};
54
54
 
55
 
Solver::Solver( QObject* parent, const QStringList& args )
56
 
  : KParts::Plugin( parent ),
57
 
    d( new Private )
 
55
Solver::Solver(QObject* parent, const QStringList& args)
 
56
        : KParts::Plugin(parent),
 
57
        d(new Private)
58
58
{
59
 
  Q_UNUSED(args)
60
 
 
61
 
  d->dialog = 0;
62
 
  d->view = qobject_cast<View*>( parent );
63
 
  if ( !d->view )
64
 
  {
65
 
    kError() << "Solver: Parent object is not a KSpread::View! Quitting." << endl;
66
 
    return;
67
 
  }
68
 
 
69
 
  QAction* solver = actionCollection()->addAction("kspreadsolver");
70
 
  solver->setText(i18n("Function Optimizer..."));
71
 
  connect( solver, SIGNAL( triggered(bool) ), this, SLOT( showDialog() ) );
 
59
    Q_UNUSED(args)
 
60
 
 
61
    d->dialog = 0;
 
62
    d->view = qobject_cast<View*>(parent);
 
63
    if (!d->view) {
 
64
        kError() << "Solver: Parent object is not a KSpread::View! Quitting." << endl;
 
65
        return;
 
66
    }
 
67
 
 
68
    QAction* solver = actionCollection()->addAction("kspreadsolver");
 
69
    solver->setText(i18n("Function Optimizer..."));
 
70
    connect(solver, SIGNAL(triggered(bool)), this, SLOT(showDialog()));
72
71
}
73
72
 
74
73
Solver::~Solver()
75
74
{
76
 
  delete d;
 
75
    delete d;
77
76
}
78
77
 
79
78
void Solver::showDialog()
80
79
{
81
 
  d->dialog = new SolverDialog( d->view->selection(), d->view );
82
 
  connect( d->dialog, SIGNAL( okClicked() ), this, SLOT( optimize() ) );
83
 
  d->dialog->show();
 
80
    d->dialog = new SolverDialog(d->view->selection(), d->view);
 
81
    connect(d->dialog, SIGNAL(okClicked()), this, SLOT(optimize()));
 
82
    d->dialog->show();
84
83
}
85
84
 
86
85
void Solver::optimize()
87
86
{
88
 
  register Sheet * const sheet = d->view->activeSheet();
89
 
  if ( !sheet )
90
 
    return;
91
 
 
92
 
  if (d->dialog->function->textEdit()->toPlainText().isEmpty())
93
 
    return;
94
 
 
95
 
  if (d->dialog->parameters->textEdit()->toPlainText().isEmpty())
96
 
    return;
97
 
 
98
 
  Region region(d->dialog->function->textEdit()->toPlainText(), d->view->doc()->map(), d->view->activeSheet());
99
 
  if (!region.isValid())
100
 
    return;
101
 
 
102
 
  const QPoint point = (*region.constBegin())->rect().topLeft();
103
 
  const Cell formulaCell = Cell( sheet, point.x(), point.y() );
104
 
  if (!formulaCell.isFormula())
105
 
    return;
106
 
 
107
 
  kDebug() << formulaCell.userInput();
108
 
  s_formula = new Formula( sheet );
109
 
  if (d->dialog->minimizeButton->isChecked())
110
 
  {
111
 
    s_formula->setExpression( formulaCell.userInput() );
112
 
  }
113
 
  else if (d->dialog->maximizeButton->isChecked())
114
 
  {
115
 
    // invert the formula
116
 
    s_formula->setExpression( "=-(" + formulaCell.userInput().mid(1) + ')' );
117
 
  }
118
 
  else // if (d->dialog->valueButton->isChecked())
119
 
  {
120
 
    // TODO
121
 
    s_formula->setExpression( "=ABS(" + formulaCell.userInput().mid(1) + '-'
122
 
                                      + d->dialog->value->text() + ')' );
123
 
  }
124
 
 
125
 
  // Determine the parameters
126
 
  int dimension = 0;
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 )
131
 
  {
132
 
    QRect range = (*it)->rect();
133
 
    for ( int col = range.left(); col <= range.right(); ++col )
134
 
    {
135
 
      for ( int row = range.top(); row <= range.bottom(); ++row )
136
 
      {
137
 
        parameters->cells.append( Cell( sheet, col, row ) );
138
 
        ++dimension;
139
 
      }
140
 
    }
141
 
  }
142
 
 
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);
146
 
 
147
 
  /* Initialize starting point */
148
 
  int index = 0;
149
 
  gsl_vector* x = gsl_vector_alloc( dimension );
150
 
  foreach (Cell cell, parameters->cells)
151
 
  {
152
 
    gsl_vector_set( x, index++, numToDouble(cell.value().asFloat()) );
153
 
  }
154
 
 
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 );
160
 
 
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 );
165
 
 
166
 
  int status = 0;
167
 
  int iteration = 0;
168
 
  const int maxIterations = d->dialog->iterations->value();
169
 
  double size = 1;
170
 
  const double epsilon = d->dialog->precision->value();
171
 
  do
172
 
  {
173
 
    iteration++;
174
 
    status = gsl_multimin_fminimizer_iterate( minimizer );
175
 
 
176
 
    if ( status )
177
 
      break;
178
 
 
179
 
    size = gsl_multimin_fminimizer_size( minimizer );
180
 
    status = gsl_multimin_test_size( size, epsilon );
181
 
 
182
 
    if ( status == GSL_SUCCESS )
183
 
    {
184
 
      kDebug() <<"converged to minimum after" << iteration <<" iteration(s) at";
185
 
    }
186
 
 
187
 
    for ( int i = 0; i < dimension; ++i )
188
 
    {
189
 
      printf( "%10.3e ", gsl_vector_get( minimizer->x, i ) );
190
 
    }
191
 
    printf( "f() = %7.3f size = %.3f\n", minimizer->fval, size );
192
 
  }
193
 
  while ( status == GSL_CONTINUE && iteration < maxIterations );
194
 
 
195
 
 
196
 
  // free allocated memory
197
 
  gsl_vector_free(x);
198
 
  gsl_vector_free(stepSizes);
199
 
  gsl_multimin_fminimizer_free(minimizer);
200
 
  delete parameters;
201
 
  delete s_formula;
 
87
    register Sheet * const sheet = d->view->activeSheet();
 
88
    if (!sheet)
 
89
        return;
 
90
 
 
91
    if (d->dialog->function->textEdit()->toPlainText().isEmpty())
 
92
        return;
 
93
 
 
94
    if (d->dialog->parameters->textEdit()->toPlainText().isEmpty())
 
95
        return;
 
96
 
 
97
    Region region(d->dialog->function->textEdit()->toPlainText(), d->view->doc()->map(), d->view->activeSheet());
 
98
    if (!region.isValid())
 
99
        return;
 
100
 
 
101
    const QPoint point = (*region.constBegin())->rect().topLeft();
 
102
    const Cell formulaCell = Cell(sheet, point.x(), point.y());
 
103
    if (!formulaCell.isFormula())
 
104
        return;
 
105
 
 
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())
 
114
        // TODO
 
115
        s_formula->setExpression("=ABS(" + formulaCell.userInput().mid(1) + '-'
 
116
                                 + d->dialog->value->text() + ')');
 
117
    }
 
118
 
 
119
    // Determine the parameters
 
120
    int dimension = 0;
 
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));
 
129
                ++dimension;
 
130
            }
 
131
        }
 
132
    }
 
133
 
 
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);
 
137
 
 
138
    /* Initialize starting point */
 
139
    int index = 0;
 
140
    gsl_vector* x = gsl_vector_alloc(dimension);
 
141
    foreach(Cell cell, parameters->cells) {
 
142
        gsl_vector_set(x, index++, numToDouble(cell.value().asFloat()));
 
143
    }
 
144
 
 
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);
 
150
 
 
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);
 
155
 
 
156
    int status = 0;
 
157
    int iteration = 0;
 
158
    const int maxIterations = d->dialog->iterations->value();
 
159
    double size = 1;
 
160
    const double epsilon = d->dialog->precision->value();
 
161
    do {
 
162
        iteration++;
 
163
        status = gsl_multimin_fminimizer_iterate(minimizer);
 
164
 
 
165
        if (status)
 
166
            break;
 
167
 
 
168
        size = gsl_multimin_fminimizer_size(minimizer);
 
169
        status = gsl_multimin_test_size(size, epsilon);
 
170
 
 
171
        if (status == GSL_SUCCESS) {
 
172
            kDebug() << "converged to minimum after" << iteration << " iteration(s) at";
 
173
        }
 
174
 
 
175
        for (int i = 0; i < dimension; ++i) {
 
176
            printf("%10.3e ", gsl_vector_get(minimizer->x, i));
 
177
        }
 
178
        printf("f() = %7.3f size = %.3f\n", minimizer->fval, size);
 
179
    } while (status == GSL_CONTINUE && iteration < maxIterations);
 
180
 
 
181
 
 
182
    // free allocated memory
 
183
    gsl_vector_free(x);
 
184
    gsl_vector_free(stepSizes);
 
185
    gsl_multimin_fminimizer_free(minimizer);
 
186
    delete parameters;
 
187
    delete s_formula;
202
188
}
203
189
 
204
190
double Solver::evaluate(const gsl_vector* vector, void *parameters)
205
191
{
206
 
  Q_UNUSED(vector)
207
 
  Q_UNUSED(parameters)
208
 
  return 0.0;
 
192
    Q_UNUSED(vector)
 
193
    Q_UNUSED(parameters)
 
194
    return 0.0;
209
195
}
210
196
 
211
197
double function(const gsl_vector* vector, void *params)
212
198
{
213
 
  Solver::Parameters* parameters = static_cast<Solver::Parameters*>( params );
214
 
 
215
 
  for ( int i = 0; i < parameters->cells.count(); ++i )
216
 
  {
217
 
    parameters->cells[i].setValue( KSpread::Value( gsl_vector_get(vector, i) ) );
218
 
  }
219
 
 
220
 
  // TODO check for errors/correct type
221
 
  return numToDouble(s_formula->eval().asFloat());
 
199
    Solver::Parameters* parameters = static_cast<Solver::Parameters*>(params);
 
200
 
 
201
    for (int i = 0; i < parameters->cells.count(); ++i) {
 
202
        parameters->cells[i].setValue(KSpread::Value(gsl_vector_get(vector, i)));
 
203
    }
 
204
 
 
205
    // TODO check for errors/correct type
 
206
    return numToDouble(s_formula->eval().asFloat());
222
207
}
223
208
 
224
209
#include "Solver.moc"