[gnumeric] solver: turn solver constraints into deps.



commit b6c18f9b8257c869e70bc8c43258680ef719df5c
Author: Morten Welinder <terra gnome org>
Date:   Sat Oct 31 00:58:08 2009 -0400

    solver: turn solver constraints into deps.

 plugins/mps/mps.c                |    2 +-
 src/dependent.c                  |   40 +++++++
 src/dependent.h                  |    9 ++
 src/dialogs/dialog-solver.c      |   56 +++++++---
 src/solver.h                     |   21 ++--
 src/tools/solver/reports-write.c |    2 +-
 src/tools/solver/solver.c        |  230 +++++++++++++++++++++----------------
 src/xml-sax-write.c              |    5 +-
 8 files changed, 237 insertions(+), 128 deletions(-)
---
diff --git a/plugins/mps/mps.c b/plugins/mps/mps.c
index 2564136..c9033fd 100644
--- a/plugins/mps/mps.c
+++ b/plugins/mps/mps.c
@@ -397,7 +397,7 @@ mps_write_coefficients (MpsInputContext *ctxt, Sheet *sh,
 		  cell_queue_recalc (cell);
 
 		  /* Add Solver constraint */
-		  c = g_new0 (SolverConstraint, 1);
+		  c = gnm_solver_constraint_new (sh);
 		  gnm_solver_constraint_set_old (c, type_map[row->type],
 						 ecol + 1, r,
 						 ecol + 3, r,
diff --git a/src/dependent.c b/src/dependent.c
index 02913ba..d6bb8a2 100644
--- a/src/dependent.c
+++ b/src/dependent.c
@@ -244,6 +244,8 @@ static void dynamic_dep_eval	   (GnmDependent *dep);
 static void dynamic_dep_debug_name (GnmDependent const *dep, GString *target);
 static void name_dep_eval	   (GnmDependent *dep);
 static void name_dep_debug_name	   (GnmDependent const *dep, GString *target);
+static void managed_dep_eval	   (GnmDependent *dep);
+static void managed_dep_debug_name (GnmDependent const *dep, GString *target);
 
 static GnmCellPos const dummy = { 0, 0 };
 static GPtrArray *dep_classes = NULL;
@@ -257,6 +259,11 @@ static GnmDependentClass name_dep_class = {
 	NULL,
 	name_dep_debug_name,
 };
+static GnmDependentClass managed_dep_class = {
+	managed_dep_eval,
+	NULL,
+	managed_dep_debug_name,
+};
 typedef struct {
 	GnmDependent  base;
 	GnmDependent *container;
@@ -275,6 +282,7 @@ dependent_types_init (void)
 	g_ptr_array_add	(dep_classes, NULL); /* Cell */
 	g_ptr_array_add	(dep_classes, &dynamic_dep_class);
 	g_ptr_array_add	(dep_classes, &name_dep_class);
+	g_ptr_array_add	(dep_classes, &managed_dep_class);
 
 #if USE_POOLS
 	micro_few_pool =
@@ -1233,6 +1241,36 @@ workbook_unlink_3d_dep (GnmDependent *dep)
 
 /*****************************************************************************/
 
+void
+dependent_managed_init (GnmManagedDependent *dep, Sheet *sheet)
+{
+	memset (dep, 0, sizeof (dep));
+	dep->base.flags = DEPENDENT_MANAGED;
+	dep->base.sheet = sheet;
+}
+
+void
+dependent_managed_set_expr (GnmManagedDependent *dep,
+			    GnmExprTop const *texpr)
+{
+	dependent_set_expr (&dep->base, texpr);
+	if (texpr && dep->base.sheet)
+		dependent_link (&dep->base);
+}
+
+static void
+managed_dep_eval (G_GNUC_UNUSED GnmDependent *dep)
+{
+}
+
+static void
+managed_dep_debug_name (GnmDependent const *dep, GString *target)
+{
+	g_string_append_printf (target, "Managed%p", (void *)dep);
+}
+
+/*****************************************************************************/
+
 static void
 name_dep_eval (G_GNUC_UNUSED GnmDependent *dep)
 {
@@ -1244,6 +1282,8 @@ name_dep_debug_name (GnmDependent const *dep, GString *target)
 	g_string_append_printf (target, "Name%p", (void *)dep);
 }
 
+/*****************************************************************************/
+
 static void
 dynamic_dep_eval (G_GNUC_UNUSED GnmDependent *dep)
 {
diff --git a/src/dependent.h b/src/dependent.h
index 15df750..1bfee5f 100644
--- a/src/dependent.h
+++ b/src/dependent.h
@@ -29,6 +29,7 @@ typedef enum {
 	DEPENDENT_CELL		   = 0x00000001,	/* builtin type */
 	DEPENDENT_DYNAMIC_DEP	   = 0x00000002,	/* builtin type */
 	DEPENDENT_NAME		   = 0x00000003,	/* builtin pseudo type */
+	DEPENDENT_MANAGED	   = 0x00000004,	/* builtin type */
 	DEPENDENT_TYPE_MASK	   = 0x00000fff,
 
 	/* Linked into the workbook wide expression list */
@@ -112,6 +113,14 @@ void		 gnm_dep_container_dump	(GnmDepContainer const *deps,
 void             gnm_dep_container_sanity_check (GnmDepContainer const *deps);
 void             gnm_dep_container_resize (GnmDepContainer *deps, int rows);
 
+typedef struct {
+	GnmDependent base;
+} GnmManagedDependent;
+
+void     dependent_managed_init (GnmManagedDependent *dep, Sheet *sheet);
+void     dependent_managed_set_expr (GnmManagedDependent *dep,
+				     GnmExprTop const *texpr);
+
 #define DEPENDENT_CONTAINER_FOREACH_DEPENDENT(dc, dep, code)	\
   do {								\
 	GnmDependent *dep = (dc)->head;				\
diff --git a/src/dialogs/dialog-solver.c b/src/dialogs/dialog-solver.c
index c14f94a..a1084fc 100644
--- a/src/dialogs/dialog-solver.c
+++ b/src/dialogs/dialog-solver.c
@@ -121,17 +121,19 @@ static GList *qp_alg_name_list = NULL;
 static void
 constraint_fill (SolverConstraint *c, SolverState *state)
 {
+	Sheet *sheet = state->sheet;
+
 	c->type = gtk_combo_box_get_active (state->type_combo);
 
-	value_release (c->lhs);
-	c->lhs = gnm_expr_entry_parse_as_value (state->lhs.entry,
-						state->sheet);
+	gnm_solver_constraint_set_lhs
+		(c,
+		 gnm_expr_entry_parse_as_value (state->lhs.entry, sheet));
 
-	value_release (c->rhs);
-	c->rhs = gnm_solver_constraint_has_rhs (c)
-		?  gnm_expr_entry_parse_as_value (state->rhs.entry,
-						  state->sheet)
-		: NULL;
+	gnm_solver_constraint_set_rhs
+		(c,
+		 gnm_solver_constraint_has_rhs (c)
+		 ? gnm_expr_entry_parse_as_value (state->rhs.entry, sheet)
+		 : NULL);
 }
 
 static gboolean
@@ -139,7 +141,7 @@ dialog_set_sec_button_sensitivity (G_GNUC_UNUSED GtkWidget *dummy,
 				   SolverState *state)
 {
 	gboolean select_ready = (state->constr != NULL);
-	SolverConstraint *test = g_new0 (SolverConstraint, 1);
+	SolverConstraint *test = gnm_solver_constraint_new (NULL);
 	gboolean ready, has_rhs;
 
 	constraint_fill (test, state);
@@ -164,6 +166,7 @@ constraint_select_click (GtkTreeSelection *Selection,
 	GtkTreeModel *store;
 	GtkTreeIter iter;
 	SolverConstraint const *c;
+	GnmValue const *lhs, *rhs;
 
 	if (gtk_tree_selection_get_selected (Selection, &store, &iter))
 		gtk_tree_model_get (store, &iter, 1, &state->constr, -1);
@@ -175,9 +178,10 @@ constraint_select_click (GtkTreeSelection *Selection,
 		return; /* Fail? */
 	c = state->constr;
 
-	if (c->lhs) {
+	lhs = gnm_solver_constraint_get_lhs (c);
+	if (lhs) {
 		GnmExprTop const *texpr =
-			gnm_expr_top_new_constant (value_dup (c->lhs));
+			gnm_expr_top_new_constant (value_dup (lhs));
 		GnmParsePos pp;
 
 		gnm_expr_entry_load_from_expr
@@ -188,9 +192,10 @@ constraint_select_click (GtkTreeSelection *Selection,
 	} else
 		gnm_expr_entry_load_from_text (state->lhs.entry, "");
 
-	if (c->rhs && gnm_solver_constraint_has_rhs (c)) {
+	rhs = gnm_solver_constraint_get_rhs (c);
+	if (rhs && gnm_solver_constraint_has_rhs (c)) {
 		GnmExprTop const *texpr =
-			gnm_expr_top_new_constant (value_dup (c->rhs));
+			gnm_expr_top_new_constant (value_dup (rhs));
 		GnmParsePos pp;
 
 		gnm_expr_entry_load_from_expr
@@ -239,7 +244,7 @@ constraint_fill_row (SolverState *state, GtkListStore *store, GtkTreeIter *iter)
 
 	constraint_fill (c, state);
 
-	text = gnm_solver_constraint_as_str (c);
+	text = gnm_solver_constraint_as_str (c, state->sheet);
 	gtk_list_store_set (store, iter, 0, text, 1, c, -1);
 	g_free (text);
 	gtk_tree_selection_select_iter (gtk_tree_view_get_selection (state->constraint_list), iter);
@@ -254,7 +259,7 @@ cb_dialog_add_clicked (SolverState *state)
 		SolverParameters *param = state->sheet->solver_parameters;
 
 		gtk_list_store_append (store, &iter);
-		state->constr = g_new0 (SolverConstraint, 1);
+		state->constr = gnm_solver_constraint_new (state->sheet);
 		constraint_fill_row (state, store, &iter);
 		param->constraints =
 			g_slist_append (param->constraints, state->constr);
@@ -452,10 +457,12 @@ check_int_constraints (GnmValue *input_range, SolverState *state)
 				continue;
 			}
 
+#if 0
 			if (!global_range_contained (state->sheet,
 						     a_constraint->lhs,
 						     input_range))
 				return text;
+#endif
 
 			g_free (text);
 		} while (gtk_tree_model_iter_next (store, &iter));
@@ -1023,6 +1030,23 @@ dialog_init (SolverState *state)
 	gtk_tree_view_column_set_expand (column, TRUE);
 	gtk_tree_view_append_column (state->constraint_list, column);
 
+	{
+		GtkWidget *w = GTK_WIDGET (state->constraint_list);
+		int width, height, vsep;
+		PangoLayout *layout =
+			gtk_widget_create_pango_layout (w, "Mg19");
+
+		gtk_widget_style_get (w,
+				      "vertical_separator", &vsep,
+				      NULL);
+
+		pango_layout_get_pixel_size (layout, &width, &height);
+		gtk_widget_set_size_request (w,
+					     -1,
+					     (2 * height + vsep) * (4 + 1));
+		g_object_unref (layout);
+	}
+
 /* Loading the old solver specs... from param  */
 
 	for (cl = param->constraints; cl; cl = cl->next) {
@@ -1031,7 +1055,7 @@ dialog_init (SolverState *state)
 		char *str;
 
 		gtk_list_store_append (store, &iter);
-		str = gnm_solver_constraint_as_str (c);
+		str = gnm_solver_constraint_as_str (c, state->sheet);
 		gtk_list_store_set (store, &iter, 0, str, 1, c, -1);
 		g_free (str);
 	}
diff --git a/src/solver.h b/src/solver.h
index d8de90e..49a98ed 100644
--- a/src/solver.h
+++ b/src/solver.h
@@ -4,6 +4,7 @@
 
 #include "gnumeric.h"
 #include "numbers.h"
+#include "dependent.h"
 #include <gsf/gsf-libxml.h>
 
 
@@ -69,16 +70,16 @@ typedef struct {
 	SolverConstraintType type;
 
 	/* Must be a range.  */
-	GnmValue *lhs;
+	GnmManagedDependent lhs;
 
 	/* Must be a constant or a range.  */
-	GnmValue *rhs;
+	GnmManagedDependent rhs;
 } SolverConstraint;
 
 #ifdef GNM_ENABLE_SOLVER
 
+SolverConstraint *gnm_solver_constraint_new (Sheet *sheet);
 void gnm_solver_constraint_free (SolverConstraint *c);
-SolverConstraint *gnm_solver_constraint_dup (SolverConstraint *c);
 
 void gnm_solver_constraint_set_old (SolverConstraint *c,
 				    SolverConstraintType type,
@@ -93,12 +94,16 @@ gboolean gnm_solver_constraint_get_part (SolverConstraint const *c,
 					 GnmCell **lhs, gnm_float *cl,
 					 GnmCell **rhs, gnm_float *cr);
 
-GnmValue *gnm_solver_constraint_get_lhs (SolverConstraint const *c,
-					 Sheet *sheet);
-GnmValue *gnm_solver_constraint_get_rhs (SolverConstraint const *c,
-					 Sheet *sheet);
+GnmValue const *gnm_solver_constraint_get_lhs (SolverConstraint const *c);
+GnmValue const *gnm_solver_constraint_get_rhs (SolverConstraint const *c);
 
-char *gnm_solver_constraint_as_str (SolverConstraint const *c);
+void gnm_solver_constraint_set_lhs (SolverConstraint *c, GnmValue *v);
+void gnm_solver_constraint_set_rhs (SolverConstraint *c, GnmValue *v);
+
+void gnm_solver_constraint_side_as_str (SolverConstraint const *c,
+					Sheet const *sheet,
+					GString *buf, gboolean lhs);
+char *gnm_solver_constraint_as_str (SolverConstraint const *c, Sheet *sheet);
 
 typedef enum {
 	SolverRunning, SolverOptimal, SolverUnbounded, SolverInfeasible,
diff --git a/src/tools/solver/reports-write.c b/src/tools/solver/reports-write.c
index 62d672f..cc79e56 100644
--- a/src/tools/solver/reports-write.c
+++ b/src/tools/solver/reports-write.c
@@ -134,7 +134,7 @@ solver_answer_report (WorkbookControl *wbc,
 
 	for (i = 0; i < res->param->n_total_constraints; i++) {
 	        SolverConstraint const *c = res->constraints_array[i];
-		char *str = gnm_solver_constraint_as_str (c);
+		char *str = gnm_solver_constraint_as_str (c, sheet);
 		GnmCell *lhs, *rhs;
 
 		gnm_solver_constraint_get_part (c, sheet, 0,
diff --git a/src/tools/solver/solver.c b/src/tools/solver/solver.c
index a59024b..a7ad30d 100644
--- a/src/tools/solver/solver.c
+++ b/src/tools/solver/solver.c
@@ -37,6 +37,7 @@
 #include "mstyle.h"
 #include "value.h"
 #include "ranges.h"
+#include "expr.h"
 #include "mathfunc.h"
 #include "analysis-tools.h"
 #include "api.h"
@@ -100,7 +101,7 @@ solver_constr_start (GsfXMLIn *xin, xmlChar const **attrs)
 	int cols = 1, rows = 1;
 	gboolean old = FALSE;
 
-	c = g_new0 (SolverConstraint, 1);
+	c = gnm_solver_constraint_new (sheet);
 
 	for (i = 0; attrs != NULL && attrs[i] && attrs[i + 1] ; i += 2) {
 		if (gnm_xml_attr_int (attrs+i, "Lcol", &lhs_col) ||
@@ -270,25 +271,33 @@ solver_get_constraint (SolverResults *res, int n)
         return res->constraints_array[n];
 }
 
+SolverConstraint *
+gnm_solver_constraint_new (Sheet *sheet)
+{
+	SolverConstraint *res = g_new0 (SolverConstraint, 1);
+	dependent_managed_init (&res->lhs, sheet);
+	dependent_managed_init (&res->rhs, sheet);
+	return res;
+}
+
 void
 gnm_solver_constraint_free (SolverConstraint *c)
 {
-	value_release (c->lhs);
-	value_release (c->rhs);
+	gnm_solver_constraint_set_lhs (c, NULL);
+	gnm_solver_constraint_set_rhs (c, NULL);
 	g_free (c);
 }
 
-SolverConstraint *
-gnm_solver_constraint_dup (SolverConstraint *c)
+static SolverConstraint *
+gnm_solver_constraint_dup (SolverConstraint *c, Sheet *sheet)
 {
-	SolverConstraint *res = g_new (SolverConstraint, 1);
+	SolverConstraint *res = gnm_solver_constraint_new (sheet);
 	res->type = c->type;
-	res->lhs = value_dup (c->lhs);
-	res->rhs = value_dup (c->rhs);
+	dependent_managed_set_expr (&res->lhs, res->lhs.base.texpr);
+	dependent_managed_set_expr (&res->rhs, res->lhs.base.texpr);
 	return res;
 }
 
-
 gboolean
 gnm_solver_constraint_has_rhs (SolverConstraint const *c)
 {
@@ -309,24 +318,27 @@ gnm_solver_constraint_has_rhs (SolverConstraint const *c)
 gboolean
 gnm_solver_constraint_valid (SolverConstraint const *c)
 {
+	GnmValue const *lhs;
 	g_return_val_if_fail (c != NULL, FALSE);
 
-	if (c->lhs == NULL || c->lhs->type != VALUE_CELLRANGE)
+	lhs = gnm_solver_constraint_get_lhs (c);
+	if (lhs == NULL || lhs->type != VALUE_CELLRANGE)
 		return FALSE;
 
 	if (gnm_solver_constraint_has_rhs (c)) {
-		if (c->rhs == NULL)
+		GnmValue const *rhs = gnm_solver_constraint_get_lhs (c);
+		if (rhs == NULL)
 			return FALSE;
-		if (c->rhs->type == VALUE_CELLRANGE) {
+		if (rhs->type == VALUE_CELLRANGE) {
 			GnmRange rl, rr;
 
-			range_init_value (&rl, c->lhs);
-			range_init_value (&rr, c->rhs);
+			range_init_value (&rl, lhs);
+			range_init_value (&rr, rhs);
 
 			if (range_width (&rl) != range_width (&rr) ||
 			    range_height (&rl) != range_height (&rr))
 				return FALSE;
-		} else if (VALUE_IS_FLOAT (c->rhs)) {
+		} else if (VALUE_IS_FLOAT (rhs)) {
 			/* Nothing */
 		} else
 			return FALSE;
@@ -339,24 +351,53 @@ static int
 gnm_solver_constraint_get_size (SolverConstraint const *c)
 {
 	GnmRange r;
+	GnmValue const *lhs;
 
 	g_return_val_if_fail (c != NULL, 0);
 
-	range_init_value (&r, c->lhs);
+	lhs = gnm_solver_constraint_get_lhs (c);
+	if (lhs) {
+		if (VALUE_IS_FLOAT (lhs))
+			return 1;
+		if (lhs->type != VALUE_CELLRANGE) {
+			range_init_value (&r, lhs);
+			return range_width (&r) * range_height (&r);
+		}
+	}
+
+	return 0;
+}
 
-	return range_width (&r) * range_height (&r);
+GnmValue const *
+gnm_solver_constraint_get_lhs (SolverConstraint const *c)
+{
+	GnmExprTop const *texpr = c->lhs.base.texpr;
+	return texpr ? gnm_expr_top_get_constant (texpr) : NULL;
 }
 
-GnmValue *
-gnm_solver_constraint_get_lhs (SolverConstraint const *c, Sheet *sheet)
+void
+gnm_solver_constraint_set_lhs (SolverConstraint *c, GnmValue *v)
 {
-	return value_dup (c->lhs);
+	/* Takes ownership.  */
+	GnmExprTop const *texpr = v ? gnm_expr_top_new_constant (v) : NULL;
+	dependent_managed_set_expr (&c->lhs, texpr);
+	if (texpr) gnm_expr_top_unref (texpr);
 }
 
-GnmValue *
-gnm_solver_constraint_get_rhs (SolverConstraint const *c, Sheet *sheet)
+GnmValue const *
+gnm_solver_constraint_get_rhs (SolverConstraint const *c)
 {
-	return value_dup (c->rhs);
+	GnmExprTop const *texpr = c->rhs.base.texpr;
+	return texpr ? gnm_expr_top_get_constant (texpr) : NULL;
+}
+
+void
+gnm_solver_constraint_set_rhs (SolverConstraint *c, GnmValue *v)
+{
+	/* Takes ownership.  */
+	GnmExprTop const *texpr = v ? gnm_expr_top_new_constant (v) : NULL;
+	dependent_managed_set_expr (&c->rhs, texpr);
+	if (texpr) gnm_expr_top_unref (texpr);
 }
 
 
@@ -367,13 +408,20 @@ gnm_solver_constraint_get_part (SolverConstraint const *c, Sheet *sheet, int i,
 {
 	GnmRange r;
 	int h, w, dx, dy;
+	GnmValue const *vl, *vr;
 
 	if (cl)	*cl = 0;
 	if (cr)	*cr = 0;
 	if (lhs) *lhs = NULL;
 	if (rhs) *rhs = NULL;
 
-	range_init_value (&r, c->lhs);
+	if (gnm_solver_constraint_valid (c))
+		return FALSE;
+
+	vl = gnm_solver_constraint_get_lhs (c);
+	vr = gnm_solver_constraint_get_rhs (c);
+
+	range_init_value (&r, vl);
 	w = range_width (&r);
 	h = range_height (&r);
 
@@ -387,11 +435,11 @@ gnm_solver_constraint_get_part (SolverConstraint const *c, Sheet *sheet, int i,
 				       r.start.col + dx, r.start.row + dy);
 
 	if (gnm_solver_constraint_has_rhs (c)) {
-		if (VALUE_IS_FLOAT (c->rhs)) {
+		if (VALUE_IS_FLOAT (vr)) {
 			if (cr)
-				*cr = value_get_as_float (c->rhs);
+				*cr = value_get_as_float (vr);
 		} else {
-			range_init_value (&r, c->rhs);
+			range_init_value (&r, vr);
 			if (rhs)
 				*rhs = sheet_cell_get (sheet,
 						       r.start.col + dx,
@@ -409,11 +457,15 @@ gnm_solver_constraint_get_part_val (SolverConstraint const *c,
 {
 	GnmRange r;
 	int h, w, dx, dy;
+	GnmValue const *vl, *vr;
 
 	if (lhs) *lhs = NULL;
 	if (rhs) *rhs = NULL;
 
-	range_init_value (&r, c->lhs);
+	vl = gnm_solver_constraint_get_lhs (c);
+	vr = gnm_solver_constraint_get_rhs (c);
+
+	range_init_value (&r, vl);
 	w = range_width (&r);
 	h = range_height (&r);
 
@@ -428,10 +480,10 @@ gnm_solver_constraint_get_part_val (SolverConstraint const *c,
 	if (lhs) *lhs = value_new_cellrange_r (sheet, &r);
 
 	if (rhs && gnm_solver_constraint_has_rhs (c)) {
-		if (VALUE_IS_FLOAT (c->rhs)) {
-			*rhs = value_dup (c->rhs);
+		if (VALUE_IS_FLOAT (vr)) {
+			*rhs = value_dup (vr);
 		} else {
-			range_init_value (&r, c->rhs);
+			range_init_value (&r, vr);
 			r.start.col += dx;
 			r.start.row += dy;
 			r.end = r.start;
@@ -453,50 +505,62 @@ gnm_solver_constraint_set_old (SolverConstraint *c,
 
 	c->type = type;
 
-	value_release (c->lhs);
 	range_init (&r,
 		    lhs_col, lhs_row,
 		    lhs_col + (cols - 1), lhs_row + (rows - 1));
-	c->lhs = value_new_cellrange_r (NULL, &r);
+	gnm_solver_constraint_set_lhs
+		(c, value_new_cellrange_r (NULL, &r));
 
-	value_release (c->rhs);
 	if (gnm_solver_constraint_has_rhs (c)) {
 		range_init (&r,
 			    rhs_col, rhs_row,
 			    rhs_col + (cols - 1), rhs_row + (rows - 1));
-		c->rhs = value_new_cellrange_r (NULL, &r);
+		gnm_solver_constraint_set_rhs
+			(c, value_new_cellrange_r (NULL, &r));
 	} else
-		c->rhs = NULL;
+		gnm_solver_constraint_set_rhs (c, NULL);
 }
 
 /* ------------------------------------------------------------------------- */
 
-static SolverConstraint *
-create_solver_constraint (int lhs_col, int lhs_row, int rhs_col, int rhs_row,
-			  SolverConstraintType type)
+void
+gnm_solver_constraint_side_as_str (SolverConstraint const *c,
+				   Sheet const *sheet,
+				   GString *buf, gboolean lhs)
 {
-        SolverConstraint *c = g_new (SolverConstraint, 1);
-	gnm_solver_constraint_set_old (c, type,
-				       lhs_col, lhs_row, rhs_col, rhs_row,
-				       1, 1);
-	return c;
+	GnmExprTop const *texpr;
+
+	texpr = lhs ? c->lhs.base.texpr : c->rhs.base.texpr;
+	if (texpr) {
+		GnmConventionsOut out;
+		GnmParsePos pp;
+
+		out.accum = buf;
+		out.pp = parse_pos_init_sheet (&pp, sheet);
+		out.convs = sheet->convs;
+		gnm_expr_top_as_gstring (texpr, &out);
+	} else
+		g_string_append (buf,
+				 value_error_name (GNM_ERROR_REF,
+						   sheet->convs->output.translated));
 }
 
 char *
-gnm_solver_constraint_as_str (SolverConstraint const *c)
+gnm_solver_constraint_as_str (SolverConstraint const *c, Sheet *sheet)
 {
+	const char * const type_str[] =	{
+		"\xe2\x89\xa4" /* "<=" */,
+		"\xe2\x89\xa5" /* ">=" */,
+		"=", "Int", "Bool"
+	};
 	GString *buf = g_string_new (NULL);
-	GnmConventions const *conv = gnm_conventions_default; /* FIXME! */
-	const char *type_str[] = { "\xe2\x89\xa4" /* "<=" */,
-				   "\xe2\x89\xa5" /* ">=" */,
-				   "=", "Int", "Bool" };
 
-	value_get_as_gstring (c->lhs, buf, conv);
+	gnm_solver_constraint_side_as_str (c, sheet, buf, TRUE);
 	g_string_append_c (buf, ' ');
 	g_string_append (buf, type_str[c->type]);
 	if (gnm_solver_constraint_has_rhs (c)) {
 		g_string_append_c (buf, ' ');
-		value_get_as_gstring (c->rhs, buf, conv);
+		gnm_solver_constraint_side_as_str (c, sheet, buf, FALSE);
 	}
 
 	return g_string_free (buf, FALSE);
@@ -673,7 +737,7 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 		lx = value_get_as_float (lval);
 
 		if (c->type == SolverINT) {
-		        n = get_col_nbr (res, c->lhs);
+		        n = get_col_nbr (res, gnm_solver_constraint_get_lhs (c));
 			if (n == -1)
 			        return NULL;
 		        alg->set_int_fn (program, n);
@@ -681,7 +745,7 @@ lp_qp_solver_init (Sheet *sheet, const SolverParameters *param,
 		        continue;
 		}
 		if (c->type == SolverBOOL) {
-		        n = get_col_nbr (res, c->lhs);
+		        n = get_col_nbr (res, gnm_solver_constraint_get_lhs (c));
 			if (n == -1)
 			        return NULL;
 		        alg->set_bool_fn (program, n);
@@ -857,10 +921,11 @@ check_program_definition_failures (Sheet            *sheet,
 		     gnm_solver_constraint_get_part_val (sc, sheet, i,
 							 &lhs, &rhs);
 		     i++) {
-			SolverConstraint *nc = g_new0 (SolverConstraint, 1);
+			SolverConstraint *nc =
+				gnm_solver_constraint_new (sheet);
 			nc->type = sc->type;
-			nc->lhs = lhs;
-			nc->rhs = rhs;
+			gnm_solver_constraint_set_lhs (nc, lhs);
+			gnm_solver_constraint_set_rhs (nc, rhs);
 		        constraints_array[i++] = nc;
 		}
 	}
@@ -997,7 +1062,7 @@ solver_lp_copy (const SolverParameters *src_param, Sheet *new_sheet)
 	for (constraints = src_param->constraints; constraints;
 	     constraints = constraints->next) {
 		SolverConstraint *old = constraints->data;
-		SolverConstraint *new = gnm_solver_constraint_dup (old);
+		SolverConstraint *new = gnm_solver_constraint_dup (old, new_sheet);
 
 		dst_param->constraints =
 		        g_slist_prepend (dst_param->constraints, new);
@@ -1025,14 +1090,13 @@ solver_lp_copy (const SolverParameters *src_param, Sheet *new_sheet)
 }
 
 /*
- * Adjusts the row indecies in the Solver's data structures when rows
+ * 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;
-	GSList	 *constraints;
         GnmValue *input_range;
 	GnmRange	  range;
 
@@ -1050,26 +1114,18 @@ solver_insert_rows (Sheet *sheet, int row, int count)
 			param->input_entry_str =
 			        g_strdup (global_range_name (sheet, &range));
 		}
-	}
-
-	/* Adjust the constraints. */
-	for (constraints = param->constraints; constraints;
-	     constraints = constraints->next) {
-		SolverConstraint *c = constraints->data;
-		(void)c;
-#warning "FIXME: Handle constraint changes"
+		value_release (input_range);
 	}
 }
 
 /*
- * Adjusts the column indecies in the Solver's data structures when columns
+ * 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;
-	GSList	 *constraints;
         GnmValue *input_range;
 	GnmRange	  range;
 
@@ -1084,27 +1140,18 @@ solver_insert_cols (Sheet *sheet, int col, int count)
 		g_free (param->input_entry_str);
 		param->input_entry_str = g_strdup (
 			global_range_name (sheet, &range));
-	}
-
-	/* Adjust the constraints. */
-	for (constraints = param->constraints; constraints;
-	     constraints = constraints->next) {
-		SolverConstraint *c = constraints->data;
-
-		(void)c;
-#warning "FIXME: Handle constraint changes"
+		value_release (input_range);
 	}
 }
 
 /*
- * Adjusts the row indecies in the Solver's data structures when rows
+ * 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;
-	GSList	 *constraints;
         GnmValue *input_range;
 	GnmRange	  range;
 
@@ -1122,27 +1169,18 @@ solver_delete_rows (Sheet *sheet, int row, int count)
 		else
 			param->input_entry_str = g_strdup (
 				global_range_name (sheet, &range));
-	}
-
-	/* Adjust the constraints. */
-	for (constraints = param->constraints; constraints;
-	     constraints = constraints->next) {
-		SolverConstraint *c = constraints->data;
-
-		(void)c;
-#warning "FIXME: Handle constraint changes"
+		value_release (input_range);
 	}
 }
 
 /*
- * Adjusts the column indecies in the Solver's data structures when columns
+ * 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;
-	GSList	 *constraints;
         GnmValue *input_range;
 	GnmRange	  range;
 
@@ -1164,14 +1202,6 @@ solver_delete_cols (Sheet *sheet, int col, int count)
 				         g_strdup (global_range_name (sheet,
 								      &range));
 		}
-	}
-
-	/* Adjust the constraints. */
-	for (constraints = param->constraints; constraints;
-	     constraints = constraints->next) {
-		SolverConstraint *c = constraints->data;
-
-		(void)c;
-#warning "FIXME: Handle constraint changes"
+		value_release (input_range);
 	}
 }
diff --git a/src/xml-sax-write.c b/src/xml-sax-write.c
index 36804c4..24f8b2c 100644
--- a/src/xml-sax-write.c
+++ b/src/xml-sax-write.c
@@ -1024,12 +1024,13 @@ xml_write_solver (GnmOutputXML *state)
 		gsf_xml_out_start_element (state->output, GNM "Constr");
 		gsf_xml_out_add_int (state->output, "Type", type);
 
-		value_get_as_gstring (c->lhs, str, state->convs);
+		gnm_solver_constraint_side_as_str (c, state->sheet, str, TRUE);
 		gsf_xml_out_add_cstr (state->output, "lhs", str->str);
 
 		if (gnm_solver_constraint_has_rhs (c)) {
 			g_string_truncate (str, 0);
-			value_get_as_gstring (c->rhs, str, state->convs);
+			gnm_solver_constraint_side_as_str (c, state->sheet,
+							   str, FALSE);
 			gsf_xml_out_add_cstr (state->output, "rhs", str->str);
 		}
 



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