1    	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2    	/*                                                                           */
3    	/*                  This file is part of the program and library             */
4    	/*         SCIP --- Solving Constraint Integer Programs                      */
5    	/*                                                                           */
6    	/*  Copyright (c) 2002-2023 Zuse Institute Berlin (ZIB)                      */
7    	/*                                                                           */
8    	/*  Licensed under the Apache License, Version 2.0 (the "License");          */
9    	/*  you may not use this file except in compliance with the License.         */
10   	/*  You may obtain a copy of the License at                                  */
11   	/*                                                                           */
12   	/*      http://www.apache.org/licenses/LICENSE-2.0                           */
13   	/*                                                                           */
14   	/*  Unless required by applicable law or agreed to in writing, software      */
15   	/*  distributed under the License is distributed on an "AS IS" BASIS,        */
16   	/*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
17   	/*  See the License for the specific language governing permissions and      */
18   	/*  limitations under the License.                                           */
19   	/*                                                                           */
20   	/*  You should have received a copy of the Apache-2.0 license                */
21   	/*  along with SCIP; see the file LICENSE. If not visit scipopt.org.         */
22   	/*                                                                           */
23   	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
24   	
25   	/**@file   reader_sol.c
26   	 * @ingroup DEFPLUGINS_READER
27   	 * @brief  file reader for primal solutions
28   	 * @author Tobias Achterberg
29   	 * @author Timo Berthold
30   	 * @author Marc Pfetsch
31   	 *
32   	 */
33   	
34   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
35   	
36   	#include <ctype.h>
37   	#include "scip/pub_fileio.h"
38   	#include "scip/pub_message.h"
39   	#include "scip/pub_misc.h"
40   	#include "scip/pub_reader.h"
41   	#include "scip/pub_sol.h"
42   	#include "scip/reader_sol.h"
43   	#include "scip/scip_general.h"
44   	#include "scip/scip_message.h"
45   	#include "scip/scip_param.h"
46   	#include "scip/scip_reader.h"
47   	#include "scip/scip_sol.h"
48   	#include <string.h>
49   	
50   	#define READER_NAME             "solreader"
51   	#define READER_DESC             "file reader for primal solutions"
52   	#define READER_EXTENSION        "sol"
53   	
54   	
55   	/*
56   	 * Local methods of reader
57   	 */
58   	
59   	/** reads a given SCIP solution file, problem has to be transformed in advance */
60   	static
61   	SCIP_RETCODE readSol(
62   	   SCIP*                 scip,               /**< SCIP data structure */
63   	   const char*           fname,              /**< name of the input file */
64   	   SCIP_Bool             xml                 /**< true, iff the given file is XML */
65   	   )
66   	{
67   	   SCIP_SOL* sol;
68   	   SCIP_Bool error;
69   	   SCIP_Bool partial;
70   	   SCIP_Bool stored;
71   	   SCIP_Bool usevartable;
72   	
73   	   assert(scip != NULL);
74   	   assert(fname != NULL);
75   	
76   	   SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) );
77   	
78   	   if( !usevartable )
79   	   {
80   	      SCIPerrorMessage("Cannot read solution file if vartable is disabled. Make sure parameter 'misc/usevartable' is set to TRUE.\n");
81   	      return SCIP_READERROR;
82   	   }
83   	
84   	   /* create zero solution */
85   	   SCIP_CALL( SCIPcreateSol(scip, &sol, NULL) );
86   	
87   	   SCIP_CALL( SCIPreadSolFile(scip, fname, sol, xml, &partial, &error) );
88   	
89   	   if( !error )
90   	   {
91   	      /* add and free the solution */
92   	      if( SCIPisTransformed(scip) )
93   	      {
94   	         SCIP_Bool completely;
95   	
96   	         assert(!partial);
97   	         assert(!SCIPsolIsPartial(sol));
98   	
99   	         /* use display/allviols to decide whether to print all violations or just the first one */
100  	         SCIP_CALL( SCIPgetBoolParam(scip, "display/allviols", &completely) );
101  	
102  	         SCIP_CALL( SCIPtrySolFree(scip, &sol, TRUE, completely, TRUE, TRUE, TRUE, &stored) );
103  	
104  	         /* display result */
105  	         SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "primal solution from solution file <%s> was %s\n",
106  	            fname, stored ? "accepted" : "rejected - solution is infeasible or objective too poor");
107  	      }
108  	      else
109  	      {
110  	         /* add primal solution to solution candidate storage, frees the solution afterwards */
111  	         SCIP_CALL( SCIPaddSolFree(scip, &sol, &stored) );
112  	
113  	         /* display result */
114  	         SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "%sprimal solution from solution file <%s> was %s\n",
115  	            partial ? "partial " : "", fname, stored ? "accepted as candidate, will be checked when solving starts" : "rejected - solution objective too poor");
116  	      }
117  	
118  	      return SCIP_OKAY;
119  	   }
120  	   else
121  	   {
122  	      /* free solution */
123  	      SCIP_CALL( SCIPfreeSol(scip, &sol) );
124  	
125  	      return SCIP_READERROR;
126  	   }
127  	}
128  	
129  	/*
130  	 * Callback methods of reader
131  	 */
132  	
133  	/** copy method for reader plugins (called when SCIP copies plugins) */
134  	static
135  	SCIP_DECL_READERCOPY(readerCopySol)
136  	{  /*lint --e{715}*/
137  	   assert(scip != NULL);
138  	   assert(reader != NULL);
139  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
140  	
141  	   /* call inclusion method of reader */
142  	   SCIP_CALL( SCIPincludeReaderSol(scip) );
143  	
144  	   return SCIP_OKAY;
145  	}
146  	
147  	
148  	/** problem reading method of reader 
149  	 *
150  	 *  In order to determine the type of the file, we have to open it. Thus, it has to be opened
151  	 *  twice. This might be removed, but is likely to not hurt the performance too much.
152  	 */
153  	static
154  	SCIP_DECL_READERREAD(readerReadSol)
155  	{  /*lint --e{715}*/
156  	   SCIP_FILE* file;
157  	   char buffer[SCIP_MAXSTRLEN];
158  	
159  	   assert(reader != NULL);
160  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
161  	   assert(result != NULL);
162  	
163  	   *result = SCIP_DIDNOTRUN;
164  	
165  	   if( SCIPgetStage(scip) < SCIP_STAGE_PROBLEM )
166  	   {
167  	      SCIPerrorMessage("reading of solution file is only possible after a problem was created\n");
168  	      return SCIP_READERROR;
169  	   }
170  	
171  	   if( SCIPgetStage(scip) == SCIP_STAGE_SOLVED )
172  	   {
173  	      SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL,
174  	         "primal solution from solution file <%s> was ignored - problem is already solved to optimality\n",
175  	         filename);
176  	      *result = SCIP_SUCCESS;
177  	      return SCIP_OKAY;
178  	   }
179  	
180  	   /* open input file in order to determine type */
181  	   file = SCIPfopen(filename, "r");
182  	   if( file == NULL )
183  	   {
184  	      SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
185  	      SCIPprintSysError(filename);
186  	      return SCIP_NOFILE;
187  	   }
188  	
189  	   /* get next line */
190  	   if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
191  	   {
192  	      SCIPerrorMessage("cannot parse file.\n");
193  	      SCIPfclose(file);
194  	      return SCIP_READERROR;
195  	   }
196  	   /* close file */
197  	   SCIPfclose(file);
198  	
199  	   /* decide whether it is xml */
200  	   if( SCIPstrAtStart(buffer, "<?xml", (size_t) 5) )
201  	   {
202  	      /* read XML solution and add it to the solution pool */
203  	      SCIP_CALL( readSol(scip, filename, TRUE) );
204  	   }
205  	   else
206  	   {
207  	      /* read the solution and add it to the solution pool */
208  	      SCIP_CALL( readSol(scip, filename, FALSE) );
209  	   }
210  	
211  	   *result = SCIP_SUCCESS;
212  	
213  	   return SCIP_OKAY;
214  	}
215  	
216  	
217  	/*
218  	 * sol file reader specific interface methods
219  	 */
220  	
221  	/** includes the sol file reader in SCIP */
222  	SCIP_RETCODE SCIPincludeReaderSol(
223  	   SCIP*                 scip                /**< SCIP data structure */
224  	   )
225  	{
226  	   SCIP_READER* reader;
227  	
228  	   /* include reader */
229  	   SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, NULL) );
230  	
231  	   assert(reader != NULL);
232  	
233  	   /* set non fundamental callbacks via setter functions */
234  	   SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopySol) );
235  	   SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadSol) );
236  	
237  	   return SCIP_OKAY;
238  	}
239  	
240