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_mst.c
26   	 * @ingroup DEFPLUGINS_READER
27   	 * @brief  file reader for partial primal solutions (like MIP-start of Cplex)
28   	 * @author Jakob Witzig
29   	 *
30   	 */
31   	
32   	/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
33   	
34   	#include <ctype.h>
35   	#include "scip/pub_fileio.h"
36   	#include "scip/pub_message.h"
37   	#include "scip/pub_misc.h"
38   	#include "scip/pub_reader.h"
39   	#include "scip/reader_mst.h"
40   	#include "scip/scip_general.h"
41   	#include "scip/scip_message.h"
42   	#include "scip/scip_param.h"
43   	#include "scip/scip_reader.h"
44   	#include "scip/scip_sol.h"
45   	#include <string.h>
46   	
47   	#define READER_NAME             "mstreader"
48   	#define READER_DESC             "file reader for partial primal solutions"
49   	#define READER_EXTENSION        "mst"
50   	
51   	
52   	/*
53   	 * Local methods of reader
54   	 */
55   	
56   	/** reads a given SCIP solution file, problem has to be transformed in advance */
57   	static
58   	SCIP_RETCODE readMst(
59   	   SCIP*                 scip,               /**< SCIP data structure */
60   	   const char*           fname,              /**< name of the input file */
61   	   SCIP_Bool             xml                 /**< true, iff the given file is XML */
62   	   )
63   	{
64   	   SCIP_SOL* sol;
65   	   SCIP_Bool error;
66   	   SCIP_Bool stored;
67   	   SCIP_Bool usevartable;
68   	
69   	   assert(scip != NULL);
70   	   assert(fname != NULL);
71   	
72   	   SCIP_CALL( SCIPgetBoolParam(scip, "misc/usevartable", &usevartable) );
73   	
74   	   if( !usevartable )
75   	   {
76   	      SCIPerrorMessage("Cannot read solution file if vartable is disabled. Make sure parameter 'misc/usevartable' is set to TRUE.\n");
77   	      return SCIP_READERROR;
78   	   }
79   	
80   	   /* create zero solution */
81   	   SCIP_CALL( SCIPcreatePartialSol(scip, &sol, NULL) );
82   	
83   	   SCIP_CALL( SCIPreadSolFile(scip, fname, sol, xml, NULL, &error) );
84   	
85   	   if( !error )
86   	   {
87   	      assert(!SCIPisTransformed(scip));
88   	
89   	      /* add primal solution to solution candidate storage, frees the solution afterwards */
90   	      SCIP_CALL( SCIPaddSolFree(scip, &sol, &stored) );
91   	
92   	      /* display result */
93   	      SCIPverbMessage(scip, SCIP_VERBLEVEL_NORMAL, NULL, "partial primal solution from solution file <%s> was accepted as candidate, will be completed and checked when solving starts\n",
94   	         fname);
95   	
96   	      return SCIP_OKAY;
97   	   }
98   	   else
99   	   {
100  	      /* free solution */
101  	      SCIP_CALL( SCIPfreeSol(scip, &sol) );
102  	
103  	      return SCIP_READERROR;
104  	   }
105  	}
106  	
107  	/*
108  	 * Callback methods of reader
109  	 */
110  	
111  	/** copy method for reader plugins (called when SCIP copies plugins) */
112  	static
113  	SCIP_DECL_READERCOPY(readerCopyMst)
114  	{  /*lint --e{715}*/
115  	   assert(scip != NULL);
116  	   assert(reader != NULL);
117  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
118  	
119  	   /* call inclusion method of reader */
120  	   SCIP_CALL( SCIPincludeReaderMst(scip) );
121  	
122  	   return SCIP_OKAY;
123  	}
124  	
125  	
126  	/** problem reading method of reader 
127  	 *
128  	 *  In order to determine the type of the file, we have to open it. Thus, it has to be opened
129  	 *  twice. This might be removed, but is likely to not hurt the performance too much.
130  	 */
131  	static
132  	SCIP_DECL_READERREAD(readerReadMst)
133  	{  /*lint --e{715}*/
134  	   SCIP_FILE* file;
135  	   char buffer[SCIP_MAXSTRLEN];
136  	
137  	   assert(reader != NULL);
138  	   assert(strcmp(SCIPreaderGetName(reader), READER_NAME) == 0);
139  	   assert(result != NULL);
140  	
141  	   *result = SCIP_DIDNOTRUN;
142  	
143  	   if( SCIPgetStage(scip) < SCIP_STAGE_PROBLEM )
144  	   {
145  	      SCIPerrorMessage("reading of partial solution file is only possible after a problem was created\n");
146  	      return SCIP_READERROR;
147  	   }
148  	
149  	   if( SCIPgetStage(scip) > SCIP_STAGE_PROBLEM )
150  	   {
151  	      SCIPerrorMessage("reading of partial solution file is only possible before the solving process is started\n");
152  	      return SCIP_READERROR;
153  	   }
154  	
155  	   /* open input file in order to determine type */
156  	   file = SCIPfopen(filename, "r");
157  	   if( file == NULL )
158  	   {
159  	      SCIPerrorMessage("cannot open file <%s> for reading\n", filename);
160  	      SCIPprintSysError(filename);
161  	      return SCIP_NOFILE;
162  	   }
163  	
164  	   /* get next line */
165  	   if( SCIPfgets(buffer, (int) sizeof(buffer), file) == NULL )
166  	   {
167  	      SCIPerrorMessage("cannot parse file.\n");
168  	      SCIPfclose(file);
169  	      return SCIP_READERROR;
170  	   }
171  	   /* close file */
172  	   SCIPfclose(file);
173  	
174  	   /* decide whether it is xml */
175  	   if( SCIPstrAtStart(buffer, "<?xml", (size_t) 5) )
176  	   {
177  	      /* read XML solution and add it to the solution pool */
178  	      SCIP_CALL( readMst(scip, filename, TRUE) );
179  	   }
180  	   else
181  	   {
182  	      /* read the solution and add it to the solution pool */
183  	      SCIP_CALL( readMst(scip, filename, FALSE) );
184  	   }
185  	
186  	   *result = SCIP_SUCCESS;
187  	
188  	   return SCIP_OKAY;
189  	}
190  	
191  	
192  	/*
193  	 * sol file reader specific interface methods
194  	 */
195  	
196  	/** includes the mst file reader in SCIP */
197  	SCIP_RETCODE SCIPincludeReaderMst(
198  	   SCIP*                 scip                /**< SCIP data structure */
199  	   )
200  	{
201  	   SCIP_READER* reader;
202  	
203  	   /* include reader */
204  	   SCIP_CALL( SCIPincludeReaderBasic(scip, &reader, READER_NAME, READER_DESC, READER_EXTENSION, NULL) );
205  	
206  	   assert(reader != NULL);
207  	
208  	   /* set non fundamental callbacks via setter functions */
209  	   SCIP_CALL( SCIPsetReaderCopy(scip, reader, readerCopyMst) );
210  	   SCIP_CALL( SCIPsetReaderRead(scip, reader, readerReadMst) );
211  	
212  	   return SCIP_OKAY;
213  	}
214