![]() | |||||||||||
| |||||||||||
Mosel files for the Mosel-Python comparison blog Description Mosel files for the blog post comparing Mosel and Python. Instructions for running these files:
Source Files By clicking on a file name, a preview is opened at the bottom of this page. Data Files TSP_adv.mos (!****************************************************** Mosel Example Problems ====================== file TSP_adv.mos ```````````````` Improved version of model 'TSP_std.mos'. -- Advanced optimization tasks (solution loading, callbacks, cuts) -- (c) 2019-2025 Fair Isaac Corporation author: S.Heipcke *******************************************************!) model "TSP test" uses "mmxprs", "mmsystem", "mmsheet", "mmetc" parameters DATA_FILE_PREFIX = "00" TOL=10E-10 end-parameters writeln("#E:IMPORT") forward procedure printsol forward procedure cb_preintsol(isheur: boolean, cutoff: real) forward function cb_optnode: boolean writeln("#S:READ") declarations CITIES: range ! Set of cities X,Y: array(CITIES) of real ONETOL = 1-TOL ! Constant to replace repeated calculations end-declarations initializations from "mmetc.diskdata:" [X, Y] as "csv,skiph," + DATA_FILE_PREFIX + "_H_TSP_cities.csv" end-initializations declarations NCITIES=getsize(CITIES) DIST: array(CITIES,CITIES) of integer ! Distance between cities NEXTC: array(CITIES) of integer ! Next city after i in the solution fly: array(CITIES,CITIES) of mpvar ! 1 iff flight from i to j INITTOURS = 1..10 InitTours : array(INITTOURS) of mpsol end-declarations declarations CITYORDER = 1..NCITIES + 1 TOURS: array(INITTOURS, CITYORDER) of integer end-declarations diskdata(ETC_DENSE, DATA_FILE_PREFIX + "_H_TSP_tours.csv", TOURS) writeln("#E:READ") writeln("#S:PROC") forall(t in INITTOURS,i in CITIES) setsol(InitTours(t),fly(TOURS(t, i),TOURS(t, i + 1)),1) forall(i,j in CITIES | i<>j) DIST(i,j):=ceil(sqrt((X(i)-X(j))^2 + (Y(i)-Y(j))^2)) ! Objective: total distance TotalDist:= sum(i,j in CITIES | i<>j) DIST(i,j)*fly(i,j) ! Visit every city once forall(i in CITIES) sum(j in CITIES | i<>j) fly(i,j) = 1 forall(j in CITIES) sum(i in CITIES | i<>j) fly(i,j) = 1 forall(i,j in CITIES | i<>j) fly(i,j) is_binary ! Set a callback to check heuristic solutions setcallback(XPRS_CB_PREINTSOL, ->cb_preintsol) ! Set a callback to create subtour elimination constraints for integer solutions setcallback(XPRS_CB_OPTNODE, ->cb_optnode) ! Disable symmetry detection setparam("XPRS_SYMMETRY", 0) setparam("XPRS_VERBOSE", false) setparam("XPRS_TIMELIMIT", 100) ! set a time limit loadprob(TotalDist) forall(t in INITTOURS) addmipsol("InitTour_" + t, InitTours(t)) minimize(TotalDist) assert(getparam("XPRS_MIPSOLS") > 0) writeln("#E:PROC") writeln("#S:TEST") printsol writeln("#E:TEST") !----------------------------------------------------------------- ! Callback function triggered when the Optimizer has a new integer ! solution ! ! We use this function to reject any heuristic solutions that ! contain subtours. procedure cb_preintsol(isheur: boolean, cutoff: real) declarations iCity: integer nCitiesVisited: integer end-declarations ! Get the tour(s) forall(i in CITIES) forall(j in CITIES) if (getsol(fly(i,j))>=ONETOL) then NEXTC(i):=j break end-if ! Verify that we have a complete tour nCitiesVisited := 1; iCity := 1 while (NEXTC(iCity) <> 1) do iCity := NEXTC(iCity) nCitiesVisited += 1 end-do if (nCitiesVisited < NCITIES) then if isheur then rejectintsol else writeln("INVALID INTEGER SOLUTION!!!") end-if end-if end-procedure !----------------------------------------------------------------- ! Callback function triggered when a node relaxation has been ! solved to optimality and the Optimizer is about to branch or ! declare the node integer feasible. ! ! If the node is about to be declared integer feasible, we need ! to check for subtours and add at least one violated subtour ! elimination constraint. function cb_optnode: boolean declarations SUBTOUR: set of integer VISITEDCITIES: set of integer iCity: integer MipInfeas: integer ncut:integer CutRange: range ! Counter for cuts cut: array(CutRange) of linctr ! Cuts cutid: array(CutRange) of integer ! Cut type identification type: array(CutRange) of integer ! Cut constraint type end-declarations returned:=false ! Call this function once per node MipInfeas := getparam("XPRS_MIPINFEAS"); if (MipInfeas = 0) then ! There are no fractionals left in the current node solution. ! Create sub-tour elimination constraints if we do not ! have a complete tour. ncut:= 0 forall(i in CITIES) forall(j in CITIES) if(getsol(fly(i,j))>=ONETOL) then NEXTC(i):=j break end-if VISITEDCITIES := {} forall (iFirstCity in CITIES) if not iFirstCity in VISITEDCITIES then SUBTOUR := {} iCity := iFirstCity while (iCity not in SUBTOUR) do SUBTOUR += {iCity} iCity := NEXTC(iCity) end-do if (getsize(SUBTOUR) < NCITIES) then ! Create the sub-tour elimination cut(s) cutid(ncut):= 0 type(ncut):= CT_LEQ cut(ncut):= sum(i in SUBTOUR) fly(i,NEXTC(i)) - (getsize(SUBTOUR) - 1) ncut+=1 ! Optional: Also exclude the inverse subtour cutid(ncut):= 0 type(ncut):= CT_LEQ cut(ncut):= sum(i in SUBTOUR) fly(NEXTC(i),i) - (getsize(SUBTOUR) - 1) ncut+=1!) ! Optional: Add a stronger subtour elimination cut cutid(ncut):= 0 type(ncut):= CT_GEQ cut(ncut) := sum(i in SUBTOUR, j in (CITIES)-SUBTOUR) fly(i,j) - 1 ncut+=1!) end-if VISITEDCITIES += SUBTOUR end-if ! Add cuts to the problem if(ncut>0) then addcuts(cutid, type, cut); num_cuts_added+=ncut end-if end-if ! MIPINFEAS end-function !----------------------------------------------------------------- ! Print the current solution procedure printsol declarations ALLCITIES: set of integer CalcDistance: real end-declarations ! Get the final tour forall(i in CITIES) forall(j in CITIES) if (getsol(fly(i,j))>=ONETOL) then NEXTC(i):=j break end-if ! Recalculate the length of the tour CalcDistance := sum(i in 1..NCITIES) DIST(i, NEXTC(i)) writeln("Total distance: ", CalcDistance) ALLCITIES:={} forall(i in CITIES) do if (i not in ALLCITIES) then write(i) first:=i repeat ALLCITIES+={first} write(" - ", NEXTC(first)) first:=NEXTC(first) until first=i writeln end-if end-do end-procedure !----------------------------------------------------------------- end-model
| |||||||||||
© Copyright 2025 Fair Isaac Corporation. |