~jdpipe/ascend/trunk-old

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
#include "config.h"
#include "solverhooks.h"
#include "simulation.h"
#include "solver.h"
#include "solverparameters.h"
#include "solverreporter.h"
#include "value.h"

#include <stdexcept>
#include <string>

extern "C"{
#include <ascend/utilities/error.h>
};

#define SOLVERHOOKS_DEBUG 0

//------------------------------------------------------------------------------
// C-level functions that SolverHooks can pass back to libascend

int ascxx_slvreq_set_solver(const char *solvername, void *user_data){
	Simulation *S = (Simulation *)user_data;
	if(NULL==S->getSolverHooks())return SLVREQ_SOLVER_HOOK_NOT_SET;
#if SOLVERHOOKS_DEBUG
	CONSOLE_DEBUG("Got solver hooks at %p from Simulation at %p",S->getSolverHooks(),S);
#endif
	return S->getSolverHooks()->setSolver(solvername, S);
}

int ascxx_slvreq_set_option(const char *optionname, value_t *val, void *user_data){
	Simulation *S = (Simulation *)user_data;
	if(NULL==S->getSolverHooks())return SLVREQ_OPTION_HOOK_NOT_SET;
	return S->getSolverHooks()->setOption(optionname, Value(val), S);
}

int ascxx_slvreq_do_solve(struct Instance *instance, void *user_data){
	Simulation *S = (Simulation *)user_data;
	if(NULL==S->getSolverHooks())return SLVREQ_SOLVE_HOOK_NOT_SET;
	return S->getSolverHooks()->doSolve(instance, S);
}


//------------------------------------------------------------------------------
// SOLVER HOOKS (C++ layer implementation)

SolverHooks::SolverHooks(SolverReporter *R) : R(R){
#if SOLVERHOOKS_DEBUG
	CONSOLE_DEBUG("Creating SolverHooks at %p",this);
#endif
	// nothing else to do
}

SolverHooks::~SolverHooks(){
	/* nothing that we own that we need to destroy? */
}

SolverHooks::SolverHooks(SolverHooks &old) : R(old.R){
#if SOLVERHOOKS_DEBUG
	CONSOLE_DEBUG("Creating new SolverHooks at %p (copy of old at %p",this,&old);
#endif
}

int
SolverHooks::setSolver(const char *solvername, Simulation *S){
	/* note desired return codes from slvreq.h */
	try{
		Solver solver(solvername);
		S->build();
		S->setSolver(solver);
	}catch(std::runtime_error *E){
		return SLVREQ_UNKNOWN_SOLVER;
	}
	CONSOLE_DEBUG("Solver set to '%s'",solvername);
	return 0;
}

int
SolverHooks::setOption(const char *optionname, Value val, Simulation *S){
	/* FIXME need to check if the system is built? */
	/* FIXME check if we have got a solver assigned? */
	SolverParameters pp = S->getParameters();

	try{
		SolverParameter p = pp.getParameter(optionname);
		try{
			p.setValueValue(val);
		}catch(std::runtime_error E){
			return SLVREQ_WRONG_OPTION_VALUE_TYPE;
		}
	}catch(std::runtime_error E){
		return SLVREQ_INVALID_OPTION_NAME;
	}
	return 0;
}

int
SolverHooks::doSolve(Instance *i, Simulation *S){
	CONSOLE_DEBUG("Solving model...");
	
	try{
		/* FIXME do solving of a particular instance? */
		if(!getSolverReporter()){
			CONSOLE_DEBUG("Creating default SolverReporter");
			SolverReporter R;
			S->solve(S->getSolver(), R);
		}else{
			CONSOLE_DEBUG("Using SolverReporter at %p",getSolverReporter());
			S->solve(S->getSolver(), *getSolverReporter());
		}
	}catch(std::runtime_error E){
		return SLVREQ_SOLVE_FAIL;
	}

	/* solver succeeded */
	return 0;
}

void
SolverHooks::assign(Simulation *S){
	S->setSolverHooks(this);
#if SOLVERHOOKS_DEBUG
	CONSOLE_DEBUG("Assigning SolverHooks to Simulation...");
#endif
	slvreq_assign_hooks(S->getInternalType(),&ascxx_slvreq_set_solver, &ascxx_slvreq_set_option, &ascxx_slvreq_do_solve, (void *)S);
}

SolverReporter *
SolverHooks::getSolverReporter(){
#if SOLVERHOOKS_DEBUG
	CONSOLE_DEBUG("SolverReporter is at %p", R);
#endif
	return R;
}

//------------------------------------------------------------------------------
// SOLVER HOOKS (Python layer implementation)

#if 0
class SolverHooksPython{
private:
	PyObject *set_solver_py;
	PyObject *set_param_py;
	PyObject *do_solve_py;
	PyObject *context_py;
public:
	SolverHooksPython(PyObject *set_solver_fn, PyObject *set_param_fn, PyObject *do_solve_fn, PyObject *context);
	virtual int setSolver(const char *solvername, Simulation *S);
	virtual int setOption(const char *optionname, const char *val, Simulation *S);
	virtual int doSolve(Instance *i, Simulation *S);
};
#endif

//------------------------------------------------------------------------------
// SOLVER HOOKS MANAGER (singleton)

SolverHooksManager::SolverHooksManager(){
#if SOLVERHOOKS_DEBUG
	CONSOLE_DEBUG("Creating SolverHooksManager with NULL hooks");
#endif
	this->hooks = NULL;
	this->own_hooks = 0;
}

SolverHooksManager *SolverHooksManager::_instance;

SolverHooksManager *
SolverHooksManager::Instance(){
	if(_instance==0){
		_instance = new SolverHooksManager();
	}
	return _instance;
}

SolverHooksManager::~SolverHooksManager(){
	if(own_hooks){
#if SOLVERHOOKS_DEBUG
		CONSOLE_DEBUG("Delete owned hooks");
#endif
		delete hooks;
	}
}

void
SolverHooksManager::setHooks(SolverHooks *H){
#if SOLVERHOOKS_DEBUG
	CONSOLE_DEBUG("Using hooks at %p",H);
#endif
	if(hooks && own_hooks){
#if SOLVERHOOKS_DEBUG
		CONSOLE_DEBUG("Deleting previous owned hooks");
#endif
		delete(hooks);
	}
	this->hooks = H;
	this->own_hooks = 0;
}

SolverHooks *
SolverHooksManager::getHooks(){
	if(this->hooks == NULL){
#if SOLVERHOOKS_DEBUG
		CONSOLE_DEBUG("Creating new default SolverHooks...");
#endif
		this->hooks = new SolverHooks();
		this->own_hooks = 1;
	}
	return this->hooks;
}