[gnumeric] solver: more cleanups.



commit a44ae99e45047cbf78c5d1c872b52d879208e907
Author: Morten Welinder <terra gnome org>
Date:   Sun Nov 1 22:06:39 2009 -0500

    solver: more cleanups.

 src/dialogs/dialog-solver.c |   20 ++++---
 src/solver.h                |   44 ++++++++-------
 src/tools/solver/solver.c   |  126 +++++++++++++++++++++++++++++++++---------
 3 files changed, 135 insertions(+), 55 deletions(-)
---
diff --git a/src/dialogs/dialog-solver.c b/src/dialogs/dialog-solver.c
index fd39941..50dee76 100644
--- a/src/dialogs/dialog-solver.c
+++ b/src/dialogs/dialog-solver.c
@@ -485,7 +485,7 @@ save_original_values (GSList *input_cells)
 /* Returns FALSE if the reports deleted the current sheet
  * and forced the dialog to die */
 static gboolean
-solver_reporting (SolverState *state, SolverResults *res, gchar const *errmsg)
+solver_reporting (SolverState *state, SolverResults *res)
 {
 	SolverOptions *opt = &res->param->options;
 	gchar         *err = NULL;
@@ -579,7 +579,8 @@ solver_reporting (SolverState *state, SolverResults *res, gchar const *errmsg)
 		go_gtk_notice_nonmodal_dialog
 			((GtkWindow *) state->dialog,
 			 &(state->warning_dialog),
-			 GTK_MESSAGE_ERROR, errmsg);
+			 GTK_MESSAGE_ERROR,
+			 _("Unknown error."));
 		break;
 	}
 	if (NULL != state)
@@ -629,7 +630,7 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 	gint                    i;
 	gboolean                answer, sensitivity, limits, performance;
 	gboolean                program, dual_program;
-	gchar const             *errmsg = _("Unknown error.");
+	GError *err = NULL;
 	SolverParameters        *param;
 	GtkTreeIter iter;
 	gchar const *name;
