[gnumeric] solver: by default, select a solver for which we have the executable.



commit 3e2b36ac8137b3ca03e47fcc2719ad3593bdc2c5
Author: Morten Welinder <terra gnome org>
Date:   Wed Nov 25 14:12:27 2009 -0500

    solver: by default, select a solver for which we have the executable.

 plugins/glpk/gnm-glpk.c       |   16 +++++++++++++++-
 plugins/lpsolve/gnm-lpsolve.c |   16 +++++++++++++++-
 src/dialogs/dialog-solver.c   |   16 ++++++++++++++++
 src/gnm-plugin.c              |   33 +++++++++++++++++++++++++++++++--
 src/gnm-plugin.h              |    1 +
 src/tools/gnm-solver.c        |   16 +++++++++++++---
 src/tools/gnm-solver.h        |    8 ++++++--
 7 files changed, 97 insertions(+), 9 deletions(-)
---
diff --git a/plugins/glpk/gnm-glpk.c b/plugins/glpk/gnm-glpk.c
index ed6528b..04f7437 100644
--- a/plugins/glpk/gnm-glpk.c
+++ b/plugins/glpk/gnm-glpk.c
@@ -14,6 +14,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#define SOLVER_PROGRAM "glpsol"
 #define PRIVATE_KEY "::glpk::"
 
 typedef struct {
@@ -259,7 +260,7 @@ gnm_glpk_start (GnmSolver *sol, WorkbookControl *wbc, GError **err,
 
 	g_return_val_if_fail (sol->status == GNM_SOLVER_STATUS_PREPARED, FALSE);
 
-	argv[argc++] = (gchar *)"glpsol";
+	argv[argc++] = (gchar *)SOLVER_PROGRAM;
 	argv[argc++] = (gchar *)(param->options.automatic_scaling
 				 ? "--scale"
 				 : "--noscale");
@@ -291,6 +292,19 @@ gnm_glpk_stop (GnmSolver *sol, GError *err, GnmGlpk *lp)
 	return TRUE;
 }
 
+gboolean
+glpk_solver_factory_functional (GnmSolverFactory *factory);
+
+gboolean
+glpk_solver_factory_functional (GnmSolverFactory *factory)
+{
+	char *full_path = g_find_program_in_path (SOLVER_PROGRAM);
+	gboolean res= (full_path != NULL);
+	g_free (full_path);
+	return res;
+}
+
+
 GnmSolver *
 glpk_solver_factory (GnmSolverFactory *factory, GnmSolverParameters *params);
 
diff --git a/plugins/lpsolve/gnm-lpsolve.c b/plugins/lpsolve/gnm-lpsolve.c
index f41e5d4..9926ad0 100644
--- a/plugins/lpsolve/gnm-lpsolve.c
+++ b/plugins/lpsolve/gnm-lpsolve.c
@@ -9,6 +9,7 @@
 #include <glib/gi18n-lib.h>
 #include <string.h>
 
+#define SOLVER_PROGRAM "lp_solve"
 #define PRIVATE_KEY "::lpsolve::"
 
 typedef struct {
@@ -256,7 +257,7 @@ gnm_lpsolve_start (GnmSolver *sol, WorkbookControl *wbc, GError **err,
 
 	g_return_val_if_fail (sol->status == GNM_SOLVER_STATUS_PREPARED, FALSE);
 
-	argv[argc++] = (gchar *)"lp_solve";
+	argv[argc++] = (gchar *)SOLVER_PROGRAM;
 	argv[argc++] = (gchar *)"-i";
 	argv[argc++] = (gchar *)(param->options.automatic_scaling
 				 ? "-s1"
@@ -286,6 +287,19 @@ gnm_lpsolve_stop (GnmSolver *sol, GError *err, GnmLPSolve *lp)
 	return TRUE;
 }
 
+gboolean
+lpsolve_solver_factory_functional (GnmSolverFactory *factory);
+
+gboolean
+lpsolve_solver_factory_functional (GnmSolverFactory *factory)
+{
+	char *full_path = g_find_program_in_path (SOLVER_PROGRAM);
+	gboolean res= (full_path != NULL);
+	g_free (full_path);
+	return res;
+}
+
+
 GnmSolver *
 lpsolve_solver_factory (GnmSolverFactory *factory, GnmSolverParameters *params);
 
diff --git a/src/dialogs/dialog-solver.c b/src/dialogs/dialog-solver.c
index beedf35..5ce1e81 100644
--- a/src/dialogs/dialog-solver.c
+++ b/src/dialogs/dialog-solver.c
@@ -1163,11 +1163,27 @@ void
 dialog_solver (WBCGtk *wbcg, Sheet *sheet)
 {
         SolverState *state;
+	GnmSolverParameters *old_params = sheet->solver_parameters;
 
 	/* Only pop up one copy per workbook */
 	if (gnumeric_dialog_raise_if_exists (wbcg, SOLVER_KEY))
 		return;
 
+	/* First time around, pick a functional algorithm.  */
+	if (!gnm_solver_factory_functional (old_params->options.algorithm)) {
+		GSList *l;
+		for (l = gnm_solver_db_get (); l; l = l->next) {
+			GnmSolverFactory *factory = l->data;
+			if (old_params->options.model_type != factory->type)
+				continue;
+			if (gnm_solver_factory_functional (factory)) {
+				gnm_solver_param_set_algorithm (old_params,
+								factory);
+				break;
+			}
+		}
+	}
+
 	state                 = g_new0 (SolverState, 1);
 	state->wbcg           = wbcg;
 	state->sheet          = sheet;
diff --git a/src/gnm-plugin.c b/src/gnm-plugin.c
index 240462c..ef139c6 100644
--- a/src/gnm-plugin.c
+++ b/src/gnm-plugin.c
@@ -512,6 +512,26 @@ cb_load_and_create (GnmSolverFactory *factory, GnmSolverParameters *param)
 	return res;
 }
 
+static gboolean
+cb_load_and_functional (GnmSolverFactory *factory)
+{
+	PluginServiceSolver *ssol =
+		g_object_get_data (G_OBJECT (factory), "ssol");
+	GOPluginService *service = GO_PLUGIN_SERVICE (ssol);
+	GOErrorInfo *ignored_error = NULL;
+	GnmSolverFactoryFunctional functional;
+
+	go_plugin_service_load (service, &ignored_error);
+	if (ignored_error != NULL) {
+		go_error_info_print (ignored_error);
+		go_error_info_free (ignored_error);
+		return FALSE;
+	}
+
+	functional = ssol->cbs.functional;
+	return (functional == NULL || functional (factory));
+}
+
 static void
 plugin_service_solver_init (PluginServiceSolver *ssol)
 {
@@ -572,7 +592,8 @@ plugin_service_solver_read_xml (GOPluginService *service, xmlNode *tree,
 		ssol->factory = gnm_solver_factory_new (CXML2C (s_id),
 							CXML2C (s_name),
 							type,
-							cb_load_and_create);
+							cb_load_and_create,
+							cb_load_and_functional);
 		g_object_set_data (G_OBJECT (ssol->factory), "ssol", ssol);
 	}
 	xmlFree (s_id);
@@ -815,6 +836,7 @@ gnm_plugin_loader_module_load_service_solver (GOPluginLoader *loader,
 	PluginServiceSolverCallbacks *cbs;
 	char *symname;
 	GnmSolverCreator creator;
+	GnmSolverFactoryFunctional functional;
 
 	g_return_if_fail (IS_GNM_PLUGIN_SERVICE_SOLVER (service));
 
@@ -825,7 +847,6 @@ gnm_plugin_loader_module_load_service_solver (GOPluginLoader *loader,
 			       NULL);
 	g_module_symbol (loader_module->handle, symname, (gpointer)&creator);
 	g_free (symname);
-
 	if (!creator) {
 		*ret_error = go_error_info_new_printf (
 			_("Module file \"%s\" has invalid format."),
@@ -833,8 +854,15 @@ gnm_plugin_loader_module_load_service_solver (GOPluginLoader *loader,
 		return;
 	}
 
+	symname = g_strconcat (go_plugin_service_get_id (service),
+			       "_solver_factory_functional",
+			       NULL);
+	g_module_symbol (loader_module->handle, symname, (gpointer)&functional);
+	g_free (symname);
+
 	cbs = go_plugin_service_get_cbs (service);
 	cbs->creator = creator;
+	cbs->functional = functional;
 }
 
 static gboolean
@@ -864,6 +892,7 @@ gplm_service_unload (GOPluginLoader *l, GOPluginService *s, GOErrorInfo **err)
 		PluginServiceSolverCallbacks *cbs =
 			go_plugin_service_get_cbs (s);
 		cbs->creator = NULL;
+		cbs->functional = NULL;
 	} else
 		return FALSE;
 	return TRUE;
diff --git a/src/gnm-plugin.h b/src/gnm-plugin.h
index ee13ee3..3513567 100644
--- a/src/gnm-plugin.h
+++ b/src/gnm-plugin.h
@@ -56,6 +56,7 @@ GType plugin_service_solver_get_type (void);
 typedef struct _PluginServiceSolver PluginServiceSolver;
 typedef struct {
 	GnmSolverCreator creator;
+	GnmSolverFactoryFunctional functional;
 } PluginServiceSolverCallbacks;
 
 /**************************************************************************/
diff --git a/src/tools/gnm-solver.c b/src/tools/gnm-solver.c
index 5579da9..9397b54 100644
--- a/src/tools/gnm-solver.c
+++ b/src/tools/gnm-solver.c
@@ -638,8 +638,6 @@ gnm_solver_param_constructor (GType type,
 	sp->options.max_time_sec = 30;
 	sp->options.assume_non_negative = TRUE;
 	sp->options.scenario_name = g_strdup ("Optimal");
-	gnm_solver_param_set_algorithm
-		(sp, g_slist_nth_data (gnm_solver_db_get (), 0));
 
 	return obj;
 }
@@ -1396,7 +1394,8 @@ GnmSolverFactory *
 gnm_solver_factory_new (const char *id,
 			const char *name,
 			GnmSolverModelType type,
-			GnmSolverCreator creator)
+			GnmSolverCreator creator,
+			GnmSolverFactoryFunctional functional)
 {
 	GnmSolverFactory *res;
 
@@ -1409,6 +1408,7 @@ gnm_solver_factory_new (const char *id,
 	res->name = g_strdup (name);
 	res->type = type;
 	res->creator = creator;
+	res->functional = functional;
 	return res;
 }
 
@@ -1420,6 +1420,16 @@ gnm_solver_factory_create (GnmSolverFactory *factory,
 	return factory->creator (factory, param);
 }
 
+gboolean
+gnm_solver_factory_functional (GnmSolverFactory *factory)
+{
+	if (factory == NULL)
+		return FALSE;
+
+	return (factory->functional == NULL ||
+		factory->functional (factory));
+}
+
 static int
 cb_compare_factories (GnmSolverFactory *a, GnmSolverFactory *b)
 {
diff --git a/src/tools/gnm-solver.h b/src/tools/gnm-solver.h
index 83722de..675fb91 100644
--- a/src/tools/gnm-solver.h
+++ b/src/tools/gnm-solver.h
@@ -207,7 +207,7 @@ typedef struct {
 	gboolean (*start) (GnmSolver *solver,
 			   WorkbookControl *wbc, GError **err);
 	gboolean (*stop) (GnmSolver *solver, GError **err);
-	gboolean (*child_exit) (GnmSolver *solver, gboolean normal, int code);
+	void (*child_exit) (GnmSolver *solver, gboolean normal, int code);
 } GnmSolverClass;
 
 GType gnm_solver_get_type  (void);
@@ -291,6 +291,7 @@ const char *gnm_sub_solver_get_cell_name (GnmSubSolver *subsol,
 
 typedef GnmSolver * (*GnmSolverCreator) (GnmSolverFactory *,
 					 GnmSolverParameters *);
+typedef gboolean (*GnmSolverFactoryFunctional) (GnmSolverFactory *);
 
 struct GnmSolverFactory_ {
 	GObject parent;
@@ -299,6 +300,7 @@ struct GnmSolverFactory_ {
 	char *name; /* Already translated */
 	GnmSolverModelType type;
 	GnmSolverCreator creator;
+	GnmSolverFactoryFunctional functional;
 };
 
 typedef struct {
@@ -310,9 +312,11 @@ GType gnm_solver_factory_get_type (void);
 GnmSolverFactory *gnm_solver_factory_new (const char *id,
 					  const char *name,
 					  GnmSolverModelType type,
-					  GnmSolverCreator creator);
+					  GnmSolverCreator creator,
+					  GnmSolverFactoryFunctional funct);
 GnmSolver *gnm_solver_factory_create (GnmSolverFactory *factory,
 				      GnmSolverParameters *param);
+gboolean gnm_solver_factory_functional (GnmSolverFactory *factory);
 
 GSList *gnm_solver_db_get (void);
 void gnm_solver_db_register (GnmSolverFactory *factory);



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