Skip to content

Commit 7992f5f

Browse files
committed
Merge branch 'adapt-debugsol-reader' into 'master'
Adapt debugsol reader See merge request integer/scip!3808
2 parents e726aef + 915a9a4 commit 7992f5f

File tree

2 files changed

+123
-81
lines changed

2 files changed

+123
-81
lines changed

src/scip/debug.c

+117-79
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ SCIP_Bool debugSolutionAvailable(
134134
static
135135
SCIP_RETCODE readSolfile(
136136
SCIP_SET* set, /**< global SCIP settings */
137-
const char* solfilename, /**< solution filename to read */
137+
const char* filename, /**< solution filename to read */
138138
SCIP_SOL** debugsolptr,
139139
SCIP_Real* debugsolvalptr,
140140
SCIP_STAGE* debugsolstageptr,
@@ -144,160 +144,198 @@ SCIP_RETCODE readSolfile(
144144
int* valssize /**< pointer to store the length of the variable names and solution values arrays */
145145
)
146146
{
147+
SCIP_FILE* file;
147148
SCIP_VAR** vars;
148149
SCIP_Real* solvalues;
149-
SCIP_FILE* file;
150150
SCIP_SOL* debugsol;
151151
SCIP_Real debugsolval;
152-
int nonvalues;
153-
int nfound;
154-
int i;
155152
SCIP_Bool unknownvariablemessage;
153+
int lineno;
154+
int i;
156155

157156
assert(set != NULL);
158-
assert(solfilename != NULL);
157+
assert(filename != NULL);
159158
assert(names != NULL);
160159
assert(*names == NULL);
161160
assert(vals != NULL);
162161
assert(*vals == NULL);
163162
assert(nvals != NULL);
164163
assert(valssize != NULL);
165164

166-
printf("***** debug: reading solution file <%s>\n", solfilename);
165+
printf("***** debug: reading solution file <%s>\n", filename);
167166

168167
/* open solution file */
169-
file = SCIPfopen(solfilename, "r");
168+
file = SCIPfopen(filename, "r");
170169
if( file == NULL )
171170
{
172-
SCIPerrorMessage("cannot open solution file <%s> specified in scip/debug.h\n", solfilename);
173-
SCIPprintSysError(solfilename);
171+
SCIPerrorMessage("cannot open solution file <%s> specified in scip/debug.h\n", filename);
172+
SCIPprintSysError(filename);
174173
return SCIP_NOFILE;
175174
}
176175

177176
/* read data */
178-
nonvalues = 0;
179177
*valssize = 0;
180178
unknownvariablemessage = FALSE;
179+
lineno = 0;
181180

182181
while( !SCIPfeof(file) )
183182
{
184-
char buf[SCIP_MAXSTRLEN];
185-
char name[SCIP_MAXSTRLEN];
186-
char objstring[SCIP_MAXSTRLEN];
187-
char valuestring[SCIP_MAXSTRLEN];
183+
/**@todo unlimit buffer size */
184+
char buffer[SCIP_MAXSTRLEN];
185+
const char* varname;
186+
const char* valuestring;
187+
char* endptr;
188188
SCIP_VAR* var;
189-
SCIP_Real val;
190-
int nread;
191189

192-
if( SCIPfgets(buf, SCIP_MAXSTRLEN, file) == NULL )
190+
/* get next line */
191+
if( SCIPfgets(buffer, (int)sizeof(buffer), file) == NULL )
193192
{
194193
if( SCIPfeof(file) )
195194
break;
196195
else
196+
{
197+
SCIPfclose(file);
197198
return SCIP_READERROR;
199+
}
198200
}
199-
200-
/* there are some lines which may preceed the solution information */
201-
if( SCIPstrncasecmp(buf, "solution status:", 16) == 0 || SCIPstrncasecmp(buf, "objective value:", 16) == 0 ||
202-
SCIPstrncasecmp(buf, "Log started", 11) == 0 || SCIPstrncasecmp(buf, "Variable Name", 13) == 0 ||
203-
SCIPstrncasecmp(buf, "All other variables", 19) == 0 || strspn(buf, " \n\r\t\f") == strlen(buf) ||
204-
SCIPstrncasecmp(buf, "NAME", 4) == 0 || SCIPstrncasecmp(buf, "ENDATA", 6) == 0 || /* allow parsing of SOL-format on the MIPLIB 2003 pages */
205-
SCIPstrncasecmp(buf, "=obj=", 5) == 0 ) /* avoid "unknown variable" warning when reading MIPLIB SOL files */
206-
{
207-
++nonvalues;
201+
++lineno;
202+
203+
/* there are some lines which may precede the solution information */
204+
if( SCIPstrncasecmp(buffer, "solution status:", 16) == 0 || SCIPstrncasecmp(buffer, "objective value:", 16) == 0
205+
|| buffer[strspn(buffer, " \t\n\v\f\r")] == '\0' || SCIPstrncasecmp(buffer, "Log started", 11) == 0
206+
|| SCIPstrncasecmp(buffer, "Variable Name", 13) == 0 || SCIPstrncasecmp(buffer, "All other variables", 19) == 0
207+
|| SCIPstrncasecmp(buffer, "NAME", 4) == 0 || SCIPstrncasecmp(buffer, "ENDATA", 6) == 0 /* allow parsing of SOL-format on the MIPLIB 2003 pages */
208+
|| SCIPstrncasecmp(buffer, "=obj=", 5) == 0 ) /* avoid "unknown variable" warning when reading MIPLIB SOL files */
208209
continue;
209-
}
210210

211-
/* cppcheck-suppress invalidscanf */
212-
nread = sscanf(buf, "%s %s %s\n", name, valuestring, objstring);
213-
if( nread < 2 )
211+
/* tokenize the line */
212+
varname = SCIPstrtok(buffer, " \t\v", &endptr);
213+
valuestring = SCIPstrtok(NULL, " \t\n\v\f\r", &endptr);
214+
if( valuestring == NULL )
214215
{
215-
printf("invalid input line %d in solution file <%s>: <%s>\n", *nvals + nonvalues, solfilename, name);
216+
SCIPerrorMessage("Invalid input line %d in solution file <%s>: <%s>.\n", lineno, filename, buffer);
216217
SCIPfclose(file);
217218
return SCIP_READERROR;
218219
}
219220

220221
/* find the variable */
221-
var = SCIPfindVar(set->scip, name);
222+
var = SCIPfindVar(set->scip, varname);
222223
if( var == NULL )
223224
{
224225
if( !unknownvariablemessage )
225226
{
226227
SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, "unknown variable <%s> in line %d of solution file <%s>\n",
227-
name, *nvals + nonvalues, solfilename);
228+
varname, lineno, filename);
228229
SCIPverbMessage(set->scip, SCIP_VERBLEVEL_NORMAL, NULL, " (further unknown variables are ignored)\n");
229230
unknownvariablemessage = TRUE;
230231
}
231232
continue;
232233
}
233234

234-
/* cast the value, check first for inv(alid) or inf(inite) ones that need special treatment */
235+
/* ignore invalid value */
235236
if( SCIPstrncasecmp(valuestring, "inv", 3) == 0 )
237+
{
238+
SCIPdebugMsg(set->scip, "ignored invalid assignment for variable <%s>\n", varname);
236239
continue;
237-
else if( SCIPstrncasecmp(valuestring, "+inf", 4) == 0 || SCIPstrncasecmp(valuestring, "inf", 3) == 0 )
238-
val = SCIPsetInfinity(set);
239-
else if( SCIPstrncasecmp(valuestring, "-inf", 4) == 0 )
240-
val = -SCIPsetInfinity(set);
241-
else
240+
}
241+
242+
/**@todo: store exact debugsol */
242243
{
243-
/* cppcheck-suppress invalidscanf */
244-
nread = sscanf(valuestring, "%lf", &val);
245-
if( nread != 1 )
244+
SCIP_Real value;
245+
246+
if( SCIPstrncasecmp(valuestring, "+inf", 4) == 0 || SCIPstrncasecmp(valuestring, "inf", 3) == 0 )
247+
value = SCIPsetInfinity(set);
248+
else if( SCIPstrncasecmp(valuestring, "-inf", 4) == 0 )
249+
value = -SCIPsetInfinity(set);
250+
else if( !SCIPstrToRealValue(valuestring, &value, &endptr) || *endptr != '\0' )
246251
{
247-
SCIPerrorMessage("Invalid solution value <%s> for variable <%s> in line %d of solution file <%s>.\n",
248-
valuestring, name, *nvals + nonvalues, solfilename);
249-
SCIPfclose(file);
250-
return SCIP_READERROR;
252+
#ifdef SCIP_WITH_EXACTSOLVE
253+
/* convert exact value */
254+
if( SCIPrationalIsString(valuestring) )
255+
{
256+
SCIP_RATIONAL* valueexact;
257+
258+
SCIP_CALL( SCIPrationalCreateString(SCIPblkmem(set->scip), &valueexact, valuestring) );
259+
260+
value = SCIPrationalGetReal(valueexact);
261+
262+
SCIPrationalFreeBlock(SCIPblkmem(set->scip), &valueexact);
263+
}
264+
else
265+
#endif
266+
{
267+
SCIPerrorMessage("Invalid solution value <%s> for variable <%s> in line %d of solution file <%s>.\n",
268+
valuestring, varname, lineno, filename);
269+
SCIPfclose(file);
270+
return SCIP_READERROR;
271+
}
251272
}
252-
}
253273

254-
/* allocate memory */
255-
if( *nvals >= *valssize )
256-
{
257-
*valssize = MAX(2 * *valssize, (*nvals)+1);
258-
SCIP_ALLOC( BMSreallocMemoryArray(names, *valssize) );
259-
SCIP_ALLOC( BMSreallocMemoryArray(vals, *valssize) );
260-
}
261-
assert(*nvals < *valssize);
274+
/* skip zero entry */
275+
if( value == 0.0 ) /*lint !e777*/
276+
continue;
262277

263-
/* store solution value in sorted list */
264-
for( i = *nvals; i > 0 && strcmp(name, (*names)[i-1]) < 0; --i )
265-
{
266-
(*names)[i] = (*names)[i-1];
267-
(*vals)[i] = (*vals)[i-1];
278+
/* search insertion index in sorted list */
279+
i = *nvals - 1;
280+
while( i >= 0 && strcmp(varname, (*names)[i]) < 0 )
281+
--i;
282+
283+
/* overwrite real solution */
284+
if( i >= 0 && strcmp(varname, (*names)[i]) == 0 )
285+
{
286+
SCIPwarningMessage(set->scip, "Overwriting %lf with %lf for <%s> in line %d of solution file <%s>.\n",
287+
(*vals)[i], value, varname, lineno, filename);
288+
(*vals)[i] = value;
289+
}
290+
/* add real solution */
291+
else
292+
{
293+
int j;
294+
295+
if( *nvals >= *valssize )
296+
{
297+
*valssize = MAX(2 * (*valssize), (*nvals) + 1);
298+
SCIP_ALLOC( BMSreallocMemoryArray(names, *valssize) );
299+
SCIP_ALLOC( BMSreallocMemoryArray(vals, *valssize) );
300+
}
301+
assert(*nvals < *valssize);
302+
303+
++i;
304+
for( j = *nvals; j > i; --j )
305+
{
306+
(*names)[j] = (*names)[j - 1];
307+
(*vals)[j] = (*vals)[j - 1];
308+
}
309+
SCIP_ALLOC( BMSduplicateMemoryArray(&(*names)[i], varname, strlen(varname)+1) );
310+
(*vals)[i] = value;
311+
++(*nvals);
312+
}
313+
314+
SCIPdebugMsg(set->scip, "found variable <%s>: value <%g>\n", varname, value);
268315
}
269-
SCIP_ALLOC( BMSduplicateMemoryArray(&(*names)[i], name, strlen(name)+1) );
270-
SCIPdebugMsg(set->scip, "found variable <%s>: value <%g>\n", (*names)[i], val);
271-
(*vals)[i] = val;
272-
(*nvals)++;
273316
}
274317

275318
/* get memory for SCIP solution */
276319
SCIP_ALLOC( BMSallocMemoryArray(&vars, *valssize) );
277320
SCIP_ALLOC( BMSallocMemoryArray(&solvalues, *valssize) );
278321

279322
debugsolval = 0.0;
280-
nfound = 0;
281323

282324
/* get solution value */
283325
for( i = 0; i < *nvals; ++i)
284326
{
285-
SCIP_VAR* var;
286-
var = SCIPfindVar(set->scip, (*names)[i]);
287-
if( var != NULL )
288-
{
289-
vars[nfound] = var;
290-
solvalues[nfound] = (*vals)[i];
291-
++nfound;
292-
debugsolval += (*vals)[i] * SCIPvarGetObj(var);
293-
}
327+
SCIP_VAR* var = SCIPfindVar(set->scip, (*names)[i]);
328+
assert(var != NULL);
329+
vars[i] = var;
330+
solvalues[i] = (*vals)[i];
331+
debugsolval += solvalues[i] * SCIPvarGetObj(var);
294332
}
295333
SCIPdebugMsg(set->scip, "Debug Solution value is %g.\n", debugsolval);
296334

297335
#ifdef SCIP_MORE_DEBUG
298-
SCIPsortPtrReal((void**)vars, solvalues, sortVarsAfterNames, nfound);
336+
SCIPsortPtrReal((void**)vars, solvalues, sortVarsAfterNames, *nvals);
299337

300-
for( i = 0; i < nfound - 1; ++i)
338+
for( i = 0; i < *nvals - 1; ++i)
301339
{
302340
assert(strcmp(SCIPvarGetName(vars[i]), SCIPvarGetName(vars[i + 1])) != 0);
303341
}
@@ -310,7 +348,7 @@ SCIP_RETCODE readSolfile(
310348
*debugsolstageptr = SCIPgetStage(set->scip);
311349

312350
/* set SCIP solution values */
313-
SCIP_CALL( SCIPsetSolVals(set->scip, debugsol, nfound, vars, solvalues ) );
351+
SCIP_CALL( SCIPsetSolVals(set->scip, debugsol, *nvals, vars, solvalues ) );
314352
}
315353

316354
BMSfreeMemoryArray(&vars);
@@ -325,7 +363,7 @@ SCIP_RETCODE readSolfile(
325363
/* close file */
326364
SCIPfclose(file);
327365

328-
printf("***** debug: read %d non-zero entries (%d variables found)\n", *nvals, nfound);
366+
printf("***** debug: found %d non-zero entries\n", *nvals);
329367

330368
return SCIP_OKAY;
331369
}

src/scip/scip_sol.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -3258,9 +3258,13 @@ SCIP_RETCODE readSolFile(
32583258
SCIP_RETCODE retcode;
32593259

32603260
/* get next line */
3261-
if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
3261+
if( SCIPfgets(buffer, (int)sizeof(buffer), file) == NULL )
3262+
{
3263+
if( !SCIPfeof(file) )
3264+
*error = TRUE;
32623265
break;
3263-
lineno++;
3266+
}
3267+
++lineno;
32643268

32653269
/* there are some lines which may precede the solution information */
32663270
if( SCIPstrncasecmp(buffer, "solution status:", 16) == 0 || SCIPstrncasecmp(buffer, "objective value:", 16) == 0

0 commit comments

Comments
 (0)