From b19bd8d8a41664328f33c9b459b2b0100f0b303f Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Fri, 9 Nov 2012 12:17:46 +1100 Subject: Add an MCF operator to the separate solver For the solver utility it'd be good to have MCF problems, so here they are! Format is: MCF(cost*) Supplies is a [int,int,int,...], where each int represents a new node Arcs is [int:int, int:int, int:int, ...] where each int:int pair represents an edge from the first to the second (1 indexed from the "supplies" array). Costs is the argument to the function. There must be as many costs as arcs, and they are set from left to right, in order. --- impl/OPTUtils.h | 475 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100755 impl/OPTUtils.h (limited to 'impl/OPTUtils.h') diff --git a/impl/OPTUtils.h b/impl/OPTUtils.h new file mode 100755 index 0000000..66ad4af --- /dev/null +++ b/impl/OPTUtils.h @@ -0,0 +1,475 @@ +/*--------------------------------------------------------------------------*/ +/*--------------------------- File OPTutils.h ------------------------------*/ +/*--------------------------------------------------------------------------*/ +/** @file + * Small classes are provided for: + * - reading the time of a code; + * - generating random numbers. + * + * The classes can be adapted to different environments setting a + * compile-time switch in this file. + * + * Additionally, a function is provided for safely reading parameters + * out of a stream. + * + * \version 1.00 + * + * \date 04 - 10 - 2010 + * + * \author Antonio Frangioni \n + * Operations Research Group \n + * Dipartimento di Informatica \n + * Universita' di Pisa \n + * + * Copyright © 1994 - 2010 by Antonio Frangioni + */ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ + +#ifndef __OPTutils + #define __OPTutils /* self-identification: #endif at the end of the file */ + +/*--------------------------------------------------------------------------*/ +/*----------------------------- MACROS -------------------------------------*/ +/*--------------------------------------------------------------------------*/ +/** @defgroup OPTUTILS_MACROS Compile-time switches in OPTutils.h + These macros control how the classes OPTTimers and OPTrand are + implemented; choose the appropriate value for your environment, + or program a new version if no value suits you. + Also, namespaces can be eliminated if they create problems. + @{ */ + + +/*----------------------- OPT_USE_NAMESPACES -------------------------------*/ + +#define OPT_USE_NAMESPACES 0 + +/**< Setting OPT_USE_NAMESPACES == 0 should instruct all codes that use + OPTutils stuff to avoid using namespaces; to start with, the common + namespace OPTutils_di_unipi_it, that contains all the types defined + herein, is *not* defined. */ + +/*---------------------------- OPT_TIMERS ----------------------------------*/ + +#define OPT_TIMERS 5 + +/**< The class OPTtimers is defined below to give an abstract interface to the + different timing routines that are used in different platforms. This is + needed since time-related functions are one of the less standard parts of + the C[++] library. The value of the OPT_TIMERS constant selects among the + different timing routines: + + - 1 = Use the Unix times() routine in sys/times.h + + - 2 = As 1 but uses sys/timeb.h (typical for Microsoft(TM) compilers) + + - 3 = Still use times() of sys/times.h, but return wallclock time + rather than CPU time + + - 4 = As 3 but uses sys/timeb.h (typical for Microsoft(TM) compilers) + + - 5 = return the user time obtained with ANSI C clock() function; this + may result in more accurate running times w.r.t. but may be limited + to ~ 72 hours on systems where ints are 32bits. + + - 6 = Use the Unix gettimeofday() routine of sys/time.h. + + Any unsupported value would simply make the class to report constant + zero as the time. + + The values 1 .. 4 rely on the constant CLK_TCK for converting between + clock ticks and seconds; for the case where the constant is not defined by + the compiler -- should not happen, but it does -- or it is defined in a + wrong way, the constant is re-defined below. */ + +/*---------------------------- OPT_RANDOM ---------------------------------*/ + +#define OPT_RANDOM 1 + +/**< The class OPTrand is defined below to give an abstract interface to the + different random generators that are used in different platforms. This is + needed since random generators are one of the less standard parts of the + C[++] library. The value of the OPT_RANDOM constant selects among the + different timing routines: + + - 0 = an hand-made implementation of a rather good random number generator + is used; note that this assumes that long ints >= 32 bits + + - 1 = standard rand() / srand() pair, common to all C libreries but not + very sophisticated + + - 2 = drand48() / srand48(), common on Unix architectures and pretty good. + + Any unsupported value would simply make the functions to report constant + zero, which is not nice but useful to quickly fix problems if you don't + use random numbers at all. */ + +/*@} -----------------------------------------------------------------------*/ +/*------------------------------ INCLUDES ----------------------------------*/ +/*--------------------------------------------------------------------------*/ + +#if( OPT_RANDOM ) + #include + + /* For random routines, see OPTrand() below. */ +#endif + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +#if( OPT_TIMERS <= 4 ) + #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 3 ) ) + #include + #else + #include + #endif + #include +#elif( OPT_TIMERS == 5 ) + #include +#elif( OPT_TIMERS == 6 ) + #include +#endif + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +#include +#include + +/* For istream and the >> operator, used in DfltdSfInpt(). */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + +/*--------------------------------------------------------------------------*/ +/*--------------------------- NAMESPACE ------------------------------------*/ +/*--------------------------------------------------------------------------*/ + +#if( OPT_USE_NAMESPACES ) +namespace OPTtypes_di_unipi_it +{ + /** @namespace OPTtypes_di_unipi_it + The namespace OPTtypes_di_unipi_it is defined to hold all the data + types, constants, classes and functions defined here. It also + comprises the namespace std. */ +#endif + + using namespace std; // I know it's not elegant, but ... + +/*--------------------------------------------------------------------------*/ +/*----------------------------- NULL ---------------------------------------*/ +/*--------------------------------------------------------------------------*/ + +#ifndef NULL + #define NULL 0 +#endif + +/* Curiously enough, some compilers do not always define NULL; for instance, + sometimes it is defined in stdlib.h. */ + +/*--------------------------------------------------------------------------*/ +/*---------------------------- CLK_TCK -------------------------------------*/ +/*--------------------------------------------------------------------------*/ + +#ifndef CLK_TCK + #define CLK_TCK 100 +#endif + +/* CLK_TCK is the constant used to transform (integer) time values in seconds + for times()-based routines. Its normal value is 100. */ + +/*--------------------------------------------------------------------------*/ +/*--------------------------- OPT_TIMERS -----------------------------------*/ +/*--------------------------------------------------------------------------*/ +/** @defgroup OPTtypes_CLASSES Classes in OPTutils.h + @{ */ + +#if( OPT_TIMERS ) + +/** Provides a common interface to the different timing routines that are + available in different platforms. */ + +class OPTtimers { + + public: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + /// constructor of the class + OPTtimers( void ) + { + ReSet(); + } + + /// start the timer + void Start( void ) + { + if( ! ticking ) { + #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 2 ) ) + times( &buff ); + t_u = buff.tms_utime; + t_s = buff.tms_stime; + #elif( ( OPT_TIMERS == 3 ) || ( OPT_TIMERS == 4 ) ) + t_u = times( &buff ); + #elif( OPT_TIMERS == 5 ) + t_u = clock(); + #elif( OPT_TIMERS == 6 ) + struct timeval t; + gettimeofday( &t , NULL ); + t_u = double( t.tv_sec + t.tv_usec * 1e-6 ); + #endif + + ticking = 1; + } + } + + /// stop the timer + void Stop( void ) + { + if( ticking ) { + Read( u , s ); + ticking = 0; + } + } + + /** Return the elapsed time. If the clock is ticking, return the *total* + time since the last Start() without stopping the clock; otherwise, + return the total elapsed time of all the past runs of the clock since + the last ReSet() [see below]. */ + + double Read( void ) + { + double tu = 0; + double ts = 0; + Read( tu , ts ); + return( tu + ts ); + } + + /// As Read( void ) but *adds* user and system time to tu and ts. + void Read( double &tu , double &ts ) + { + if( ticking ) { + #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 2 ) ) + times( &buff ); + tu += ( double( buff.tms_utime - t_u ) ) / double( CLK_TCK ); + ts += ( double( buff.tms_stime - t_s ) ) / double( CLK_TCK ); + #elif( ( OPT_TIMERS == 3 ) || ( OPT_TIMERS == 4 ) ) + tu += ( double( times( &buff ) - t_u ) ) / double( CLK_TCK ); + #elif( OPT_TIMERS == 5 ) + tu += ( double( clock() - t_u ) ) / double( CLOCKS_PER_SEC ); + #elif( OPT_TIMERS == 6 ) + struct timeval t; + gettimeofday( &t , NULL ); + tu += double( t.tv_sec + t.tv_usec * 1e-6 ) - t_u; + #endif + } + else { tu += u; ts += s; } + } + + /// reset the timer + void ReSet( void ) + { + u = s = 0; ticking = 0; + } + + private: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + double u; // elapsed *user* time, in seconds + double s; // elapsed *system* time, in seconds + char ticking; // 1 if the clock is ticking + + #if( ( OPT_TIMERS > 0 ) && ( OPT_TIMERS <= 5 ) ) + clock_t t_u; + + #if( OPT_TIMERS <= 4 ) + struct tms buff; + + #if( ( OPT_TIMERS == 1 ) || ( OPT_TIMERS == 3 ) ) + clock_t t_s; + #endif + #endif + #elif( OPT_TIMERS == 6 ) + double t_u; + #endif + + }; // end( class OPTtimers ); + +#endif + +/*--------------------------------------------------------------------------*/ +/*------------------------------ OPTrand() ---------------------------------*/ +/*--------------------------------------------------------------------------*/ + +/** Provide a common interface to the different random generators that are + available in different platforms. */ + +class OPTrand { + + public: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + /// constructor of the class + OPTrand( void ) + { + #if( OPT_RANDOM == 0 ) + A[ 0 ] = -1; + srand( long( 123456789 ) ); + #else + OPTrand::srand( long( 1 ) ); + #endif + } + + /** Returns a random number uniformly distributed in [0, 1). + \note each object of class OPTrand has its own sequence, so that + multiple OPTrand objects being used within the same program do not + interfere with each other (as opposed to what C random routines + would do). */ + + double rand( void ) + { + #if( OPT_RANDOM == 0 ) + long nmbr = *(gb_fptr--); + if( nmbr < 0 ) + nmbr = gb_flip_cycle(); + return( double( nmbr ) / double( (unsigned long)0x80000000 ) ); + #elif( OPT_RANDOM == 1 ) + ::srand( myseed ); + myseed = ::rand(); + return( double( myseed ) / double( RAND_MAX ) ); + #elif( OPT_RANDOM == 2 ) + return( erand48( myseed ) ); + #else + return( 0 ); // random, eh? + #endif + } + + /// Seeds the random generator for this instance of OPTrand. + void srand( long seed ) + { + #if( OPT_RANDOM == 0 ) + long prev = seed , next = 1; + seed = prev = mod_diff( prev , 0 ); + A[ 55 ] = prev; + + for( long i = 21 ; i ; i = ( i + 21 ) % 55 ) { + A[ i ] = next; + next = mod_diff( prev , next ); + if( seed & 1 ) + seed = 0x40000000 + ( seed >> 1 ); + else + seed >>= 1; + + next = mod_diff( next , seed ); + prev = A[ i ]; + } + + gb_flip_cycle(); + gb_flip_cycle(); + gb_flip_cycle(); + gb_flip_cycle(); + gb_flip_cycle(); + #elif( OPT_RANDOM == 1 ) + myseed = int( seed ); + #elif( OPT_RANDOM == 2 ) + long *sp = (long*)( &myseed ); + *sp = seed; // copy higher 32 bits + myseed[ 2 ] = 0x330E; // initialize lower 16 bits + #endif + } + + private: //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + #if( OPT_RANDOM == 0 ) + long A[ 56 ]; + long *gb_fptr; + + long mod_diff( long x , long y ) + { + return( ( ( x ) - ( y ) ) & 0x7fffffff ); + } + + long gb_flip_cycle( void ) + { + long *ii, *jj; + for( ii = &A[ 1 ] , jj = &A[ 32 ] ; jj <= &A[ 55 ] ; ii++ , jj++ ) + *ii = mod_diff( *ii , *jj ); + + for( jj = &A[ 1 ] ; ii <= &A[ 55 ] ; ii++ , jj++ ) + *ii = mod_diff( *ii , *jj ); + + gb_fptr = &A[ 54 ]; + + return A[ 55 ]; + } + #elif( OPT_RANDOM == 1 ) + int myseed; + #elif( OPT_RANDOM == 2 ) + unsigned short int myseed[ 3 ]; + #endif + + }; // end( class( OPTrand ) ) + +/* @} end( group( OPTtypes_CLASSES ) ) */ +/*--------------------------------------------------------------------------*/ +/*--------------------------- DfltdSfInpt() --------------------------------*/ +/*--------------------------------------------------------------------------*/ +/** @defgroup OPTtypes_FUNCTIONS Functions in OPTutils.h + @{ */ + +/** Template function for reading parameters from a istream. The function is + "safe" because it works also if the istream is not given, is not be long + enough or contains erroneous things. + + Given a &istream (possibly NULL), DfltdSfInpt() attempts to read Param out + of it, skipping any line that begins with the comment carachter (defaulted + to '#'), any blank line and any line starting with anything that can not + be interpreted as a `T'. If, for any reason, the read operation fails, + then the parameter is given the default value `Dflt'. Otherwise, all the + rest of the line up to the nearest newline ('\n') carachter is flushed. */ + +template +inline void DfltdSfInpt( istream *iStrm , T &Param , const T Dflt , + const char cmntc = '#' ) +{ + string comm( 1 , cmntc ); + + // the "! ! stream" trick is there to force the compiler to apply the + // stream -> bool conversion, in case it is too dumb to do it by itself + if( iStrm && ( ! ( ! (*iStrm) ) ) ) { + string buf; + + for( ;; ) { + if( ! ( (*iStrm) >> ws ) ) // skip whitespace + break; + + if( ! (*iStrm).good() ) // check stream is OK + break; + + getline( *iStrm , buf ); + + if( ! buf.empty() ) + if( buf.substr( 0 , 1 ).compare( comm ) ) { + stringstream ss; + ss << buf; + if( ! ( ss >> Param ) ) + break; + + return; + } + } + } + + Param = Dflt; + + } // end( DfltdSfInpt ) + +/* @} end( group( OPTtypes_FUNCTIONS ) ) */ +/*--------------------------------------------------------------------------*/ + +#if( OPT_USE_NAMESPACES ) + }; // end( namespace OPTtypes_di_unipi_it ) +#endif + +/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------*/ + +#endif /* OPTutils.h included */ + +/*--------------------------------------------------------------------------*/ +/*---------------------- End File OPTutils.h -------------------------------*/ +/*--------------------------------------------------------------------------*/ -- cgit v1.2.3