Scippy

SCIP

Solving Constraint Integer Programs

HeurFrats.cpp
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the program and library */
4/* SCIP --- Solving Constraint Integer Programs */
5/* */
6/* Copyright (c) 2002-2024 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 HeurFrats.cpp
26 * @brief fractional travelling salesman heuristic - Rounding heuristic for TSP
27 * @author Timo Berthold
28 */
29
30/*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
31
32#include "HeurFrats.h"
33#include "ProbDataTSP.h"
34
35using namespace tsp;
36using namespace std;
37
38
39/*
40 * Local methods
41 */
42
43
44/*
45 * Callback methods of primal heuristic
46 */
47
48/** destructor of primal heuristic to free user data (called when SCIP is exiting) */
49SCIP_DECL_HEURFREE(HeurFrats::scip_free)
50{ /*lint --e{715}*/
51 return SCIP_OKAY;
52}
53
54/** initialization method of primal heuristic (called after problem was transformed) */
55SCIP_DECL_HEURINIT(HeurFrats::scip_init)
56{
57 ProbDataTSP* probdata;
58
59 /* create heuristic data */
60 SCIP_CALL( SCIPcreateSol(scip, &sol, heur) );
61
62 /* load the problem specific data */
63 probdata = dynamic_cast<ProbDataTSP*>(SCIPgetObjProbData(scip));
64 assert(probdata != NULL);
65
66 graph = probdata->getGraph();
67 assert(graph != NULL);
68
69 capture_graph(graph);
70
71 return SCIP_OKAY;
72}
73
74/** deinitialization method of primal heuristic (called before transformed problem is freed) */
75SCIP_DECL_HEUREXIT(HeurFrats::scip_exit)
76{ /*lint --e{715}*/
77 /* free everything which was created in scip_init */
78 SCIP_CALL( SCIPfreeSol(scip, &sol) );
79 release_graph(&graph);
80
81 return SCIP_OKAY;
82}
83
84/** solving process initialization method of primal heuristic (called when branch and bound process is about to begin)
85 *
86 * This method is called when the presolving was finished and the branch and bound process is about to begin.
87 * The primal heuristic may use this call to initialize its branch and bound specific data.
88 *
89 */
90SCIP_DECL_HEURINITSOL(HeurFrats::scip_initsol)
91{ /*lint --e{715}*/
92 return SCIP_OKAY;
93}
94
95/** solving process deinitialization method of primal heuristic (called before branch and bound process data is freed)
96 *
97 * This method is called before the branch and bound process is freed.
98 * The primal heuristic should use this call to clean up its branch and bound data.
99 */
100SCIP_DECL_HEUREXITSOL(HeurFrats::scip_exitsol)
101{ /*lint --e{715}*/
102 return SCIP_OKAY;
103}
104
105/** execution method of primal heuristic */
106SCIP_DECL_HEUREXEC(HeurFrats::scip_exec)
107{ /*lint --e{715}*/
108 SCIP_SOL* newsol;
109 GRAPHNODE* currnode;
110 SCIP_Bool* visited;
111 SCIP_Bool success;
112 int nnodes;
113 int i;
114
115 assert(result != NULL);
116 /* since the timing is SCIP_HEURTIMING_AFTERLPNODE, the current node should have an LP */
117 assert(SCIPhasCurrentNodeLP(scip));
118
119 *result = SCIP_DIDNOTRUN;
120
121 /* only call heuristic, if an optimal LP solution is at hand */
123 return SCIP_OKAY;
124
125 /* get the working solution from heuristic's local data */
126 assert(sol != NULL);
127
128 /* copy the current LP solution to the working solution */
130
131 *result = SCIP_DIDNOTFIND;
132
133 /* choose the first node as starting point*/
134 currnode = &graph->nodes[0]; /*lint !e613*/
135 nnodes = graph->nnodes; /*lint !e613*/
136 success = TRUE;
137
138 /* allocate local memory */
139 SCIP_CALL( SCIPcreateSol (scip, &newsol, heur) );
140 SCIP_CALL( SCIPallocBufferArray(scip, &visited, nnodes) ); /*lint !e530*/
141 BMSclearMemoryArray(visited, nnodes);
142
143 assert(currnode->id == 0);
144 visited[0] = TRUE;
145
146 /*exactly nnodes edges have to be inserted into the tour */
147 for( i = 0; i < nnodes; i++ )
148 {
149 GRAPHEDGE* edge;
150 SCIP_Real bestval;
151 GRAPHEDGE* bestedge;
152
153 /* initialization */
154 bestedge = NULL;
155 bestval = -1;
156
157 /* the graph works with adjacency lists */
158 edge = currnode->first_edge;
159
160 /* the last edge is treated separately */
161 if( i != nnodes-1 )
162 {
163 while( edge != NULL )
164 {
165 /* update, if an edge has a better LP value AND was not visited yet AND was not globally fixed to zero */
166 if( SCIPgetSolVal(scip, sol, edge->var) > bestval && !visited[edge->adjac->id]
167 && SCIPvarGetUbGlobal(edge->var) == 1.0 )
168 {
169 bestval = SCIPgetSolVal(scip, sol, edge->var);
170 bestedge = edge;
171 }
172 edge = edge->next;
173 }
174 }
175 else
176 {
177 GRAPHNODE* finalnode;
178 finalnode = &graph->nodes[0]; /*lint !e613*/
179
180 /* find the last edge which closes the tour */
181 while( edge != NULL )
182 {
183 if( edge->adjac == finalnode )
184 {
185 if( SCIPvarGetUbGlobal(edge->var) == 1.0 )
186 {
187 bestval = SCIPgetSolVal(scip, sol, edge->var);
188 bestedge = edge;
189 }
190 break;
191 }
192 edge = edge->next;
193 }
194 }
195
196 /* it may happen that we were not able to build a complete tour */
197 if( bestval == -1 )
198 {
199 success = FALSE;
200 break;
201 }
202
203 /* assert that the data is not corrupted */
204 assert(bestedge != NULL);
205 assert(SCIPisFeasLE(scip, 0.0, bestval) && SCIPisFeasLE(scip, bestval, 1.0));
206 assert(bestval == SCIPgetSolVal(scip, sol, bestedge->var)); /*lint !e777*/
207
208 /* fix the variable which represents the best edge to one in the new solution and proceed to next node */
209 SCIP_CALL( SCIPsetSolVal(scip, newsol, bestedge->var, 1.0) );
210 currnode = bestedge->adjac;
211 assert(currnode != NULL);
212 assert(0 <= currnode->id && currnode->id <= nnodes-1);
213 if( i != nnodes-1 )
214 assert(!visited[currnode->id]);
215 visited[currnode->id] = TRUE;
216 }
217
218 /* if we were able to construct a complete tour, try to add the solution to SCIP */
219 if( success )
220 {
221 for( i = 0; i < nnodes; i++ )
222 assert(visited[graph->nodes[i].id]); /*lint !e613*/
223
224 success = FALSE;
225
226 /* due to construction we already know, that the solution will be feasible */
227 SCIP_CALL( SCIPtrySol(scip, newsol, FALSE, FALSE, FALSE, FALSE, FALSE, &success) );
228 if( success )
229 *result = SCIP_FOUNDSOL;
230 }
231 /* free all local memory */
232 SCIP_CALL( SCIPfreeSol(scip, &newsol) );
233 SCIPfreeBufferArray(scip, &visited);
234
235 return SCIP_OKAY;
236}
237
238/** clone method which will be used to copy a objective plugin */
239SCIP_DECL_HEURCLONE(scip::ObjCloneable* HeurFrats::clone) /*lint !e665*/
240{
241 return new HeurFrats(scip);
242}
void capture_graph(GRAPH *gr)
void release_graph(GRAPH **gr)
SCIP_DECL_HEURFREE(HeurFrats::scip_free)
Definition: HeurFrats.cpp:49
SCIP_DECL_HEURINIT(HeurFrats::scip_init)
Definition: HeurFrats.cpp:55
SCIP_DECL_HEURINITSOL(HeurFrats::scip_initsol)
Definition: HeurFrats.cpp:90
SCIP_DECL_HEUREXITSOL(HeurFrats::scip_exitsol)
Definition: HeurFrats.cpp:100
SCIP_DECL_HEUREXIT(HeurFrats::scip_exit)
Definition: HeurFrats.cpp:75
SCIP_DECL_HEUREXEC(HeurFrats::scip_exec)
Definition: HeurFrats.cpp:106
SCIP_DECL_HEURCLONE(scip::ObjCloneable *HeurFrats::clone)
Definition: HeurFrats.cpp:239
fractional travelling salesman heuristic - Rounding heuristic for TSP
C++ problem data for TSP.
GRAPH * getGraph()
Definition: ProbDataTSP.h:97
#define NULL
Definition: def.h:267
#define SCIP_Bool
Definition: def.h:91
#define SCIP_Real
Definition: def.h:173
#define TRUE
Definition: def.h:93
#define FALSE
Definition: def.h:94
#define SCIP_CALL(x)
Definition: def.h:374
#define nnodes
Definition: gastrans.c:74
SCIP_Bool SCIPhasCurrentNodeLP(SCIP *scip)
Definition: scip_lp.c:83
SCIP_LPSOLSTAT SCIPgetLPSolstat(SCIP *scip)
Definition: scip_lp.c:168
#define SCIPallocBufferArray(scip, ptr, num)
Definition: scip_mem.h:124
#define SCIPfreeBufferArray(scip, ptr)
Definition: scip_mem.h:136
SCIP_RETCODE SCIPcreateSol(SCIP *scip, SCIP_SOL **sol, SCIP_HEUR *heur)
Definition: scip_sol.c:184
SCIP_RETCODE SCIPfreeSol(SCIP *scip, SCIP_SOL **sol)
Definition: scip_sol.c:841
SCIP_RETCODE SCIPtrySol(SCIP *scip, SCIP_SOL *sol, SCIP_Bool printreason, SCIP_Bool completely, SCIP_Bool checkbounds, SCIP_Bool checkintegrality, SCIP_Bool checklprows, SCIP_Bool *stored)
Definition: scip_sol.c:2954
SCIP_RETCODE SCIPlinkLPSol(SCIP *scip, SCIP_SOL *sol)
Definition: scip_sol.c:882
SCIP_RETCODE SCIPsetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var, SCIP_Real val)
Definition: scip_sol.c:1077
SCIP_Real SCIPgetSolVal(SCIP *scip, SCIP_SOL *sol, SCIP_VAR *var)
Definition: scip_sol.c:1217
SCIP_Bool SCIPisFeasLE(SCIP *scip, SCIP_Real val1, SCIP_Real val2)
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:18088
#define BMSclearMemoryArray(ptr, num)
Definition: memory.h:130
Definition: pqueue.h:38
scip::ObjProbData * SCIPgetObjProbData(SCIP *scip)
GRAPHNODE * adjac
Definition: GomoryHuTree.h:72
SCIP_VAR * var
Definition: GomoryHuTree.h:74
struct GraphEdge * next
Definition: GomoryHuTree.h:69
struct GraphEdge * first_edge
Definition: GomoryHuTree.h:53
Definition of base class for all clonable classes.
Definition: objcloneable.h:48
@ SCIP_LPSOLSTAT_OPTIMAL
Definition: type_lp.h:43
@ SCIP_DIDNOTRUN
Definition: type_result.h:42
@ SCIP_DIDNOTFIND
Definition: type_result.h:44
@ SCIP_FOUNDSOL
Definition: type_result.h:56
@ SCIP_OKAY
Definition: type_retcode.h:42