[gnumeric] solver: keep input and target as managed deps.



commit 9b9a7b44d464b965607bc71515bc20786278c93b
Author: Morten Welinder <terra gnome org>
Date:   Sun Nov 1 09:23:21 2009 -0500

    solver: keep input and target as managed deps.

 ChangeLog                        |    7 +
 plugins/lpsolve/lpsolve-write.c  |   12 +-
 plugins/mps/mps.c                |    9 +-
 src/dialogs/dialog-solver.c      |   30 +++--
 src/expr.c                       |   11 ++
 src/expr.h                       |    1 +
 src/sheet.c                      |    6 +-
 src/solver.h                     |   23 ++--
 src/tools/solver/ChangeLog       |    8 +
 src/tools/solver/reports-write.c |    8 +-
 src/tools/solver/reports.c       |    9 +-
 src/tools/solver/solver.c        |  266 ++++++++++++++------------------------
 src/xml-sax-write.c              |   16 ++-
 13 files changed, 185 insertions(+), 221 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 492c22f..41fed47 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2009-11-01  Morten Welinder  <terra gnome org>
+
+	* src/solver.h (struct _SolverParameters): Keep target and input
+	as deps so they get maintained.
+
+	* src/expr.c (gnm_expr_top_get_cellref): New function.
+
 2009-10-31  Morten Welinder  <terra gnome org>
 
 	* src/dependent.c (dependent_managed_init,
diff --git a/plugins/lpsolve/lpsolve-write.c b/plugins/lpsolve/lpsolve-write.c
index a0d6cb9..60858af 100644
--- a/plugins/lpsolve/lpsolve-write.c
+++ b/plugins/lpsolve/lpsolve-write.c
@@ -153,11 +153,12 @@ lpsolve_create_program (Sheet *sheet, GError **err)
 	GString *declarations = g_string_new (NULL);
 	GString *objfunc = g_string_new (NULL);
 	GSList *l;
+	GnmCell *target_cell = gnm_solver_param_get_target_cell (sp);
 
-	/* This is insane -- why do we keep a string?  */
+	/* This is insane  */
 	{
-		GnmValue *vr =
-			value_new_cellrange_str (sheet, sp->input_entry_str);
+		GnmValue const *vr =
+			gnm_expr_top_get_constant (sheet, sp->input.texpr);
 		GnmEvalPos ep;
 
 		g_slist_free (sp->input_cells);
@@ -175,14 +176,13 @@ lpsolve_create_program (Sheet *sheet, GError **err)
 		workbook_foreach_cell_in_range (&ep, vr, CELL_ITER_ALL,
 						cb_grab_cells,
 						&sp->input_cells);
-		value_release (vr);
 	}
 
 	/* ---------------------------------------- */
 
 	switch (sp->problem_type) {
 	case SolverEqualTo:
-		if (!lpsolve_affine_func (constraints, sp->target_cell,
+		if (!lpsolve_affine_func (constraints, target_cell,
 					  sp->input_cells, err))
 			goto fail;
 		/* FIXME -- what value goes here?  */
@@ -198,7 +198,7 @@ lpsolve_create_program (Sheet *sheet, GError **err)
 		g_assert_not_reached ();
 	}
 
-	if (!lpsolve_affine_func (objfunc, sp->target_cell,
+	if (!lpsolve_affine_func (objfunc, target_cell,
 				  sp->input_cells, err))
 		goto fail;
 	g_string_append (objfunc, ";\n");
diff --git a/plugins/mps/mps.c b/plugins/mps/mps.c
index c9033fd..68f8ba8 100644
--- a/plugins/mps/mps.c
+++ b/plugins/mps/mps.c
@@ -437,8 +437,8 @@ mps_write_coefficients (MpsInputContext *ctxt, Sheet *sh,
 	cell_queue_recalc (cell);
 
 	/* Store the input cell range for the Solver dialog. */
-	g_free (param->input_entry_str);
-	param->input_entry_str = g_strdup (range_as_string (&v_range));
+	gnm_solver_param_set_input (param,
+				    value_new_cellrange_r (NULL, &v_range));
 }
 
 /* Creates the spreadsheet model. */
@@ -453,6 +453,7 @@ mps_create_sheet (MpsInputContext *ctxt, WorkbookView *wbv)
 		ctxt->objective_row
 		? ctxt->objective_row->name
 		: "-";
+	GnmCellRef cr;
 
 	n_rows_per_fn = (ctxt->n_cols + MAX_COL - 1) / MAX_COL;
 	mps_prepare (wbv, ctxt);
@@ -477,8 +478,8 @@ mps_create_sheet (MpsInputContext *ctxt, WorkbookView *wbv)
 		}
 	}
 
-	param->target_cell = sheet_cell_fetch (sh, OBJECTIVE_VALUE_COL,
-					       MAIN_INFO_ROW);
+	gnm_cellref_init (&cr, NULL, OBJECTIVE_VALUE_COL, MAIN_INFO_ROW, TRUE);
+	gnm_solver_param_set_target (param, &cr);
 	param->problem_type = SolverMinimize;
 
 	/* Write the name of the program. */
diff --git a/src/dialogs/dialog-solver.c b/src/dialogs/dialog-solver.c
index 027c943..f93b3ff 100644
--- a/src/dialogs/dialog-solver.c
+++ b/src/dialogs/dialog-solver.c
@@ -616,7 +616,8 @@ solver_add_scenario (SolverState *state, SolverResults *res, gchar const *name)
 	input_range = gnm_expr_entry_parse_as_value (state->change_cell_entry,
 						     state->sheet);
 
-	scenario_add_new (name, input_range, param->input_entry_str,
+	scenario_add_new (name, input_range,
+			  value_peek_string (gnm_solver_param_get_input (param)),
 			  comment, state->sheet, &scenario);
 	scenario_add (state->sheet, scenario);
 	if (input_range != NULL)
@@ -647,6 +648,7 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 	SolverParameters        *param;
 	GtkTreeIter iter;
 	gchar const *name;
+	GnmCell *target_cell;
 
 	param = state->sheet->solver_parameters;
 
@@ -667,16 +669,14 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 		return;
 	}
 
-	g_free (param->input_entry_str);
-	param->input_entry_str = value_get_as_string (input_range);
+	gnm_solver_param_set_input (param, value_dup (input_range));
 
-	param->target_cell =
-		sheet_cell_fetch (state->sheet,
-				  target_range->v_range.cell.a.col,
-				  target_range->v_range.cell.a.row );
+	gnm_solver_param_set_target (param,
+				     &target_range->v_range.cell.a);
+	target_cell = gnm_solver_param_get_target_cell (param);
 
 	/* Check that the target cell type is number. */
-	if (! gnm_cell_is_number (param->target_cell)) {
+	if (!target_cell || !gnm_cell_is_number (target_cell)) {
 		go_gtk_notice_nonmodal_dialog
 			((GtkWindow *) state->dialog,
 			 &(state->warning_dialog),
@@ -767,7 +767,7 @@ cb_dialog_solve_clicked (G_GNUC_UNUSED GtkWidget *button,
 		goto out;
 	}
 
-	state->ov_target     = value_get_as_float (param->target_cell->value);
+	state->ov_target     = value_get_as_float (target_cell->value);
 	state->ov            = save_original_values (input_cells);
 	state->ov_stack      = g_slist_prepend (state->ov_stack, state->ov);
 	state->ov_cell_stack = g_slist_prepend (state->ov_cell_stack,
@@ -820,6 +820,8 @@ dialog_init (SolverState *state)
 	GtkTreeViewColumn *column;
 	GList *l = NULL;
 	GSList *cl;
+	GnmCell *target_cell;
+	GnmValue const *input;
 
 	param = state->sheet->solver_parameters;
 
@@ -1087,12 +1089,14 @@ dialog_init (SolverState *state)
 		glade_xml_get_widget(state->gui, "program")),
 			param->options.program_report);
 
-	if (param->input_entry_str != NULL)
+	input = gnm_solver_param_get_input (param);
+	if (input != NULL)
 		gnm_expr_entry_load_from_text (state->change_cell_entry,
-					       param->input_entry_str);
-	if (param->target_cell != NULL)
+					       value_peek_string (input));
+	target_cell = gnm_solver_param_get_target_cell (param);
+	if (target_cell)
 		gnm_expr_entry_load_from_text (state->target_entry,
-				    cell_name(param->target_cell));
+					       cell_name (target_cell));
 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (
 		glade_xml_get_widget(state->gui, "max_button")),
 			param->problem_type == SolverMaximize);
diff --git a/src/expr.c b/src/expr.c
index a990f03..213070f 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -3044,6 +3044,17 @@ gnm_expr_top_get_constant (GnmExprTop const *texpr)
 	return texpr->expr->constant.value;
 }
 
+GnmCellRef *
+gnm_expr_top_get_cellref (GnmExprTop const *texpr)
+{
+	g_return_val_if_fail (IS_GNM_EXPR_TOP (texpr), NULL);
+
+	if (GNM_EXPR_GET_OPER (texpr->expr) != GNM_EXPR_OP_CELLREF)
+		return NULL;
+
+	return &texpr->expr->cellref.ref;
+}
+
 /**
  * gnm_expr_top_first_funcall :
  * @texpr :
diff --git a/src/expr.h b/src/expr.h
index 5952a30..e7782b2 100644
--- a/src/expr.h
+++ b/src/expr.h
@@ -140,6 +140,7 @@ gboolean	gnm_expr_top_is_array		(GnmExprTop const *texpr);
 GnmValue       *gnm_expr_top_get_range		(GnmExprTop const *texpr);
 GSList	       *gnm_expr_top_get_ranges		(GnmExprTop const *texpr);
 GnmValue const *gnm_expr_top_get_constant	(GnmExprTop const *texpr);
+GnmCellRef     *gnm_expr_top_get_cellref	(GnmExprTop const *texpr);
 void		gnm_expr_top_get_boundingbox	(GnmExprTop const *texpr,
 						 Sheet const *sheet,
 						 GnmRange *bound);
diff --git a/src/sheet.c b/src/sheet.c
index 1255851..c867d97 100644
--- a/src/sheet.c
+++ b/src/sheet.c
@@ -755,7 +755,7 @@ gnm_sheet_init (Sheet *sheet)
 	sheet->sheet_objects = NULL;
 	sheet->max_object_extent.col = sheet->max_object_extent.row = 0;
 
-	sheet->solver_parameters = solver_param_new ();
+	sheet->solver_parameters = solver_param_new (sheet);
 
 	sheet->cols.max_used = -1;
 	sheet->cols.info = g_ptr_array_new ();
@@ -4452,7 +4452,6 @@ sheet_insert_cols (Sheet *sheet, int col, int count,
 		colrow_move (sheet, i, 0, i, gnm_sheet_get_last_row (sheet),
 			     &sheet->cols, i, i + count);
 
-	solver_insert_cols (sheet, col, count);
 	scenarios_insert_cols (sheet->scenarios, col, count);
 	sheet_colrow_insert_finish (&reloc_info, TRUE, col, count, pundo);
 
@@ -4551,7 +4550,6 @@ sheet_delete_cols (Sheet *sheet, int col, int count,
 		colrow_move (sheet, i, 0, i, gnm_sheet_get_last_row (sheet),
 			     &sheet->cols, i, i - count);
 
-	solver_delete_cols (sheet, col, count);
 	scenarios_delete_cols (sheet->scenarios, col, count);
 	sheet_colrow_delete_finish (&reloc_info, TRUE, col, count, pundo);
 
@@ -4628,7 +4626,6 @@ sheet_insert_rows (Sheet *sheet, int row, int count,
 		colrow_move (sheet, 0, i, gnm_sheet_get_last_col (sheet), i,
 			     &sheet->rows, i, i + count);
 
-	solver_insert_rows (sheet, row, count);
 	scenarios_insert_rows (sheet->scenarios, row, count);
 	sheet_colrow_insert_finish (&reloc_info, FALSE, row, count, pundo);
 
@@ -4727,7 +4724,6 @@ sheet_delete_rows (Sheet *sheet, int row, int count,
 		colrow_move (sheet, 0, i, gnm_sheet_get_last_col (sheet), i,
 			     &sheet->rows, i, i - count);
 
-	solver_delete_rows (sheet, row, count);
 	scenarios_delete_rows (sheet->scenarios, row, count);
 	sheet_colrow_delete_finish (&reloc_info, FALSE, row, count, pundo);
 
diff --git a/src/solver.h b/src/solver.h
index acb3257..7c4a2b2 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -46,10 +46,11 @@ typedef enum {
 
 struct _SolverParameters {
 	SolverProblemType  problem_type;
-	GnmCell            *target_cell;
+	Sheet             *sheet;
+	GnmDependent       target;
+	GnmDependent       input;
 	GSList		   *input_cells;
 	GSList             *constraints;
-	char               *input_entry_str;
 	int                n_constraints;
 	int                n_variables;
 	int                n_int_constraints;
@@ -242,7 +243,14 @@ gchar *          solver_reports        (WorkbookControl *wbc, Sheet *sheet,
 
 /* Initializes the Solver's data structure containing the parameters.
  * Each sheet can currently have one copy of this data structure. */
-SolverParameters *solver_param_new     (void);
+SolverParameters *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);
+
+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             solver_param_destroy  (SolverParameters *sp);
@@ -255,21 +263,12 @@ SolverParameters *solver_lp_copy       (SolverParameters const *src_param,
 /* Frees the data structure allocated for the results. */
 void             solver_results_free   (SolverResults *res);
 
-/* Returns a pointer to the target cell of the model attached to the
- * given sheet. */
-GnmCell		*solver_get_target_cell (Sheet *sheet);
-
 /* Returns a pointer to a input variable cell. */
 GnmCell		*solver_get_input_var (SolverResults *res, int n);
 
 /* Returns a pointer to a constraint. */
 SolverConstraint* solver_get_constraint (SolverResults *res, int n);
 
-void              solver_insert_cols    (Sheet *sheet, int col, int count);
-void              solver_insert_rows    (Sheet *sheet, int row, int count);
-void              solver_delete_rows    (Sheet *sheet, int row, int count);
-void              solver_delete_cols    (Sheet *sheet, int col, int count);
-
 void              solver_param_read_sax (GsfXMLIn *xin, xmlChar const **attrs);
 
 #else /* !GNM_ENABLE_SOLVER */
diff --git a/src/tools/solver/ChangeLog b/src/tools/solver/ChangeLog
index 117100b..3ac7fdf 100644
--- a/src/tools/solver/ChangeLog
+++ b/src/tools/solver/ChangeLog
@@ -1,3 +1,11 @@
+2009-11-01  Morten Welinder  <terra gnome org>
+
+	* solver.c (gnm_solver_param_get_input,
+	gnm_solver_param_set_input, gnm_solver_param_set_target,
+	gnm_solver_param_get_target): New functions.
+	(solver_insert_rows, solver_insert_cols, solver_delete_rows,
+	solver_delete_cols): Removed -- no longer needed.
+
 2009-10-31  Morten Welinder  <terra gnome org>
 
 	* solver.c (solver_constr_start): Read the new format.
diff --git a/src/tools/solver/reports-write.c b/src/tools/solver/reports-write.c
index cc79e56..90f830b 100644
--- a/src/tools/solver/reports-write.c
+++ b/src/tools/solver/reports-write.c
@@ -82,7 +82,8 @@ solver_answer_report (WorkbookControl *wbc,
 	dao_set_bold (&dao, 0, 6, 4, 6);
 
 	/* Set `Cell' field (cell reference to the target cell). */
-	dao_set_cell (&dao, 1, 7, cell_name (res->param->target_cell));
+	cell = gnm_solver_param_get_target_cell (res->param);
+	dao_set_cell (&dao, 1, 7, cell_name (cell));
 
 	/* Set `Name' field */
 	dao_set_cell (&dao, 2, 7, res->target_name);
@@ -431,14 +432,13 @@ solver_limits_report (WorkbookControl *wbc,
 	 */
 
 	/* Set `Target Cell' field (cell reference to the target cell). */
-	dao_set_cell (&dao, 1, 7, cell_name (res->param->target_cell));
+        cell = gnm_solver_param_get_target_cell (res->param);
+	dao_set_cell (&dao, 1, 7, cell_name (cell));
 
 	/* Set `Target Name' field */
 	dao_set_cell (&dao, 2, 7, res->target_name);
 
 	/* Set `Target Value' field */
-        cell = sheet_cell_get (sheet, res->param->target_cell->pos.col,
-                               res->param->target_cell->pos.row);
         dao_set_cell_float (&dao, 3, 7, res->value_of_obj_fn);
 
 
diff --git a/src/tools/solver/reports.c b/src/tools/solver/reports.c
index 4a01956..a5f847c 100644
--- a/src/tools/solver/reports.c
+++ b/src/tools/solver/reports.c
@@ -149,7 +149,7 @@ static void
 calculate_limits (Sheet *sheet, SolverParameters *param, SolverResults *res)
 {
         int i, n;
-	GnmCell *tcell = solver_get_target_cell (sheet);
+	GnmCell *tcell = gnm_solver_param_get_target_cell (param);
 
 	for (i = 0; i < param->n_total_constraints; i++) {
 	        gnm_float       slack, lhs, rhs, x, y, old_val;
@@ -222,15 +222,14 @@ solver_prepare_reports (SolverProgram *program, SolverResults *res,
 {
 	SolverParameters *param = res->param;
 	const SolverLPAlgorithm *alg;
+	GnmCell const *target_cell;
 
 	if (res->param->options.model_type == SolverLPModel)
 	        alg = &lp_algorithm[param->options.algorithm];
 	else
 	        alg = &qp_algorithm[param->options.algorithm];
 
-        res->target_name = dao_find_name (sheet,
-					  res->param->target_cell->pos.col,
-					  res->param->target_cell->pos.row);
+	target_cell = gnm_solver_param_get_target_cell (res->param);
         get_input_variable_names (res, sheet);
         get_constraint_names (res, sheet);
 
@@ -261,7 +260,7 @@ solver_prepare_reports_success (SolverProgram *program, SolverResults *res,
 	 * Fetch the target cell value from the sheet since it's
 	 * formula may have a constant increment or decrement.
 	 */
-	cell = solver_get_target_cell (sheet);
+	cell = gnm_solver_param_get_target_cell (param);
 	res->value_of_obj_fn = value_get_as_float (cell->value);
 
 	/*
diff --git a/src/tools/solver/solver.c b/src/tools/solver/solver.c
index dce5e0e..41e8181 100644
--- a/src/tools/solver/solver.c
+++ b/src/tools/solver/solver.c
@@ -66,18 +66,20 @@ attr_eq (const xmlChar *a, const char *s)
 
 
 SolverParameters *
-solver_param_new (void)
+solver_param_new (Sheet *sheet)
 {
 	SolverParameters *res = g_new0 (SolverParameters, 1);
 
+	dependent_managed_init (&res->target, sheet);
+	dependent_managed_init (&res->input, sheet);
+
 	res->options.model_type          = SolverLPModel;
+	res->sheet                       = sheet;
 	res->options.assume_non_negative = TRUE;
 	res->options.algorithm           = GLPKSimplex;
 	res->options.scenario_name       = g_strdup ("Optimal");
-	res->input_entry_str             = g_strdup ("");
 	res->problem_type                = SolverMaximize;
 	res->constraints                 = NULL;
-	res->target_cell                 = NULL;
 	res->input_cells		 = NULL;
 	res->constraints		 = NULL;
 
@@ -87,14 +89,59 @@ solver_param_new (void)
 void
 solver_param_destroy (SolverParameters *sp)
 {
+	dependent_managed_set_expr (&sp->target, NULL);
+	dependent_managed_set_expr (&sp->input, NULL);
 	go_slist_free_custom (sp->constraints,
 			      (GFreeFunc)gnm_solver_constraint_free);
 	g_slist_free (sp->input_cells);
-	g_free (sp->input_entry_str);
 	g_free (sp->options.scenario_name);
 	g_free (sp);
 }
 
+GnmValue const *
+gnm_solver_param_get_input (SolverParameters const *sp)
+{
+	return sp->input.texpr
+		? gnm_expr_top_get_constant (sp->input.texpr)
+		: NULL;
+}
+
+void
+gnm_solver_param_set_input (SolverParameters *sp, GnmValue *v)
+{
+	/* Takes ownership.  */
+	GnmExprTop const *texpr = v ? gnm_expr_top_new_constant (v) : NULL;
+	dependent_managed_set_expr (&sp->input, texpr);
+	if (texpr) gnm_expr_top_unref (texpr);
+}
+
+void
+gnm_solver_param_set_target (SolverParameters *sp, GnmCellRef const *cr)
+{
+	GnmExprTop const *texpr = gnm_expr_top_new (gnm_expr_new_cellref (cr));
+	dependent_managed_set_expr (&sp->target, texpr);
+	gnm_expr_top_unref (texpr);
+}
+
+const GnmCellRef *
+gnm_solver_param_get_target (SolverParameters const *sp)
+{
+	return sp->target.texpr
+		? gnm_expr_top_get_cellref (sp->target.texpr)
+		: NULL;
+}
+      
+GnmCell *
+gnm_solver_param_get_target_cell (SolverParameters const *sp)
+{
+	const GnmCellRef *cr = gnm_solver_param_get_target (sp);
+	if (!cr)
+		return NULL;
+
+        return sheet_cell_get (eval_sheet (cr->sheet, sp->sheet),
+			       cr->col, cr->row);
+}
+
 static void
 solver_constr_start (GsfXMLIn *xin, xmlChar const **attrs)
 {
@@ -156,9 +203,9 @@ solver_param_read_sax (GsfXMLIn *xin, xmlChar const **attrs)
 {
 	Sheet *sheet = gnm_xml_in_cur_sheet (xin);
 	SolverParameters *sp = sheet->solver_parameters;
-	int i;
 	int col = -1, row = -1;
 	int ptype;
+	GnmParsePos pp;
 
 	static GsfXMLInNode const dtd[] = {
 	  GSF_XML_IN_NODE (SHEET_SOLVER_CONSTR, SHEET_SOLVER_CONSTR, GNM, "Constr", GSF_XML_NO_CONTENT, &solver_constr_start, NULL),
@@ -166,31 +213,39 @@ solver_param_read_sax (GsfXMLIn *xin, xmlChar const **attrs)
 	};
 	static GsfXMLInDoc *doc;
 
-	for (i = 0; attrs != NULL && attrs[i] && attrs[i + 1] ; i += 2) {
-		if (gnm_xml_attr_int (attrs+i, "ProblemType", &ptype))
+	parse_pos_init_sheet (&pp, sheet);
+
+	for (; attrs && attrs[0] && attrs[1] ; attrs += 2) {
+		if (gnm_xml_attr_int (attrs, "ProblemType", &ptype))
 			sp->problem_type = (SolverProblemType)ptype;
-		else 		if (strcmp (CXML2C (attrs[i]), "Inputs") == 0) {
-			g_free (sp->input_entry_str);
-			sp->input_entry_str = g_strdup (CXML2C (attrs[i+1]));
-		} else if (gnm_xml_attr_int (attrs+i, "TargetCol", &col) ||
-			   gnm_xml_attr_int (attrs+i, "TargetRow", &row) ||
-			   gnm_xml_attr_int (attrs+i, "MaxTime", &(sp->options.max_time_sec)) ||
-			   gnm_xml_attr_int (attrs+i, "MaxIter", &(sp->options.max_iter)) ||
-			   gnm_xml_attr_bool (attrs+i, "NonNeg", &(sp->options.assume_non_negative)) ||
-			   gnm_xml_attr_bool (attrs+i, "Discr", &(sp->options.assume_discrete)) ||
-			   gnm_xml_attr_bool (attrs+i, "AutoScale", &(sp->options.automatic_scaling)) ||
-			   gnm_xml_attr_bool (attrs+i, "ShowIter", &(sp->options.show_iter_results)) ||
-			   gnm_xml_attr_bool (attrs+i, "AnswerR", &(sp->options.answer_report)) ||
-			   gnm_xml_attr_bool (attrs+i, "SensitivityR", &(sp->options.sensitivity_report)) ||
-			   gnm_xml_attr_bool (attrs+i, "LimitsR", &(sp->options.limits_report)) ||
-			   gnm_xml_attr_bool (attrs+i, "PerformR", &(sp->options.performance_report)) ||
-			   gnm_xml_attr_bool (attrs+i, "ProgramR", &(sp->options.program_report)))
+		else if (strcmp (CXML2C (attrs[0]), "Inputs") == 0) {
+			GnmValue *v = value_new_cellrange_parsepos_str
+				(&pp,
+				 CXML2C (attrs[1]),
+				 GNM_EXPR_PARSE_DEFAULT);
+			gnm_solver_param_set_input (sp, v);
+		} else if (gnm_xml_attr_int (attrs, "TargetCol", &col) ||
+			   gnm_xml_attr_int (attrs, "TargetRow", &row) ||
+			   gnm_xml_attr_int (attrs, "MaxTime", &(sp->options.max_time_sec)) ||
+			   gnm_xml_attr_int (attrs, "MaxIter", &(sp->options.max_iter)) ||
+			   gnm_xml_attr_bool (attrs, "NonNeg", &(sp->options.assume_non_negative)) ||
+			   gnm_xml_attr_bool (attrs, "Discr", &(sp->options.assume_discrete)) ||
+			   gnm_xml_attr_bool (attrs, "AutoScale", &(sp->options.automatic_scaling)) ||
+			   gnm_xml_attr_bool (attrs, "ShowIter", &(sp->options.show_iter_results)) ||
+			   gnm_xml_attr_bool (attrs, "AnswerR", &(sp->options.answer_report)) ||
+			   gnm_xml_attr_bool (attrs, "SensitivityR", &(sp->options.sensitivity_report)) ||
+			   gnm_xml_attr_bool (attrs, "LimitsR", &(sp->options.limits_report)) ||
+			   gnm_xml_attr_bool (attrs, "PerformR", &(sp->options.performance_report)) ||
+			   gnm_xml_attr_bool (attrs, "ProgramR", &(sp->options.program_report)))
 			; /* Nothing */
 	}
 
 	if (col >= 0 && col < gnm_sheet_get_max_cols (sheet) &&
-	    row >= 0 && row < gnm_sheet_get_max_rows (sheet))
-		sp->target_cell = sheet_cell_fetch (sheet, col, row);
+	    row >= 0 && row < gnm_sheet_get_max_rows (sheet)) {
+		GnmCellRef cr;
+		gnm_cellref_init (&cr, NULL, col, row, TRUE);
+		gnm_solver_param_set_target (sp, &cr);
+	}
 
 	if (!doc)
 		doc = gsf_xml_in_doc_new (dtd, NULL);
@@ -252,6 +307,9 @@ solver_results_free (SolverResults *res)
 	g_free (res->constraint_names);
 	g_free (res->shadow_prizes);
 	g_free (res->input_cells_array);
+	if (res->constraints_array)
+	        for (i = 0; i < res->n_constraints; i++)
+		        gnm_solver_constraint_free (res->constraints_array[i]);
 	g_free (res->constraints_array);
 	g_free (res->obj_coeff);
 	if (res->constr_coeff != NULL)
@@ -270,14 +328,6 @@ solver_results_free (SolverResults *res)
 /* ------------------------------------------------------------------------- */
 
 GnmCell *
-solver_get_target_cell (Sheet *sheet)
-{
-        return sheet_cell_get (sheet,
-			       sheet->solver_parameters->target_cell->pos.col,
-			       sheet->solver_parameters->target_cell->pos.row);
-}
-
-GnmCell *
 solver_get_input_var (SolverResults *res, int n)
 {
         return res->input_cells_array[n];
@@ -377,7 +427,7 @@ gnm_solver_constraint_get_size (SolverConstraint const *c)
 	if (lhs) {
 		if (VALUE_IS_FLOAT (lhs))
 			return 1;
-		if (lhs->type != VALUE_CELLRANGE) {
+		if (lhs->type == VALUE_CELLRANGE) {
 			range_init_value (&r, lhs);
 			return range_width (&r) * range_height (&r);
 		}
@@ -433,7 +483,7 @@ gnm_solver_constraint_get_part (SolverConstraint const *c, Sheet *sheet, int i,
 	if (lhs) *lhs = NULL;
 	if (rhs) *rhs = NULL;
 
-	if (gnm_solver_constraint_valid (c))
+	if (!gnm_solver_constraint_valid (c))
 		return FALSE;
 
 	vl = gnm_solver_constraint_get_lhs (c);
@@ -480,6 +530,9 @@ gnm_solver_constraint_get_part_val (SolverConstraint const *c,
 	if (lhs) *lhs = NULL;
 	if (rhs) *rhs = NULL;
 
+	if (!gnm_solver_constraint_valid (c))
+		return FALSE;
+
 	vl = gnm_solver_constraint_get_lhs (c);
 	vr = gnm_solver_constraint_get_rhs (c);
 
@@ -637,7 +690,7 @@ save_original_values (SolverResults          *res,
 		++i;
 	}
 
-	cell = solver_get_target_cell (sheet);
+	cell = gnm_solver_param_get_target_cell (param);
 	res->original_value_of_obj_fn = value_get_as_float (cell->value);
 }
 
@@ -702,7 +755,7 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 	program = alg->init_fn (param);
 
 	/* Set up the objective function coefficients. */
-	target = solver_get_target_cell (sheet);
+	target = gnm_solver_param_get_target_cell (param);
 	clear_input_vars (param->n_variables, res);
 
 	gnm_cell_eval (target);
@@ -932,13 +985,13 @@ check_program_definition_failures (Sheet            *sheet,
 	i = 0;
  	for (c = param->constraints; c ; c = c->next) {
 	        SolverConstraint *sc = c->data;
-		int i;
+		int j;
 		GnmValue *lhs, *rhs;
 
-		for (i = 0;
-		     gnm_solver_constraint_get_part_val (sc, sheet, i,
+		for (j = 0;
+		     gnm_solver_constraint_get_part_val (sc, sheet, j,
 							 &lhs, &rhs);
-		     i++) {
+		     j++) {
 			SolverConstraint *nc =
 				gnm_solver_constraint_new (sheet);
 			nc->type = sc->type;
@@ -1057,19 +1110,15 @@ solver (WorkbookControl *wbc, Sheet *sheet, const gchar **errmsg)
 SolverParameters *
 solver_lp_copy (const SolverParameters *src_param, Sheet *new_sheet)
 {
-	SolverParameters *dst_param = solver_param_new ();
+	SolverParameters *dst_param = solver_param_new (new_sheet);
 	GSList           *constraints;
 	GSList           *inputs;
 
-	if (src_param->target_cell != NULL)
-	        dst_param->target_cell =
-		        sheet_cell_fetch (new_sheet,
-					  src_param->target_cell->pos.col,
-					  src_param->target_cell->pos.row);
-
 	dst_param->problem_type = src_param->problem_type;
-	g_free (dst_param->input_entry_str);
-	dst_param->input_entry_str = g_strdup (src_param->input_entry_str);
+	dependent_managed_set_expr (&dst_param->target,
+				    src_param->target.texpr);
+	dependent_managed_set_expr (&dst_param->input,
+				    src_param->input.texpr);
 
 	g_free (dst_param->options.scenario_name);
 	dst_param->options = src_param->options;
@@ -1106,120 +1155,3 @@ solver_lp_copy (const SolverParameters *src_param, Sheet *new_sheet)
 
 	return dst_param;
 }
-
-/*
- * Adjusts the row indices in the Solver's data structures when rows
- * are inserted.
- */
-void
-solver_insert_rows (Sheet *sheet, int row, int count)
-{
-	SolverParameters *param = sheet->solver_parameters;
-        GnmValue *input_range;
-	GnmRange	  range;
-
-	/* Adjust the input range. */
-	input_range = value_new_cellrange_str (sheet, param->input_entry_str);
-	if (input_range != NULL) {
-	        if (input_range->v_range.cell.a.row >= row) {
-		        range.start.col = input_range->v_range.cell.a.col;
-		        range.start.row = input_range->v_range.cell.a.row +
-			        count;
-		        range.end.col   = input_range->v_range.cell.b.col;
-		        range.end.row   = input_range->v_range.cell.b.row +
-			        count;
-			g_free (param->input_entry_str);
-			param->input_entry_str =
-			        g_strdup (global_range_name (sheet, &range));
-		}
-		value_release (input_range);
-	}
-}
-
-/*
- * Adjusts the column indices in the Solver's data structures when columns
- * are inserted.
- */
-void
-solver_insert_cols (Sheet *sheet, int col, int count)
-{
-	SolverParameters *param = sheet->solver_parameters;
-        GnmValue *input_range;
-	GnmRange	  range;
-
-	/* Adjust the input range. */
-	input_range = value_new_cellrange_str (sheet, param->input_entry_str);
-	if (input_range != NULL &&
-	    input_range->v_range.cell.a.col >= col) {
-		range.start.col = input_range->v_range.cell.a.col + count;
-		range.start.row = input_range->v_range.cell.a.row;
-		range.end.col   = input_range->v_range.cell.b.col + count;
-		range.end.row   = input_range->v_range.cell.b.row;
-		g_free (param->input_entry_str);
-		param->input_entry_str = g_strdup (
-			global_range_name (sheet, &range));
-		value_release (input_range);
-	}
-}
-
-/*
- * Adjusts the row indices in the Solver's data structures when rows
- * are deleted.
- */
-void
-solver_delete_rows (Sheet *sheet, int row, int count)
-{
-	SolverParameters *param = sheet->solver_parameters;
-        GnmValue *input_range;
-	GnmRange	  range;
-
-	/* Adjust the input range. */
-	input_range = value_new_cellrange_str (sheet, param->input_entry_str);
-	if (input_range != NULL &&
-	    input_range->v_range.cell.a.row >= row) {
-		range.start.col = input_range->v_range.cell.a.col;
-		range.start.row = input_range->v_range.cell.a.row - count;
-		range.end.col   = input_range->v_range.cell.b.col;
-		range.end.row   = input_range->v_range.cell.b.row - count;
-		g_free (param->input_entry_str);
-		if (range.start.row < row || range.end.row < row)
-			param->input_entry_str = g_strdup ("");
-		else
-			param->input_entry_str = g_strdup (
-				global_range_name (sheet, &range));
-		value_release (input_range);
-	}
-}
-
-/*
- * Adjusts the column indices in the Solver's data structures when columns
- * are deleted.
- */
-void
-solver_delete_cols (Sheet *sheet, int col, int count)
-{
-	SolverParameters *param = sheet->solver_parameters;
-        GnmValue *input_range;
-	GnmRange	  range;
-
-	/* Adjust the input range. */
-	input_range = value_new_cellrange_str (sheet, param->input_entry_str);
-	if (input_range != NULL) {
-	        if (input_range->v_range.cell.a.col >= col) {
-		        range.start.col = input_range->v_range.cell.a.col -
-			        count;
-		        range.start.row = input_range->v_range.cell.a.row;
-		        range.end.col   = input_range->v_range.cell.b.col -
-			        count;
-		        range.end.row   = input_range->v_range.cell.b.row;
-			g_free (param->input_entry_str);
-			if (range.start.col < col || range.end.col < col)
-			        param->input_entry_str = g_strdup ("");
-			else
-			        param->input_entry_str =
-				         g_strdup (global_range_name (sheet,
-								      &range));
-		}
-		value_release (input_range);
-	}
-}
diff --git a/src/xml-sax-write.c b/src/xml-sax-write.c
index 24f8b2c..9a351be 100644
--- a/src/xml-sax-write.c
+++ b/src/xml-sax-write.c
@@ -967,22 +967,28 @@ xml_write_solver (GnmOutputXML *state)
 {
         SolverParameters *param = state->sheet->solver_parameters;
 	GSList *ptr;
+	GnmCellRef const *target;
+	GnmValue const *input;
 
 	if (param == NULL)
 		return;
 
 	gsf_xml_out_start_element (state->output, GNM "Solver");
 
-	if (param->target_cell != NULL) {
+	target = gnm_solver_param_get_target (param);
+	if (target != NULL) {
+		/* FIXME: This drops sheet */
 		gsf_xml_out_add_int (state->output, "TargetCol",
-			param->target_cell->pos.col);
+				     target->col);
 		gsf_xml_out_add_int (state->output, "TargetRow",
-			param->target_cell->pos.row);
+				     target->row);
 	}
 
 	gsf_xml_out_add_int (state->output, "ProblemType", param->problem_type);
-	gsf_xml_out_add_cstr (state->output, "Inputs",
-		param->input_entry_str);
+	input = gnm_solver_param_get_input (param);
+	if (input)
+		gsf_xml_out_add_cstr (state->output, "Inputs",
+				      value_peek_string (input));
 	gsf_xml_out_add_int (state->output, "MaxTime",
 		param->options.max_time_sec);
 	gsf_xml_out_add_int (state->output, "MaxIter",



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