@@ -755,7 +756,7 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 						input_cells);
 
 
-	res = solver (WORKBOOK_CONTROL (state->wbcg), state->sheet, &errmsg);
+	res = solver (WORKBOOK_CONTROL (state->wbcg), state->sheet, &err);
 	workbook_recalc (state->sheet->workbook);
 
 	if (res != NULL) {
@@ -763,7 +764,7 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 
 		/* WARNING : The dialog may be deleted by the reports
 		 * solver_reporting will return FALSE if state is gone and cleared */
-		if (solver_reporting (state, res, errmsg) &&
+		if (solver_reporting (state, res) &&
 		    res->status == SolverOptimal &&
 		    param->options.add_scenario)
 			solver_add_scenario (state, res,
@@ -771,9 +772,12 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 
 		solver_results_free (res);
 	} else
-		go_gtk_notice_nonmodal_dialog (GTK_WINDOW (state->dialog),
-					  &(state->warning_dialog),
-					  GTK_MESSAGE_ERROR, errmsg);
+		go_gtk_notice_nonmodal_dialog
+			(GTK_WINDOW (state->dialog),
+			 &(state->warning_dialog),
+			 GTK_MESSAGE_ERROR,
+			 err ? err->message : _("Unknown error."));
+
 out:
 	if (target_range != NULL)
 		value_release (target_range);
diff --git a/src/solver.h b/src/solver.h
index d9d4352..006504a 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -12,6 +12,7 @@ G_BEGIN_DECLS
 
 #define SOLVER_MAX_TIME_ERR _("The maximum time exceeded. The optimal value could not be found in given time.")
 
+/* -------------------------------------------------------------------------- */
 
 typedef enum {
 	SolverLPModel, SolverQPModel, SolverNLPModel
@@ -40,6 +41,8 @@ typedef struct {
 	SolverAlgorithmType algorithm;
 } SolverOptions;
 
+/* -------------------------------------------------------------------------- */
+
 typedef enum {
         SolverMinimize, SolverMaximize, SolverEqualTo
 } SolverProblemType;
@@ -58,6 +61,26 @@ struct _SolverParameters {
 	SolverOptions      options;
 };
 
+/* Creates a new SolverParameters object. */
+SolverParameters *gnm_solver_param_new (Sheet *sheet);
+
+/* Duplicate a SolverParameters object. */
+SolverParameters *gnm_solver_param_dup (SolverParameters const *src_param,
+					Sheet *new_sheet);
+
+/* Frees the memory resources in the solver parameter structure. */
+void gnm_solver_param_free (SolverParameters *sp);
+
+GnmValue const *gnm_solver_param_get_input (SolverParameters const *sp);
+void gnm_solver_param_set_input (SolverParameters *sp, GnmValue *v);
+GSList *gnm_solver_param_get_input_cells (SolverParameters const *sp);
+
+const GnmCellRef *gnm_solver_param_get_target (SolverParameters const *sp);
+void gnm_solver_param_set_target (SolverParameters *sp, GnmCellRef const *cr);
+GnmCell *gnm_solver_param_get_target_cell (SolverParameters const *sp);
+
+gboolean gnm_solver_param_valid (SolverParameters const *sp, GError **err);
+
 /* -------------------------------------------------------------------------- */
 
 typedef enum {
@@ -239,7 +262,7 @@ typedef struct {
  * the results of the run.  Note that it should be freed when no longer
  * needed (by calling solver_results_free). */
 SolverResults    *solver               (WorkbookControl *wbc, Sheet *sheet,
-					const gchar **errmsg);
+					GError **err);
 
 /* Creates the Solver's reports. */
 gchar *          solver_reports        (WorkbookControl *wbc, Sheet *sheet,
@@ -248,25 +271,6 @@ gchar *          solver_reports        (WorkbookControl *wbc, Sheet *sheet,
 					gboolean limits, gboolean performance,
 					gboolean program, gboolean dual);
 
-/* Creates a new SolverParameters object. */
-SolverParameters *gnm_solver_param_new (Sheet *sheet);
-
-GnmValue const *gnm_solver_param_get_input (SolverParameters const *sp);
-void gnm_solver_param_set_input (SolverParameters *sp, GnmValue *v);
-GSList *gnm_solver_param_get_input_cells (SolverParameters const *sp);
-
-const GnmCellRef *gnm_solver_param_get_target (SolverParameters const *sp);
-void gnm_solver_param_set_target (SolverParameters *sp, GnmCellRef const *cr);
-GnmCell *gnm_solver_param_get_target_cell (SolverParameters const *sp);
-
-/* Frees the memory resources in the solver parameter structure. */
-void gnm_solver_param_free (SolverParameters *sp);
-
-/* Creates a copy of the Solver's data structures when a sheet is
- * duplicated. */
-SolverParameters *gnm_solver_param_dup (SolverParameters const *src_param,
-					Sheet *new_sheet);
-
 /* Frees the data structure allocated for the results. */
 void             solver_results_free   (SolverResults *res);
 
diff --git a/src/tools/solver/solver.c b/src/tools/solver/solver.c
index 05d8327..6cb5af4 100644
--- a/src/tools/solver/solver.c
+++ b/src/tools/solver/solver.c
@@ -179,6 +179,71 @@ gnm_solver_param_get_target_cell (SolverParameters const *sp)
 			       cr->col, cr->row);
 }
 
+gboolean
+gnm_solver_param_valid (SolverParameters const *sp, GError **err)
+{
+	GSList *l;
+	int i;
+	GnmCell *target_cell;
+	GSList *input_cells;
+
+	target_cell = gnm_solver_param_get_target_cell (sp);
+	if (!target_cell) {
+		g_set_error (err,
+			     go_error_invalid (),
+			     0,
+			     _("Invalid solver target"));
+		return FALSE;
+	}
+
+	if (!gnm_cell_has_expr (target_cell)) {
+		g_set_error (err,
+			     go_error_invalid (),
+			     0,
+			     _("Target cell, %s, must contain a formula"),
+			     cell_name (target_cell));
+		return FALSE;
+	}
+
+	if (!gnm_solver_param_get_input (sp)) {
+		g_set_error (err,
+			     go_error_invalid (),
+			     0,
+			     _("Invalid solver input range"));
+		return FALSE;
+	}
+	input_cells = gnm_solver_param_get_input_cells (sp);
+	for (l = input_cells; l; l = l->next) {
+		GnmCell *cell = l->data;
+		if (gnm_cell_has_expr (cell)) {
+			g_set_error (err,
+				     go_error_invalid (),
+				     0,
+				     _("Input cell %s contains a formula"),
+				     cell_name (cell));
+			g_slist_free (input_cells);
+			return FALSE;
+		}
+	}
+	g_slist_free (input_cells);
+
+	for (i = 1, l = sp->constraints; l; i++, l = l->next) {
+		SolverConstraint *c = l->data;
+		if (!gnm_solver_constraint_valid (c)) {
+			g_set_error (err,
+				     go_error_invalid (),
+				     0,
+				     _("Solver constraint #%d is invalid"),
+				     i);
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+/* ------------------------------------------------------------------------- */
+
 static void
 solver_constr_start (GsfXMLIn *xin, xmlChar const **attrs)
 {
@@ -787,7 +852,7 @@ clear_input_vars (int n_variables, SolverResults *res)
 static SolverProgram
 lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 		   SolverResults *res, const SolverLPAlgorithm *alg,
-		   gnm_float start_time, GTimeVal start, const gchar **errmsg)
+		   gnm_float start_time, GTimeVal start, GError **err)
 {
         SolverProgram     program;
 	GnmCell          *target;
@@ -813,12 +878,6 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 				res->obj_coeff[i] = x;
 			}
 		}
-		/* Check that the target cell contains a formula. */
-		if (! res->n_nonzeros_in_obj) {
-		        *errmsg = _("Target cell should contain a formula.");
-			solver_results_free (res);
-			return NULL;
-		}
 	} else {
 	        /* FIXME: Init qp */
 	}
@@ -842,9 +901,10 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 
 		/* Check that LHS is a number type. */
 		if (lval == NULL || !VALUE_IS_NUMBER (lval)) {
-			*errmsg = _("The LHS cells should contain formulas "
-				    "that yield proper numerical values.  "
-				    "Specify valid LHS entries.");
+			g_set_error (err, go_error_invalid (), 0,
+				     _("The LHS cells should contain formulas "
+				       "that yield proper numerical values.  "
+				       "Specify valid LHS entries."));
 			solver_results_free (res);
 			return NULL;
 		}
@@ -887,9 +947,10 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 
 		/* Check that RHS is a number type. */
 		if (rval == NULL || !VALUE_IS_NUMBER (rval)) {
-			*errmsg = _("The RHS cells should contain proper "
-				    "numerical values only.  Specify valid "
-				    "RHS entries.");
+			g_set_error (err, go_error_invalid (), 0,
+				     _("The RHS cells should contain proper "
+				       "numerical values only.  Specify valid "
+				       "RHS entries."));
 			solver_results_free (res);
 			return NULL;
 		}
@@ -904,7 +965,8 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 		g_get_current_time (&cur_time);
 		if (cur_time.tv_sec - start.tv_sec >
 		    param->options.max_time_sec) {
-			*errmsg = SOLVER_MAX_TIME_ERR;
+			g_set_error (err, go_error_invalid (), 0,
+				     SOLVER_MAX_TIME_ERR);
 			solver_results_free (res);
 			return NULL;
 		}
@@ -920,7 +982,9 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 	        alg->maxim_fn (program);
 	        break;
 	case SolverEqualTo:
-		*errmsg = _("EqualTo models are not supported yet.  Please use Min or Max");
+		g_set_error (err, go_error_invalid (), 0,
+			     _("EqualTo models are not supported yet.  "
+			       "Please use Min or Max"));
 		solver_results_free (res);
 	        return NULL; /* FIXME: Equal to feature not yet implemented. */
 	default:
@@ -933,19 +997,22 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 	if (alg->set_option_fn (program, SolverOptAutomaticScaling,
 				&(param->options.automatic_scaling),
 				NULL, NULL)) {
-		*errmsg = _("Failure setting automatic scaling with this solver, try a different algorithm.");
+		g_set_error (err, go_error_invalid (), 0,
+			     _("Failure setting automatic scaling with this solver, try a different algorithm."));
 		solver_results_free (res);
 	        return NULL;
 	}
 	if (alg->set_option_fn (program, SolverOptMaxIter, NULL, NULL,
 				&(param->options.max_iter))) {
-		*errmsg = _("Failure setting the maximum number of iterations with this solver, try a different algorithm.");
+		g_set_error (err, go_error_invalid (), 0,
+			     _("Failure setting the maximum number of iterations with this solver, try a different algorithm."));
 		solver_results_free (res);
 	        return NULL;
 	}
 	if (alg->set_option_fn (program, SolverOptMaxTimeSec, NULL, &start_time,
 				&(param->options.max_time_sec))) {
-		*errmsg = _("Failure setting the maximum solving time with this solver, try a different algorithm.");
+		g_set_error (err, go_error_invalid (), 0,
+			     _("Failure setting the maximum solving time with this solver, try a different algorithm."));
 		solver_results_free (res);
 	        return NULL;
 	}
@@ -970,7 +1037,7 @@ static gboolean
 check_program_definition_failures (Sheet            *sheet,
 				   SolverParameters *param,
 				   SolverResults    **res,
-				   const gchar      **errmsg)
+				   GError **err)
 {
 	GSList           *inputs;
 	GSList           *c;
@@ -993,9 +1060,10 @@ check_program_definition_failures (Sheet            *sheet,
 		/* Check that the cell contains a number or is empty. */
 		if (! (cell->value == NULL || VALUE_IS_EMPTY (cell->value)
 		       || VALUE_IS_NUMBER (cell->value))) {
-		        *errmsg = _("Some of the input cells contain "
-				    "non-numeric values.  Specify a valid "
-				    "input range.");
+			g_set_error (err, go_error_invalid (), 0,
+				     _("Some of the input cells contain "
+				       "non-numeric values.  Specify a valid "
+				       "input range."));
 			g_slist_free (input_cells);
 			return TRUE;
 		}
@@ -1064,7 +1132,7 @@ check_program_definition_failures (Sheet            *sheet,
 
 static SolverResults *
 solver_run (WorkbookControl *wbc, Sheet *sheet,
-	    const SolverLPAlgorithm *alg, const gchar **errmsg)
+	    const SolverLPAlgorithm *alg, GError **err)
 {
 	SolverParameters  *param = sheet->solver_parameters;
 	SolverProgram     program;
@@ -1078,7 +1146,11 @@ solver_run (WorkbookControl *wbc, Sheet *sheet,
 #endif
 
 	g_get_current_time (&start);
-	if (check_program_definition_failures (sheet, param, &res, errmsg))
+
+	if (!gnm_solver_param_valid (param, err))
+		return NULL;
+
+	if (check_program_definition_failures (sheet, param, &res, err))
 	        return NULL;
 
 #if defined(HAVE_TIMES) && defined(HAVE_SYSCONF)
@@ -1095,7 +1167,7 @@ solver_run (WorkbookControl *wbc, Sheet *sheet,
 
 	program              = lp_qp_solver_init (sheet, param, res, alg,
 						  -res->time_real, start,
-						  errmsg);
+						  err);
 	if (program == NULL)
 	        return NULL;
 
@@ -1129,7 +1201,7 @@ solver_run (WorkbookControl *wbc, Sheet *sheet,
 }
 
 SolverResults *
-solver (WorkbookControl *wbc, Sheet *sheet, const gchar **errmsg)
+solver (WorkbookControl *wbc, Sheet *sheet, GError **err)
 {
 	const SolverLPAlgorithm *alg = NULL;
 	SolverParameters  *param = sheet->solver_parameters;
@@ -1148,7 +1220,7 @@ solver (WorkbookControl *wbc, Sheet *sheet, const gchar **errmsg)
 		g_assert_not_reached ();
 	}
 
-	return solver_run (wbc, sheet, alg, errmsg);
+	return solver_run (wbc, sheet, alg, err);
 }
 
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]