<commit_before>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "simple_logger.hpp"

#include "OSRMException.h"

#include <boost/assert.hpp>

#include <cstdio>

#ifdef _MSC_VER
#include <io.h>
#define isatty _isatty
#define fileno _fileno
#else
#include <unistd.h>
#endif

#include <ostream>
#include <iostream>
#include <mutex>

namespace
{
static const char COL_RESET[] { "\x1b[0m"};
static const char RED[] { "\x1b[31m"};
#ifndef NDEBUG
static const char YELLOW[] { "\x1b[33m"};
#endif
// static const char GREEN[] { "\x1b[32m"};
// static const char BLUE[] { "\x1b[34m"};
// static const char MAGENTA[] { "\x1b[35m"};
// static const char CYAN[] { "\x1b[36m"};
}

void LogPolicy::Unmute() { m_is_mute = false; }

void LogPolicy::Mute() { m_is_mute = true; }

bool LogPolicy::IsMute() const { return m_is_mute; }

LogPolicy &LogPolicy::GetInstance()
{
    static LogPolicy runningInstance;
    return runningInstance;
}

SimpleLogger::SimpleLogger() : level(logINFO) {}

std::mutex &SimpleLogger::get_mutex()
{
    static std::mutex m;
    return m;
}

std::ostringstream &SimpleLogger::Write(LogLevel l)
{
    std::lock_guard<std::mutex> lock(get_mutex());
    try
    {
        level = l;
        os << "[";
        switch (level)
        {
        case logINFO:
            os << "info";
            break;
        case logWARNING:
            os << "warn";
            break;
        case logDEBUG:
#ifndef NDEBUG
            os << "debug";
#endif
            break;
        default:
            throw OSRMException("unkown logging state");
            break;
        }
        os << "] ";
    }
    catch (...)
    {
    }
    return os;
}

SimpleLogger::~SimpleLogger()
{
    std::lock_guard<std::mutex> lock(get_mutex());
    if (!LogPolicy::GetInstance().IsMute())
    {
        const bool is_terminal = (0 != isatty(fileno(stdout)) ? true : false);
        switch (level)
        {
        case logINFO:
            std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
            break;
        case logWARNING:
            std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "")
                      << std::endl;
            break;
        case logDEBUG:
#ifndef NDEBUG
            std::cout << (is_terminal ? YELLOW : "") << os.str() << (is_terminal ? COL_RESET : "")
                      << std::endl;
#endif
            break;
        default:
            throw OSRMException("unkown logging state");
            break;
        }
    }
}
<commit_msg>rethrow exception, refactor default block in fully covered switch statement<commit_after>/*

Copyright (c) 2013, Project OSRM, Dennis Luxen, others
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this list
of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*/

#include "simple_logger.hpp"

#include "OSRMException.h"

#include <boost/assert.hpp>

#include <cstdio>

#ifdef _MSC_VER
#include <io.h>
#define isatty _isatty
#define fileno _fileno
#else
#include <unistd.h>
#endif

#include <ostream>
#include <iostream>
#include <mutex>

namespace
{
static const char COL_RESET[] { "\x1b[0m"};
static const char RED[] { "\x1b[31m"};
#ifndef NDEBUG
static const char YELLOW[] { "\x1b[33m"};
#endif
// static const char GREEN[] { "\x1b[32m"};
// static const char BLUE[] { "\x1b[34m"};
// static const char MAGENTA[] { "\x1b[35m"};
// static const char CYAN[] { "\x1b[36m"};
}

void LogPolicy::Unmute() { m_is_mute = false; }

void LogPolicy::Mute() { m_is_mute = true; }

bool LogPolicy::IsMute() const { return m_is_mute; }

LogPolicy &LogPolicy::GetInstance()
{
    static LogPolicy runningInstance;
    return runningInstance;
}

SimpleLogger::SimpleLogger() : level(logINFO) {}

std::mutex &SimpleLogger::get_mutex()
{
    static std::mutex m;
    return m;
}

std::ostringstream &SimpleLogger::Write(LogLevel l)
{
    std::lock_guard<std::mutex> lock(get_mutex());
    try
    {
        level = l;
        os << "[";
        switch (level)
        {
        case logWARNING:
            os << "warn";
            break;
        case logDEBUG:
#ifndef NDEBUG
            os << "debug";
#endif
            break;
        default: //logINFO:
            os << "info";
            break;
        }
        os << "] ";
    }
    catch (const std::exception &e)
    {
        // encapsulate in OSRMException
        throw OSRMException(std::string(e.what()) + ", getting ostringstream");
    }
    return os;
}

SimpleLogger::~SimpleLogger()
{
    std::lock_guard<std::mutex> lock(get_mutex());
    if (!LogPolicy::GetInstance().IsMute())
    {
        const bool is_terminal = (0 != isatty(fileno(stdout)) ? true : false);
        switch (level)
        {
        case logWARNING:
            std::cerr << (is_terminal ? RED : "") << os.str() << (is_terminal ? COL_RESET : "")
                      << std::endl;
            break;
        case logDEBUG:
#ifndef NDEBUG
            std::cout << (is_terminal ? YELLOW : "") << os.str() << (is_terminal ? COL_RESET : "")
                      << std::endl;
#endif
            break;
        default: //logINFO:
            std::cout << os.str() << (is_terminal ? COL_RESET : "") << std::endl;
            break;
        }
    }
}
<|endoftext|>


<commit_before>/*
    <one line to give the library's name and an idea of what it does.>
    Copyright (C) 2013  Carlos A. Morales <carlos.morales@playfulplay.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "Notification.h"

Notification::Notification() :  notify("libnotify.so")
{

    this->message =
        ( Message *) notify.resolve("NotifyNotification");
    this->init =
        (NotificationInit)  notify.resolve( "notify_init");
    this->dialog=
        (NotificationDialog)  notify.resolve("notify_notification_new");
    this->category =
        (NotificationCategory)  notify.resolve("notify_notification_set_category");
    this->timeout =
        (NotificationTimeout)  notify.resolve("notify_notification_set_timeout");
    this->send =
        (NotificationShow)  notify.resolve( "notify_notification_show");

    this->lib = LibNotify;/*
    } else {
        qDebug() << "load none";
        lib = None;
    }*/
  //  qDebug() << "ran notification constructor";

}

Notification::~Notification()
{

}

FreedesktopNotificationType Notification::getLib(){
    return this->lib;
}

	/**
	* to be used when the desktop supports pointer events
	*/
void Notification::clickHandler()
{

}

void Notification::sendNotification(QString title,QString msg)
{
    if (lib == LibNotify){
		this->init("prueba esta");

		this->message = ( Message *)dialog(title.toStdString().data(), msg.toStdString().data(),"probando");

		this->timeout(message, 3000);

		this->send(message,NULL);

	}

}

#include "Notification.moc"
<commit_msg>fix libNotify load detection, sends notification via qDebug if no lib is detected.<commit_after>/*
    <one line to give the library's name and an idea of what it does.>
    Copyright (C) 2013  Carlos A. Morales <carlos.morales@playfulplay.com>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "Notification.h"

Notification::Notification() :  notify("libnotify.so")
{

    this->message =
        ( Message *) notify.resolve("NotifyNotification");
    this->init =
        (NotificationInit)  notify.resolve( "notify_init");
    this->dialog=
        (NotificationDialog)  notify.resolve("notify_notification_new");
    this->category =
        (NotificationCategory)  notify.resolve("notify_notification_set_category");
    this->timeout =
        (NotificationTimeout)  notify.resolve("notify_notification_set_timeout");
    this->send =
        (NotificationShow)  notify.resolve( "notify_notification_show");

    if(this->notify.isLoaded()) {
        this->lib = LibNotify;
    } else {
        qDebug() << "load none";
        this->lib = None;
    }
  //  qDebug() << "ran notification constructor";

}

Notification::~Notification()
{

}

FreedesktopNotificationType Notification::getLib(){
    return this->lib;
}

	/**
	* to be used when the desktop supports pointer events
	*/
void Notification::clickHandler()
{

}

void Notification::sendNotification(QString title,QString msg)
{
    if (this->lib == LibNotify){
		this->init("prueba esta");

		this->message = ( Message *)dialog(title.toStdString().data(), msg.toStdString().data(),"probando");

		this->timeout(message, 3000);

		this->send(message,NULL);

	}

}

#include "Notification.moc"
<|endoftext|>


<commit_before>#include "NetworkDetect.h"

INetworkDetection* NetworkDetectionFactory::createNetworkDetection() {
    return new CNetworkDetection();
}

void CNetworkDetection::Cleanup()
{
    stop(1000);

	WSACleanup();
}

void CNetworkDetection::Startup()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
}

/**
* \author	Darryn Campbell (DCC, JRQ768)
* \date		August 2011 (Initial Creation)
*/
void CNetworkDetection::CheckConnectivity()
{
	bool bConnectSuccessful = false;
	struct addrinfo hints, *result = NULL, *ptr = NULL;
	SOCKET sockfd = INVALID_SOCKET;
	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	char szPortAsString[5 + 1];
	_itoa(m_iPort, szPortAsString, 10);
	char* szHost = new char[m_szHost.length() + 1];
	memset(szHost, 0, m_szHost.length() + 1);
	strcpy(szHost, m_szHost.c_str());
	int iResult = getaddrinfo(szHost, szPortAsString, &hints, &result);
	if (iResult != 0)
	{
		//  Log the Fact that we can't get the addr info
		int iErr = WSAGetLastError();
		m_szLastError = "Attempted to resolve hostname to connect to but did not succeed, return value (" + itos(iResult) +
			"), last error (" + itos(iErr) + ")";
		LOG(INFO) + m_szLastError;
	}
	else
	{
		ptr=result;
		sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

		if (sockfd == INVALID_SOCKET)
		{
			int iErr = WSAGetLastError();
			m_szLastError = "Unable to create communications socket, last error was " + itos(iErr);
			LOG(INFO) + m_szLastError;
		}
		else
		{
			//  Make the Socket Non Blocking
			u_long iNonBlock = 1;
			int iNonBlockRes = ioctlsocket(sockfd, FIONBIO, &iNonBlock);
			if (iNonBlockRes != NO_ERROR)
			{
				m_szLastError = "Error setting socket into Non Blocking mode";
				LOG(INFO) + m_szLastError;
			}
			else
			{
				int iConnectSuccess = connect(sockfd, ptr->ai_addr, ptr->ai_addrlen);

#if defined(OS_WINCE)
                if (iConnectSuccess == SOCKET_ERROR)
#else
				//  Because Socket is non blocking we expect it to return SOCKET_ERROR
				//  and WSAGetLastError() would be WSAEWOULDBLOCK
                if (!(iConnectSuccess == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK))
#endif
				{
					m_szLastError = "Socket Operation unexpectedly blocked, are you connected to a PC?";
					LOG(WARNING) + m_szLastError;
				}
				else
				{
					fd_set WriteFDs;
					FD_ZERO(&WriteFDs);
					FD_SET(sockfd, &WriteFDs);
					int iSelectReturnVal = select(0, 0, &WriteFDs, 0, &m_connectionTimeout);
					if (iSelectReturnVal > 0)
					{
						//  We have a socket to connect to
						bConnectSuccessful = true;
					}
					else if (iSelectReturnVal == 0)
					{
						m_szLastError = "Unable to connect to specified host " + m_szHost + " on port " + itos(m_iPort);
						LOG(INFO) + m_szLastError;
					}
					else
					{
						//  Some form of error occured
						int iErr = WSAGetLastError();
						m_szLastError = "Unable to connect to specified host, last error was " + itos(iErr);
						LOG(INFO) + m_szLastError;
					}
				}
			}
			closesocket(sockfd);
			sockfd = INVALID_SOCKET;
		}
	}
	delete[] szHost;
    if (result != 0)
    {
	    freeaddrinfo(result);
    }
	if (bConnectSuccessful)
	{
		if (m_NetworkState != NETWORK_CONNECTED)
		{
			m_NetworkState = NETWORK_CONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Connected");
			detectedCallbackData.put("failureMessage", "Connected");
			m_pDetectCallback.set(detectedCallbackData);
		}
	}
	else
	{
		//  We are not connected
		if (m_NetworkState != NETWORK_DISCONNECTED)
		{
			m_NetworkState = NETWORK_DISCONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Disconnected");
			detectedCallbackData.put("failureMessage", m_szLastError);
			m_pDetectCallback.set(detectedCallbackData);
		}
	}
}

<commit_msg>Reverting change to test that socket would block<commit_after>#include "NetworkDetect.h"

INetworkDetection* NetworkDetectionFactory::createNetworkDetection() {
    return new CNetworkDetection();
}

void CNetworkDetection::Cleanup()
{
    stop(1000);

	WSACleanup();
}

void CNetworkDetection::Startup()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);
}

/**
* \author	Darryn Campbell (DCC, JRQ768)
* \date		August 2011 (Initial Creation)
*/
void CNetworkDetection::CheckConnectivity()
{
	bool bConnectSuccessful = false;
	struct addrinfo hints, *result = NULL, *ptr = NULL;
	SOCKET sockfd = INVALID_SOCKET;
	ZeroMemory(&hints, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;
	char szPortAsString[5 + 1];
	_itoa(m_iPort, szPortAsString, 10);
	char* szHost = new char[m_szHost.length() + 1];
	memset(szHost, 0, m_szHost.length() + 1);
	strcpy(szHost, m_szHost.c_str());
	int iResult = getaddrinfo(szHost, szPortAsString, &hints, &result);
	if (iResult != 0)
	{
		//  Log the Fact that we can't get the addr info
		int iErr = WSAGetLastError();
		m_szLastError = "Attempted to resolve hostname to connect to but did not succeed, return value (" + itos(iResult) +
			"), last error (" + itos(iErr) + ")";
		LOG(INFO) + m_szLastError;
	}
	else
	{
		ptr=result;
		sockfd = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol);

		if (sockfd == INVALID_SOCKET)
		{
			int iErr = WSAGetLastError();
			m_szLastError = "Unable to create communications socket, last error was " + itos(iErr);
			LOG(INFO) + m_szLastError;
		}
		else
		{
			//  Make the Socket Non Blocking
			u_long iNonBlock = 1;
			int iNonBlockRes = ioctlsocket(sockfd, FIONBIO, &iNonBlock);
			if (iNonBlockRes != NO_ERROR)
			{
				m_szLastError = "Error setting socket into Non Blocking mode";
				LOG(INFO) + m_szLastError;
			}
			else
			{
				int iConnectSuccess = connect(sockfd, ptr->ai_addr, ptr->ai_addrlen);

//#if defined(OS_WINCE)
//                if (iConnectSuccess == SOCKET_ERROR)
//#else
				//  Because Socket is non blocking we expect it to return SOCKET_ERROR
				//  and WSAGetLastError() would be WSAEWOULDBLOCK
                if (!(iConnectSuccess == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK))
//#endif
				{
					m_szLastError = "Socket Operation unexpectedly blocked, are you connected to a PC?";
					LOG(WARNING) + m_szLastError;
				}
				else
				{
					fd_set WriteFDs;
					FD_ZERO(&WriteFDs);
					FD_SET(sockfd, &WriteFDs);
					int iSelectReturnVal = select(0, 0, &WriteFDs, 0, &m_connectionTimeout);
					if (iSelectReturnVal > 0)
					{
						//  We have a socket to connect to
						bConnectSuccessful = true;
					}
					else if (iSelectReturnVal == 0)
					{
						m_szLastError = "Unable to connect to specified host " + m_szHost + " on port " + itos(m_iPort);
						LOG(INFO) + m_szLastError;
					}
					else
					{
						//  Some form of error occured
						int iErr = WSAGetLastError();
						m_szLastError = "Unable to connect to specified host, last error was " + itos(iErr);
						LOG(INFO) + m_szLastError;
					}
				}
			}
			closesocket(sockfd);
			sockfd = INVALID_SOCKET;
		}
	}
	delete[] szHost;
    if (result != 0)
    {
	    freeaddrinfo(result);
    }
	if (bConnectSuccessful)
	{
		if (m_NetworkState != NETWORK_CONNECTED)
		{
			m_NetworkState = NETWORK_CONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Connected");
			detectedCallbackData.put("failureMessage", "Connected");
			m_pDetectCallback.set(detectedCallbackData);
		}
	}
	else
	{
		//  We are not connected
		if (m_NetworkState != NETWORK_DISCONNECTED)
		{
			m_NetworkState = NETWORK_DISCONNECTED;
			rho::Hashtable<rho::String, rho::String> detectedCallbackData;
			detectedCallbackData.put("connectionInformation", "Disconnected");
			detectedCallbackData.put("failureMessage", m_szLastError);
			m_pDetectCallback.set(detectedCallbackData);
		}
	}
}

<|endoftext|>


<commit_before>/****************************************************************************/
/*                                                                          */
/*              CO759: Model for HW2, TSP via Subtour Cuts                  */
/*              Date:  January 27, 2015                                     */
/*                                                                          */
/****************************************************************************/

#include <cstdio>
#include <cstdlib>
#include <getopt.h>
#include <cmath>
#include <cplex.h>
#include "lp.h"
#include "util.h"
#include <iostream>

static void usage (char *f);
static int getprob (char *fname, int *p_ncount, int *p_ecount, int **p_elist,
    int **p_elen);
static int parseargs (int ac, char **av);
static int subtour (int ncount, int ecount, int *elist, int *elen, int *tlist);
static int euclid_edgelen (int i, int j, double *x, double *y);

static int solve(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist);
static int connect(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist);

static char *fname = (char *) NULL;
static int debug = 0;
static int seed = 0;
static int geometric_data = 0;
static int TVAL = 10000000;

int main (int ac, char **av)
{
    int rval  = 0, ncount = 0, ecount = 0;
    int *elist = (int *) NULL, *elen = (int *) NULL, *tlist = (int *) NULL;
    double szeit, wt;

    seed = (int) CO759_real_zeit ();

    rval = parseargs (ac, av);
    if (rval) goto CLEANUP;

    printf ("Problem name: %s\n", fname);
    printf ("Seed = %d\n", seed);
    if (debug)  printf ("Debugging turned on\n");
    if (geometric_data) printf ("Geomtric data\n");

    rval = getprob (fname, &ncount, &ecount, &elist, &elen);
    if (rval) {
        fprintf (stderr, "getprob failed\n");
        goto CLEANUP;
    }

    tlist = (int *) malloc ((ncount)*sizeof (int));
    if (!tlist) {
        fprintf (stderr, "out of memory for tlist\n");
        rval = 1;  goto CLEANUP;
    }

    szeit = CO759_zeit ();
    rval = subtour (ncount, ecount, elist, elen, tlist);
    if (rval) {
        fprintf (stderr, "subtour failed\n");
        goto CLEANUP;
    }
    printf ("Running Time: %.2f seconds\n", CO759_zeit() - szeit);
    fflush (stdout);

    wt = 0.0;
    printf ("Optimal Tour: %.0f\n", wt); fflush (stdout);

CLEANUP:

    if (tlist) free (tlist);
    if (elist) free (elist);
    if (elen) free (elen);
    return rval;
}

#define LP_EPSILON 0.000001

static int subtour (int ncount, int ecount, int *elist, int *elen, int *tlist)
{
    int rval = 0, i, j, infeasible = 0;
    double  obj[1], lb[1], ub[1], objval, *x = (double *) NULL;
    int     cmatbeg[1], cmatind[2];
    double  cmatval[2];
    CO759lp lp;

    rval = CO759lp_init (&lp);
    if (rval) { fprintf (stderr, "CO759lp_init failed\n"); goto CLEANUP; }

    rval = CO759lp_create (&lp, "subtour");
    if (rval) { fprintf (stderr, "CO759lp_create failed\n"); goto CLEANUP; }

    /* Build a row for each degree equation */

    for (i = 0; i < ncount; i++) {
        rval = CO759lp_new_row (&lp, 'E', 2.0);
        if (rval) {
            fprintf (stderr, "CO759lp_new_row failed\n"); goto CLEANUP;
        }
    }

    /* Build a column for each edge of the graph */

    cmatbeg[0] = 0;
    cmatval[0] = 1.0;
    cmatval[1] = 1.0;
    for (j = 0; j < ecount; j++) {
        obj[0]     = (double) elen[j];
        lb[0]      = 0.0;
        ub[0]      = 1.0;
        cmatind[0] = elist[2*j];
        cmatind[1] = elist[2*j+1];
        rval = CO759lp_addcols (&lp, 1 /* # of new variables */,
           2 /* # of new nonzeros */, obj, cmatbeg, cmatind, cmatval, lb, ub);
        if (rval) {
            fprintf (stderr, "CClp_addcols failed\n"); goto CLEANUP;
        }
    }

    rval = CO759lp_write (&lp, "subtour.lp");
    if (rval) {
        fprintf (stderr, "CO759lp_write failed\n"); goto CLEANUP;
    }

    rval = CO759lp_opt (&lp, &infeasible);
    if (rval) {
        fprintf (stderr, "CO759lp_opt failed\n"); goto CLEANUP;
    }
    if (infeasible) {
        fprintf (stderr, "LP is infeasible\n");
        rval = 1; goto CLEANUP;
    }

    rval = CO759lp_objval (&lp, &objval);
    if (rval) {
        fprintf (stderr, "CO759lp_objval failed\n"); goto CLEANUP;
    }

    printf ("Degree-Equation LP Value: %f\n", objval);
    fflush (stdout);

    x = (double *) malloc (ecount * sizeof (double));
    if (!x) {
        fprintf (stderr, "out of memory for x\n");
        rval = 1; goto CLEANUP;
    }

    rval = CO759lp_x (&lp, x);
    if (rval) {
        fprintf (stderr, "CO759lp_x failed\n"); goto CLEANUP;
    }

    for (i = 0, j = 0; j < ecount; j++) {
        if (x[j] > LP_EPSILON) i++;
    }

    printf ("LP graph has %d edges\n", i);
    for (j = 0; j < ecount; j++) {
        if (x[j] > LP_EPSILON) {
            printf ("%d %d %f\n", elist[2*j], elist[2*j+1], x[j]);
        }
    }
    fflush (stdout);

	solve(&lp,ncount,ecount,elist,elen,tlist);

CLEANUP:
    CO759lp_free (&lp);
    if (x) free (x);
    return rval;
}

static int solve(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist) {
	double * x;
	int i, frac = -1, rval;
	int bound = connect(lp,ncount,ecount,elist,elen,tlist);
	if( bound >= TVAL ) {
		return 0;
	} else {
		x = new double[ecount];
		if( !x ) {
			std::cerr << "out of memory for x" << std::endl;
			return 1;
		}
		rval = CO759lp_x(lp, x);
		if(rval) {
			std::cerr << "CO759lp_x failed" << std::endl;
		}

		for(i = 0; i < ecount; i++ ) {
			if( x[i] > LP_EPSILON && x[i] < (1-LP_EPSILON) ) {
				std::cout << "Fractional edge " << elist[2*i] << " " << elist[2*i+1] << " " << x[i] << std::endl;
				frac = i;
				break;
			}
		}
		if( frac == -1 ) {
			std::cerr << "No fractional edge found" << std::endl;
			return 2;
		}

	}

	return 0;
}

static int connect(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist) {
	return 0;
}

static int getprob (char *filename, int *p_ncount, int *p_ecount, int **p_elist,
    int **p_elen)
{
    FILE *f = (FILE *) NULL;
    int i, j, end1, end2, w, rval = 0, ncount, ecount;
    int *elist = (int *) NULL, *elen = (int *) NULL;
    double *x = (double *) NULL, *y = (double *) NULL;

    if ((f = fopen (filename, "r")) == NULL) {
	fprintf (stderr, "Unable to open %s for input\n",filename);
        rval = 1;  goto CLEANUP;
    }

    if (geometric_data == 0) {
        if (fscanf (f, "%d %d", &ncount, &ecount) != 2) {
       	    fprintf (stderr, "Input file %s has invalid format\n",filename);
            rval = 1;  goto CLEANUP;
        }

        printf ("Nodes: %d  Edges: %d\n", ncount, ecount);
        fflush (stdout);

        elist = (int *) malloc (2 * ecount * sizeof (int));
        if (!elist) {
            fprintf (stderr, "out of memory for elist\n");
            rval = 1;  goto CLEANUP;
        }

        elen = (int *) malloc (ecount * sizeof (int));
        if (!elen) {
            fprintf (stderr, "out of memory for elen\n");
            rval = 1;  goto CLEANUP;
        }

        for (i = 0; i < ecount; i++) {
    	    if (fscanf(f,"%d %d %d",&end1, &end2, &w) != 3) {
	        fprintf (stderr, "%s has invalid input format\n", filename);
                rval = 1;  goto CLEANUP;
	    }
	    elist[2*i] = end1;
	    elist[2*i+1] = end2;
	    elen[i] = w;
        }
    } else {
        if (fscanf (f, "%d", &ncount) != 1) {
       	    fprintf (stderr, "Input file %s has invalid format\n",filename);
            rval = 1;  goto CLEANUP;
        }

        x = (double *) malloc (ncount * sizeof (double));
        y = (double *) malloc (ncount * sizeof (double));
        if (!x || !y) {
            fprintf (stdout, "out of memory for x or y\n");
            rval = 1; goto CLEANUP;
        }

        for (i = 0; i < ncount; i++) {
    	    if (fscanf(f,"%lf %lf",&x[i], &y[i]) != 2) {
	        fprintf (stderr, "%s has invalid input format\n", filename);
                rval = 1;  goto CLEANUP;
	    }
        }

        ecount = (ncount * (ncount - 1)) / 2;
        printf ("Complete graph: %d nodes, %d edges\n", ncount, ecount);

        elist = (int *) malloc (2 * ecount * sizeof (int));
        if (!elist) {
            fprintf (stderr, "out of memory for elist\n");
            rval = 1;  goto CLEANUP;
        }

        elen = (int *) malloc (ecount * sizeof (int));
        if (!elen) {
            fprintf (stderr, "out of memory for elen\n");
            rval = 1;  goto CLEANUP;
        }

        ecount = 0;
        for (i = 0; i < ncount; i++) {
            for (j = i+1; j < ncount; j++) {
                elist[2*ecount] = i;
                elist[2*ecount+1] = j;
                elen[ecount] = euclid_edgelen (i, j, x, y);
                ecount++;
            }
        }
    }

    *p_ncount = ncount;
    *p_ecount = ecount;
    *p_elist = elist;
    *p_elen = elen;

CLEANUP:
    if (f) fclose (f);
    if (x) free (x);
    if (y) free (y);
    return rval;
}

static int euclid_edgelen (int i, int j, double *x, double *y)
{
    double t1 = x[i] - x[j], t2 = y[i] - y[j];
    return (int) (sqrt (t1 * t1 + t2 * t2) + 0.5);
}

static int parseargs (int ac, char **av)
{
    int c;

    while ((c = getopt (ac, av, "dgs:")) != EOF) {
        switch (c) {
        case 'd':
            debug = 1;
            break;
        case 'g':
            geometric_data = 1;
            break;
        case 's':
            seed = atoi (optarg);
            break;
        case '?':
        default:
            usage (av[0]);
            return 1;
        }
    }

    if (optind >= ac) {
        usage (av[0]);
        return 1;
    }
    fname = av[optind++];

    return 0;
}

static void usage (char *f)
{
    fprintf (stderr, "Usage: %s prob_file\n", f);
    fprintf (stderr, "   -d    turn on debugging\n");
    fprintf (stderr, "   -g    prob_file has x-y coordinates\n");
    fprintf (stderr, "   -s d  random seed\n");
}

<commit_msg>nearest neighbor tour<commit_after>/****************************************************************************/
/*                                                                          */
/*              CO759: Model for HW2, TSP via Subtour Cuts                  */
/*              Date:  January 27, 2015                                     */
/*                                                                          */
/****************************************************************************/

#include <cstdio>
#include <cstdlib>
#include <getopt.h>
#include <cmath>
#include <cplex.h>
#include "lp.h"
#include "util.h"
#include <iostream>

static void usage (char *f);
static int getprob (char *fname, int *p_ncount, int *p_ecount, int **p_elist,
    int **p_elen);
static int parseargs (int ac, char **av);
static int subtour (int ncount, int ecount, int *elist, int *elen, int *tlist);
static int euclid_edgelen (int i, int j, double *x, double *y);

static int solve(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist);
static int connect(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist);

static char *fname = (char *) NULL;
static int debug = 0;
static int seed = 0;
static int geometric_data = 0;
static int TVAL = 10000000;

int main (int ac, char **av)
{
    int rval  = 0, ncount = 0, ecount = 0;
    int *elist = (int *) NULL, *elen = (int *) NULL, *tlist = (int *) NULL;
    double szeit, wt;

    seed = (int) CO759_real_zeit ();

    rval = parseargs (ac, av);
    if (rval) goto CLEANUP;

    printf ("Problem name: %s\n", fname);
    printf ("Seed = %d\n", seed);
    if (debug)  printf ("Debugging turned on\n");
    if (geometric_data) printf ("Geomtric data\n");

    rval = getprob (fname, &ncount, &ecount, &elist, &elen);
    if (rval) {
        fprintf (stderr, "getprob failed\n");
        goto CLEANUP;
    }

    tlist = (int *) malloc ((ncount)*sizeof (int));
    if (!tlist) {
        fprintf (stderr, "out of memory for tlist\n");
        rval = 1;  goto CLEANUP;
    }

    szeit = CO759_zeit ();
    rval = subtour (ncount, ecount, elist, elen, tlist);
    if (rval) {
        fprintf (stderr, "subtour failed\n");
        goto CLEANUP;
    }
    printf ("Running Time: %.2f seconds\n", CO759_zeit() - szeit);
    fflush (stdout);

    wt = 0.0;
    printf ("Optimal Tour: %.0f\n", wt); fflush (stdout);

CLEANUP:

    if (tlist) free (tlist);
    if (elist) free (elist);
    if (elen) free (elen);
    return rval;
}

#define LP_EPSILON 0.000001

static int subtour (int ncount, int ecount, int *elist, int *elen, int *tlist)
{
    int rval = 0, i, j, infeasible = 0;
    double  obj[1], lb[1], ub[1], objval, *x = (double *) NULL;
    int     cmatbeg[1], cmatind[2];
    double  cmatval[2];
    CO759lp lp;

    rval = CO759lp_init (&lp);
    if (rval) { fprintf (stderr, "CO759lp_init failed\n"); goto CLEANUP; }

    rval = CO759lp_create (&lp, "subtour");
    if (rval) { fprintf (stderr, "CO759lp_create failed\n"); goto CLEANUP; }

    /* Build a row for each degree equation */

    for (i = 0; i < ncount; i++) {
        rval = CO759lp_new_row (&lp, 'E', 2.0);
        if (rval) {
            fprintf (stderr, "CO759lp_new_row failed\n"); goto CLEANUP;
        }
    }

    /* Build a column for each edge of the graph */

    cmatbeg[0] = 0;
    cmatval[0] = 1.0;
    cmatval[1] = 1.0;
    for (j = 0; j < ecount; j++) {
        obj[0]     = (double) elen[j];
        lb[0]      = 0.0;
        ub[0]      = 1.0;
        cmatind[0] = elist[2*j];
        cmatind[1] = elist[2*j+1];
        rval = CO759lp_addcols (&lp, 1 /* # of new variables */,
           2 /* # of new nonzeros */, obj, cmatbeg, cmatind, cmatval, lb, ub);
        if (rval) {
            fprintf (stderr, "CClp_addcols failed\n"); goto CLEANUP;
        }
    }

    rval = CO759lp_write (&lp, "subtour.lp");
    if (rval) {
        fprintf (stderr, "CO759lp_write failed\n"); goto CLEANUP;
    }

    rval = CO759lp_opt (&lp, &infeasible);
    if (rval) {
        fprintf (stderr, "CO759lp_opt failed\n"); goto CLEANUP;
    }
    if (infeasible) {
        fprintf (stderr, "LP is infeasible\n");
        rval = 1; goto CLEANUP;
    }

    rval = CO759lp_objval (&lp, &objval);
    if (rval) {
        fprintf (stderr, "CO759lp_objval failed\n"); goto CLEANUP;
    }

    printf ("Degree-Equation LP Value: %f\n", objval);
    fflush (stdout);

    x = (double *) malloc (ecount * sizeof (double));
    if (!x) {
        fprintf (stderr, "out of memory for x\n");
        rval = 1; goto CLEANUP;
    }

    rval = CO759lp_x (&lp, x);
    if (rval) {
        fprintf (stderr, "CO759lp_x failed\n"); goto CLEANUP;
    }

    for (i = 0, j = 0; j < ecount; j++) {
        if (x[j] > LP_EPSILON) i++;
    }

    printf ("LP graph has %d edges\n", i);
    for (j = 0; j < ecount; j++) {
        if (x[j] > LP_EPSILON) {
            printf ("%d %d %f\n", elist[2*j], elist[2*j+1], x[j]);
        }
    }
    fflush (stdout);
    TVAL = nntour(ncount,ecount,elist,elen,tlist);
    solve(&lp,ncount,ecount,elist,elen,tlist);

CLEANUP:
    CO759lp_free (&lp);
    if (x) free (x);
    return rval;
}
// elist - array 2*ecount
// elist[2*i] is end0 of ith edge
// elist[2*i+1] is end1 of ith edge
// elen - array ecount
// elen[i] is length of ith edge
int nntour(int ncount, int ecount, int *elist, int *elen, int *tlist)
{
    int tour_len = 0;
    int start = 0;
    int marks = new double[ecount];
    int i, j, best, bestend, end = start, len = 0;

    for (i = 0; i < ncount; i++) marks[i] = 0;
    tour_len += elen[end];
    for (i = 1; i < ncount; i++) {
        marks[end] = 1;
        best = TVAL;
        for (j = 0; j < ncount; j++) {
            if (marks[j] == 0 && elen[j] < best) {
                best = elen[j]; bestend = j;
            }
        }
        len += best; end = bestend; tour_len += elen[end];
    }
    return tour_len;
}

static int solve(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist) {
	double * x;
	int i, frac = -1, rval;
	int bound = connect(lp,ncount,ecount,elist,elen,tlist);
	if( bound >= TVAL ) {
		return 0;
	} else {
		x = new double[ecount];
		if( !x ) {
			std::cerr << "out of memory for x" << std::endl;
			return 1;
		}
		rval = CO759lp_x(lp, x);
		if(rval) {
			std::cerr << "CO759lp_x failed" << std::endl;
		}

		for(i = 0; i < ecount; i++ ) {
			if( x[i] > LP_EPSILON && x[i] < (1-LP_EPSILON) ) {
				std::cout << "Fractional edge " << elist[2*i] << " " << elist[2*i+1] << " " << x[i] << std::endl;
				frac = i;
				break;
			}
		}
		if( frac == -1 ) {
			std::cerr << "No fractional edge found" << std::endl;
			return 2;
		}

	}

	return 0;
}

static int connect(CO759lp * lp, int ncount, int ecount, int *elist, int *elen, int *tlist) {
	return 0;
}

static int getprob (char *filename, int *p_ncount, int *p_ecount, int **p_elist,
    int **p_elen)
{
    FILE *f = (FILE *) NULL;
    int i, j, end1, end2, w, rval = 0, ncount, ecount;
    int *elist = (int *) NULL, *elen = (int *) NULL;
    double *x = (double *) NULL, *y = (double *) NULL;

    if ((f = fopen (filename, "r")) == NULL) {
	fprintf (stderr, "Unable to open %s for input\n",filename);
        rval = 1;  goto CLEANUP;
    }

    if (geometric_data == 0) {
        if (fscanf (f, "%d %d", &ncount, &ecount) != 2) {
       	    fprintf (stderr, "Input file %s has invalid format\n",filename);
            rval = 1;  goto CLEANUP;
        }

        printf ("Nodes: %d  Edges: %d\n", ncount, ecount);
        fflush (stdout);

        elist = (int *) malloc (2 * ecount * sizeof (int));
        if (!elist) {
            fprintf (stderr, "out of memory for elist\n");
            rval = 1;  goto CLEANUP;
        }

        elen = (int *) malloc (ecount * sizeof (int));
        if (!elen) {
            fprintf (stderr, "out of memory for elen\n");
            rval = 1;  goto CLEANUP;
        }

        for (i = 0; i < ecount; i++) {
    	    if (fscanf(f,"%d %d %d",&end1, &end2, &w) != 3) {
	        fprintf (stderr, "%s has invalid input format\n", filename);
                rval = 1;  goto CLEANUP;
	    }
	    elist[2*i] = end1;
	    elist[2*i+1] = end2;
	    elen[i] = w;
        }
    } else {
        if (fscanf (f, "%d", &ncount) != 1) {
       	    fprintf (stderr, "Input file %s has invalid format\n",filename);
            rval = 1;  goto CLEANUP;
        }

        x = (double *) malloc (ncount * sizeof (double));
        y = (double *) malloc (ncount * sizeof (double));
        if (!x || !y) {
            fprintf (stdout, "out of memory for x or y\n");
            rval = 1; goto CLEANUP;
        }

        for (i = 0; i < ncount; i++) {
    	    if (fscanf(f,"%lf %lf",&x[i], &y[i]) != 2) {
	        fprintf (stderr, "%s has invalid input format\n", filename);
                rval = 1;  goto CLEANUP;
	    }
        }

        ecount = (ncount * (ncount - 1)) / 2;
        printf ("Complete graph: %d nodes, %d edges\n", ncount, ecount);

        elist = (int *) malloc (2 * ecount * sizeof (int));
        if (!elist) {
            fprintf (stderr, "out of memory for elist\n");
            rval = 1;  goto CLEANUP;
        }

        elen = (int *) malloc (ecount * sizeof (int));
        if (!elen) {
            fprintf (stderr, "out of memory for elen\n");
            rval = 1;  goto CLEANUP;
        }

        ecount = 0;
        for (i = 0; i < ncount; i++) {
            for (j = i+1; j < ncount; j++) {
                elist[2*ecount] = i;
                elist[2*ecount+1] = j;
                elen[ecount] = euclid_edgelen (i, j, x, y);
                ecount++;
            }
        }
    }

    *p_ncount = ncount;
    *p_ecount = ecount;
    *p_elist = elist;
    *p_elen = elen;

CLEANUP:
    if (f) fclose (f);
    if (x) free (x);
    if (y) free (y);
    return rval;
}

static int euclid_edgelen (int i, int j, double *x, double *y)
{
    double t1 = x[i] - x[j], t2 = y[i] - y[j];
    return (int) (sqrt (t1 * t1 + t2 * t2) + 0.5);
}

static int parseargs (int ac, char **av)
{
    int c;

    while ((c = getopt (ac, av, "dgs:")) != EOF) {
        switch (c) {
        case 'd':
            debug = 1;
            break;
        case 'g':
            geometric_data = 1;
            break;
        case 's':
            seed = atoi (optarg);
            break;
        case '?':
        default:
            usage (av[0]);
            return 1;
        }
    }

    if (optind >= ac) {
        usage (av[0]);
        return 1;
    }
    fname = av[optind++];

    return 0;
}

static void usage (char *f)
{
    fprintf (stderr, "Usage: %s prob_file\n", f);
    fprintf (stderr, "   -d    turn on debugging\n");
    fprintf (stderr, "   -g    prob_file has x-y coordinates\n");
    fprintf (stderr, "   -s d  random seed\n");
}

<|endoftext|>


<commit_before>#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string.hpp>

#include <QProgressDialog>
#include <QMessageBox>

#include "image_annotation.h"

namespace fish_annotator { namespace image_annotator {

namespace fs = boost::filesystem;

ImageAnnotation::ImageAnnotation(
  const std::string& image_file,
  const std::string& species,
  const std::string& subspecies,
  uint64_t id,
  const Rect &rect,
  enum AnnotationType type)
  : image_file_(image_file)
  , species_(species)
  , subspecies_(subspecies)
  , id_(id)
  , area_(rect)
  , type_(type) {
  boost::algorithm::to_lower(species_);
  boost::algorithm::to_lower(subspecies_);
}

ImageAnnotation::ImageAnnotation()
  : image_file_()
  , species_()
  , subspecies_()
  , id_(0)
  , area_(0, 0, 0, 0)
  , type_(kBox) {
}

bool ImageAnnotation::operator==(const ImageAnnotation &rhs) const {
  if(image_file_ != rhs.image_file_) return false;
  if(species_ != rhs.species_) return false;
  if(subspecies_ != rhs.subspecies_) return false;
  if(id_ != rhs.id_) return false;
  if(area_.x != rhs.area_.x) return false;
  if(area_.y != rhs.area_.y) return false;
  if(area_.w != rhs.area_.w) return false;
  if(area_.h != rhs.area_.h) return false;
  if(type_ != rhs.type_) return false;
  return true;
}

bool ImageAnnotation::operator!=(const ImageAnnotation &rhs) const {
  return !operator==(rhs);
}

pt::ptree ImageAnnotation::write() const {
  pt::ptree tree;
  tree.put("image_file", image_file_);
  tree.put("species", species_);
  tree.put("subspecies", subspecies_);
  tree.put("id", id_);
  tree.put("x", area_.x);
  tree.put("y", area_.y);
  tree.put("w", area_.w);
  tree.put("h", area_.h);
  switch(type_) {
    case kBox:
      tree.put("type", "box");
      break;
    case kLine:
      tree.put("type", "line");
      break;
    case kDot:
      tree.put("type", "dot");
      break;
  }
  return tree;
}

void ImageAnnotation::write_csv(std::ofstream &csv) const {
  csv << image_file_ << ",";
  csv << species_ << ",";
  csv << subspecies_ << ",";
  csv << id_ << ",";
  csv << area_.x << ",";
  csv << area_.y << ",";
  csv << area_.w << ",";
  csv << area_.h << ",";
  switch(type_) {
    case kBox:
      csv << "Box,0.0";
      break;
    case kLine: {
      double xdiff = static_cast<double>(area_.x - area_.w);
      double ydiff = static_cast<double>(area_.y - area_.h);
      double length = std::sqrt(xdiff * xdiff + ydiff * ydiff);
      csv << "Line,";
      csv << length;
      break;
    }
    case kDot:
      csv << "Dot,0.0";
      break;
  }
}

void ImageAnnotation::read(const pt::ptree &tree) {
  image_file_ = tree.get<std::string>("image_file");
  species_ = tree.get<std::string>("species");
  boost::algorithm::to_lower(species_);
  subspecies_ = tree.get<std::string>("subspecies");
  boost::algorithm::to_lower(subspecies_);
  id_ = tree.get<uint64_t>("id");
  uint64_t x = tree.get<uint64_t>("x");
  uint64_t y = tree.get<uint64_t>("y");
  uint64_t w = tree.get<uint64_t>("w");
  uint64_t h = tree.get<uint64_t>("h");
  area_ = Rect(x, y, w, h);
  type_ = kBox; // default
  auto opt_type_str = tree.get_optional<std::string>("type");
  if(opt_type_str != boost::none) {
    auto type_str = opt_type_str.get();
    if(type_str == "box") {
      type_ = kBox;
    }
    else if(type_str == "line") {
      type_ = kLine;
    }
    else if(type_str == "dot") {
      type_ = kDot;
    }
  }
}

ImageAnnotationList::ImageAnnotationList()
  : list_()
  , by_file_()
  , by_species_() {
}

void ImageAnnotationList::insert(std::shared_ptr<ImageAnnotation> annotation) {
  list_.push_front(annotation);
  by_file_.insert({annotation->image_file_, list_.begin()});
  by_species_.insert({{annotation->species_, annotation->subspecies_},
                      list_.begin()});
}

void ImageAnnotationList::remove(const fs::path &image_file, uint64_t id) {
  auto range = by_file_.left.equal_range(image_file.filename().string());
  for(auto it = range.first; it != range.second; ++it) {
    if((*(it->second))->id_ == id) {
      list_.erase(it->second);
      by_species_.right.erase(by_species_.right.find(it->second));
      by_file_.left.erase(it);
      break;
    }
  }
}

uint64_t ImageAnnotationList::nextId(const fs::path &image_file) {
  auto range = by_file_.left.equal_range(image_file.filename().string());
  uint64_t max_id = 0;
  for(auto it = range.first; it != range.second; ++it) {
    if((*(it->second))->id_ > max_id) {
      max_id = (*(it->second))->id_;
    }
  }
  return max_id + 1;
}

std::vector<std::shared_ptr<ImageAnnotation>>
ImageAnnotationList::getImageAnnotations(const fs::path &image_file) {
  std::vector<std::shared_ptr<ImageAnnotation>> annotations;
  auto range = by_file_.left.equal_range(image_file.filename().string());
  for(auto it = range.first; it != range.second; ++it) {
    annotations.push_back(*(it->second));
  }
  return annotations;
}

void ImageAnnotationList::insertGlobalStateAnnotation(
  std::string image_file_name,
  std::shared_ptr<GlobalStateAnnotation> ann) {
    global_states_[image_file_name] = ann;
}

std::shared_ptr<GlobalStateAnnotation>
ImageAnnotationList::getGlobalStateAnnotation(
  const std::string &image_file) {
  if(global_states_.find(image_file) == global_states_.end()) {
    return nullptr;
  }
  else {
    return global_states_[image_file];
  }
}

std::map<std::string, uint64_t>
ImageAnnotationList::getCounts(const std::string &image_file) {
  std::map<std::string, uint64_t> counts;
  auto range = by_file_.left.equal_range(image_file);
  for(auto it = range.first; it != range.second; ++it) {
    std::string species = (*(it->second))->species_;
    auto count_it = counts.find(species);
    if(count_it != counts.end()) {
      count_it->second++;
    }
    else {
      counts.insert({species, 1});
    }
  }
  return counts;
}

std::vector<Species> ImageAnnotationList::getAllSpecies() {
  std::vector<Species> vec;
  for(const auto &elem : by_species_.left) {
    const std::string &species = elem.first.first;
    const std::string &subspecies = elem.first.second;
    auto it = std::find_if(vec.begin(), vec.end(),
        [&species](const Species &s) {
          return species == s.getName();
        });
    if(it == vec.end()) {
      vec.push_back(Species(species));
      if(!subspecies.empty()) {
        vec.back().getSubspecies().push_back(subspecies);
      }
    }
    else if(!subspecies.empty()) {
      auto &subs = it->getSubspecies();
      auto sub_it = std::find_if(subs.begin(), subs.end(),
        [&subspecies](const std::string &s) {
          return subspecies == s;
        });
      if(sub_it == subs.end()) {
        subs.push_back(subspecies);
      }
    }
  }
  return vec;
}

bool ImageAnnotationList::operator==(ImageAnnotationList &rhs) {
  if(list_.size() != rhs.list_.size()) return false;
  auto it = list_.begin();
  auto it_rhs = rhs.list_.begin();
  for(; it != list_.end() && it_rhs != rhs.list_.end(); ++it, ++it_rhs) {
    if(**it != **it_rhs) return false;
  }
  return true;
}

void ImageAnnotationList::write(
  const std::vector<fs::path> &filenames) const {
  std::unique_ptr<QProgressDialog> dlg(new QProgressDialog(
    "Saving annotations...",
    "Abort",
    0,
    static_cast<int>(filenames.size() - 1),
    nullptr,
    Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint));
  dlg->setCancelButton(0);
  dlg->setWindowTitle("Save Annotations");
  dlg->setMinimumDuration(10);
  int iter = 0;
  fs::path sum_file(filenames[0]);
  sum_file = sum_file.parent_path();
  sum_file /= "_summary.csv";
  std::ofstream sum(sum_file.string());
  sum << "Image File,Species,Subspecies,ID,Top,Left,Width,Height,Type,Length";
  sum << (global_states_.size() > 0 ?
    global_states_.begin()->second->writeCsvHeader() : "");
  sum << std::endl;
  for(const auto &image_file : filenames) {
    fs::path csv_file(image_file);
    csv_file.replace_extension(".csv");
    std::ofstream csv(csv_file.string());
    csv << "Image File,Species,Subspecies,ID,Top,Left,Width,Height,Type,Length";
    const auto &global_state = global_states_.at(image_file.string());
    csv << global_state->writeCsvHeader();
    csv << std::endl;
    pt::ptree tree;
    pt::ptree detections;
    auto range = by_file_.left.equal_range(image_file.filename().string());
    for(auto it = range.first; it != range.second; ++it) {
      (*(it->second))->write_csv(csv);
      csv << global_state->writeCsvValues() << std::endl;
      (*(it->second))->write_csv(sum);
      sum << global_state->writeCsvValues() << std::endl;
      detections.push_back(std::make_pair("", (*(it->second))->write()));
    }
    tree.add_child("detections", detections);
    tree.add_child("global_state", global_state->write());
    fs::path json_file(image_file);
    json_file.replace_extension(".json");
    pt::write_json(json_file.string(), tree);
    dlg->setValue(iter++);
    if(dlg->wasCanceled()) {
      break;
    }
  }
}

void ImageAnnotationList::read(
  const std::vector<fs::path> &filenames) {
  for(const auto &image_file : filenames) {
    fs::path json_file(image_file);
    json_file.replace_extension(".json");
    if(fs::exists(json_file)) {
      pt::ptree tree;
      pt::read_json(json_file.string(), tree);
      auto it = tree.find("annotation_list");
      if(it != tree.not_found()) {
        for(auto &val : tree.get_child("annotation_list")) {
          auto annotation = std::make_shared<ImageAnnotation>();
          annotation->read(val.second);
          insert(annotation);
        }
      }
      else {
        auto it_new = tree.find("detections");
        if(it_new != tree.not_found()) {
          for(auto &val : tree.get_child("detections")) {
            auto annotation = std::make_shared<ImageAnnotation>();
            annotation->read(val.second.get_child(""));
            insert(annotation);
          }
        }
        auto it_new_gs = tree.find("global_state");
        if(it_new_gs != tree.not_found()) {
          std::map<std::string, bool> global_state_init;
          for(auto &val : tree.get_child("global_state")) {
            global_state_init.insert(std::pair<std::string, bool>(
              val.first,
              val.second.get<std::string>(val.first) == "1"));
          }
          global_states_.insert(
            std::pair<std::string, std::shared_ptr<GlobalStateAnnotation>>(
            image_file.string(),
            std::make_shared<GlobalStateAnnotation>(global_state_init)));
        }
      }
    }
  }
}

}} // namespace fish_annotator::image_annotator
<commit_msg>Index by filename only<commit_after>#include <boost/property_tree/json_parser.hpp>
#include <boost/algorithm/string.hpp>

#include <QProgressDialog>
#include <QMessageBox>

#include "image_annotation.h"
#include <fstream>
std::ofstream debug2("DEBUG2.txt");
namespace fish_annotator { namespace image_annotator {

namespace fs = boost::filesystem;

ImageAnnotation::ImageAnnotation(
  const std::string& image_file,
  const std::string& species,
  const std::string& subspecies,
  uint64_t id,
  const Rect &rect,
  enum AnnotationType type)
  : image_file_(image_file)
  , species_(species)
  , subspecies_(subspecies)
  , id_(id)
  , area_(rect)
  , type_(type) {
  boost::algorithm::to_lower(species_);
  boost::algorithm::to_lower(subspecies_);
}

ImageAnnotation::ImageAnnotation()
  : image_file_()
  , species_()
  , subspecies_()
  , id_(0)
  , area_(0, 0, 0, 0)
  , type_(kBox) {
}

bool ImageAnnotation::operator==(const ImageAnnotation &rhs) const {
  if(image_file_ != rhs.image_file_) return false;
  if(species_ != rhs.species_) return false;
  if(subspecies_ != rhs.subspecies_) return false;
  if(id_ != rhs.id_) return false;
  if(area_.x != rhs.area_.x) return false;
  if(area_.y != rhs.area_.y) return false;
  if(area_.w != rhs.area_.w) return false;
  if(area_.h != rhs.area_.h) return false;
  if(type_ != rhs.type_) return false;
  return true;
}

bool ImageAnnotation::operator!=(const ImageAnnotation &rhs) const {
  return !operator==(rhs);
}

pt::ptree ImageAnnotation::write() const {
  pt::ptree tree;
  tree.put("image_file", image_file_);
  tree.put("species", species_);
  tree.put("subspecies", subspecies_);
  tree.put("id", id_);
  tree.put("x", area_.x);
  tree.put("y", area_.y);
  tree.put("w", area_.w);
  tree.put("h", area_.h);
  switch(type_) {
    case kBox:
      tree.put("type", "box");
      break;
    case kLine:
      tree.put("type", "line");
      break;
    case kDot:
      tree.put("type", "dot");
      break;
  }
  return tree;
}

void ImageAnnotation::write_csv(std::ofstream &csv) const {
  csv << image_file_ << ",";
  csv << species_ << ",";
  csv << subspecies_ << ",";
  csv << id_ << ",";
  csv << area_.x << ",";
  csv << area_.y << ",";
  csv << area_.w << ",";
  csv << area_.h << ",";
  switch(type_) {
    case kBox:
      csv << "Box,0.0";
      break;
    case kLine: {
      double xdiff = static_cast<double>(area_.x - area_.w);
      double ydiff = static_cast<double>(area_.y - area_.h);
      double length = std::sqrt(xdiff * xdiff + ydiff * ydiff);
      csv << "Line,";
      csv << length;
      break;
    }
    case kDot:
      csv << "Dot,0.0";
      break;
  }
}

void ImageAnnotation::read(const pt::ptree &tree) {
  image_file_ = tree.get<std::string>("image_file");
  species_ = tree.get<std::string>("species");
  boost::algorithm::to_lower(species_);
  subspecies_ = tree.get<std::string>("subspecies");
  boost::algorithm::to_lower(subspecies_);
  id_ = tree.get<uint64_t>("id");
  uint64_t x = tree.get<uint64_t>("x");
  uint64_t y = tree.get<uint64_t>("y");
  uint64_t w = tree.get<uint64_t>("w");
  uint64_t h = tree.get<uint64_t>("h");
  area_ = Rect(x, y, w, h);
  type_ = kBox; // default
  auto opt_type_str = tree.get_optional<std::string>("type");
  if(opt_type_str != boost::none) {
    auto type_str = opt_type_str.get();
    if(type_str == "box") {
      type_ = kBox;
    }
    else if(type_str == "line") {
      type_ = kLine;
    }
    else if(type_str == "dot") {
      type_ = kDot;
    }
  }
}

ImageAnnotationList::ImageAnnotationList()
  : list_()
  , by_file_()
  , by_species_() {
}

void ImageAnnotationList::insert(std::shared_ptr<ImageAnnotation> annotation) {
  list_.push_front(annotation);
  by_file_.insert({annotation->image_file_, list_.begin()});
  by_species_.insert({{annotation->species_, annotation->subspecies_},
                      list_.begin()});
}

void ImageAnnotationList::remove(const fs::path &image_file, uint64_t id) {
  auto range = by_file_.left.equal_range(image_file.filename().string());
  for(auto it = range.first; it != range.second; ++it) {
    if((*(it->second))->id_ == id) {
      list_.erase(it->second);
      by_species_.right.erase(by_species_.right.find(it->second));
      by_file_.left.erase(it);
      break;
    }
  }
}

uint64_t ImageAnnotationList::nextId(const fs::path &image_file) {
  auto range = by_file_.left.equal_range(image_file.filename().string());
  uint64_t max_id = 0;
  for(auto it = range.first; it != range.second; ++it) {
    if((*(it->second))->id_ > max_id) {
      max_id = (*(it->second))->id_;
    }
  }
  return max_id + 1;
}

std::vector<std::shared_ptr<ImageAnnotation>>
ImageAnnotationList::getImageAnnotations(const fs::path &image_file) {
  std::vector<std::shared_ptr<ImageAnnotation>> annotations;
  auto range = by_file_.left.equal_range(image_file.filename().string());
  for(auto it = range.first; it != range.second; ++it) {
    annotations.push_back(*(it->second));
  }
  return annotations;
}

void ImageAnnotationList::insertGlobalStateAnnotation(
  std::string image_file_name,
  std::shared_ptr<GlobalStateAnnotation> ann) {
    global_states_[image_file_name] = ann;
}

std::shared_ptr<GlobalStateAnnotation>
ImageAnnotationList::getGlobalStateAnnotation(
  const std::string &image_file) {
  if(global_states_.find(image_file) == global_states_.end()) {
    return nullptr;
  }
  else {
    return global_states_[image_file];
  }
}

std::map<std::string, uint64_t>
ImageAnnotationList::getCounts(const std::string &image_file) {
  std::map<std::string, uint64_t> counts;
  auto range = by_file_.left.equal_range(image_file);
  for(auto it = range.first; it != range.second; ++it) {
    std::string species = (*(it->second))->species_;
    auto count_it = counts.find(species);
    if(count_it != counts.end()) {
      count_it->second++;
    }
    else {
      counts.insert({species, 1});
    }
  }
  return counts;
}

std::vector<Species> ImageAnnotationList::getAllSpecies() {
  std::vector<Species> vec;
  for(const auto &elem : by_species_.left) {
    const std::string &species = elem.first.first;
    const std::string &subspecies = elem.first.second;
    auto it = std::find_if(vec.begin(), vec.end(),
        [&species](const Species &s) {
          return species == s.getName();
        });
    if(it == vec.end()) {
      vec.push_back(Species(species));
      if(!subspecies.empty()) {
        vec.back().getSubspecies().push_back(subspecies);
      }
    }
    else if(!subspecies.empty()) {
      auto &subs = it->getSubspecies();
      auto sub_it = std::find_if(subs.begin(), subs.end(),
        [&subspecies](const std::string &s) {
          return subspecies == s;
        });
      if(sub_it == subs.end()) {
        subs.push_back(subspecies);
      }
    }
  }
  return vec;
}

bool ImageAnnotationList::operator==(ImageAnnotationList &rhs) {
  if(list_.size() != rhs.list_.size()) return false;
  auto it = list_.begin();
  auto it_rhs = rhs.list_.begin();
  for(; it != list_.end() && it_rhs != rhs.list_.end(); ++it, ++it_rhs) {
    if(**it != **it_rhs) return false;
  }
  return true;
}

void ImageAnnotationList::write(
  const std::vector<fs::path> &filenames) const {
  std::unique_ptr<QProgressDialog> dlg(new QProgressDialog(
    "Saving annotations...",
    "Abort",
    0,
    static_cast<int>(filenames.size() - 1),
    nullptr,
    Qt::Window | Qt::WindowTitleHint | Qt::CustomizeWindowHint));
  dlg->setCancelButton(0);
  dlg->setWindowTitle("Save Annotations");
  dlg->setMinimumDuration(10);
  int iter = 0;
  debug2 << "CREATING SUMMARY FILE " << filenames[0] << std::endl;
  fs::path sum_file(filenames[0]);
  sum_file = sum_file.parent_path();
  sum_file /= "_summary.csv";
  std::ofstream sum(sum_file.string());
  sum << "Image File,Species,Subspecies,ID,Top,Left,Width,Height,Type,Length";
  sum << (global_states_.size() > 0 ?
    global_states_.begin()->second->writeCsvHeader() : "");
  sum << std::endl;
  for(const auto &image_file : filenames) {
    fs::path csv_file(image_file);
    csv_file.replace_extension(".csv");
    std::ofstream csv(csv_file.string());
    csv << "Image File,Species,Subspecies,ID,Top,Left,Width,Height,Type,Length";
    const auto &global_state = global_states_.at(
      image_file.filename().string());
    csv << global_state->writeCsvHeader();
    csv << std::endl;
    pt::ptree tree;
    pt::ptree detections;
    auto range = by_file_.left.equal_range(image_file.filename().string());
    for(auto it = range.first; it != range.second; ++it) {
      (*(it->second))->write_csv(csv);
      csv << global_state->writeCsvValues() << std::endl;
      (*(it->second))->write_csv(sum);
      sum << global_state->writeCsvValues() << std::endl;
      detections.push_back(std::make_pair("", (*(it->second))->write()));
    }
    tree.add_child("detections", detections);
    tree.add_child("global_state", global_state->write());
    fs::path json_file(image_file);
    json_file.replace_extension(".json");
    pt::write_json(json_file.string(), tree);
    dlg->setValue(iter++);
    if(dlg->wasCanceled()) {
      break;
    }
  }
}

void ImageAnnotationList::read(
  const std::vector<fs::path> &filenames) {
  for(const auto &image_file : filenames) {
    fs::path json_file(image_file);
    json_file.replace_extension(".json");
    if(fs::exists(json_file)) {
      pt::ptree tree;
      pt::read_json(json_file.string(), tree);
      auto it = tree.find("annotation_list");
      if(it != tree.not_found()) {
        for(auto &val : tree.get_child("annotation_list")) {
          auto annotation = std::make_shared<ImageAnnotation>();
          annotation->read(val.second);
          insert(annotation);
        }
      }
      else {
        auto it_new = tree.find("detections");
        if(it_new != tree.not_found()) {
          for(auto &val : tree.get_child("detections")) {
            auto annotation = std::make_shared<ImageAnnotation>();
            annotation->read(val.second.get_child(""));
            insert(annotation);
          }
        }
        auto it_new_gs = tree.find("global_state");
        if(it_new_gs != tree.not_found()) {
          std::map<std::string, bool> global_state_init;
          for(auto &val : tree.get_child("global_state")) {
            global_state_init.insert(std::pair<std::string, bool>(
              val.first,
              val.second.get<std::string>(val.first) == "1"));
          }
          global_states_.insert(
            std::pair<std::string, std::shared_ptr<GlobalStateAnnotation>>(
            image_file.string(),
            std::make_shared<GlobalStateAnnotation>(global_state_init)));
        }
      }
    }
  }
}

}} // namespace fish_annotator::image_annotator
<|endoftext|>


<commit_before>// Copyright (c) 2013, Cloudera, inc.
// Confidential Cloudera Information: Covered by NDA.

#include "kudu/master/master-path-handlers.h"

#include <algorithm>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <string>
#include <vector>

#include "kudu/common/schema.h"
#include "kudu/common/wire_protocol.h"
#include "kudu/gutil/map-util.h"
#include "kudu/gutil/stringprintf.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/server/webui_util.h"
#include "kudu/master/catalog_manager.h"
#include "kudu/master/master.h"
#include "kudu/master/master.pb.h"
#include "kudu/master/ts_descriptor.h"
#include "kudu/master/ts_manager.h"
#include "kudu/util/url-coding.h"

namespace kudu {

using std::vector;
using std::string;
using strings::Substitute;
using metadata::QuorumPeerPB;

namespace master {

const int kSysTablesEntryStatePrefixLen = 11;  // kTableState
const int kSysTabletsEntryStatePrefixLen = 12; // kTabletState

MasterPathHandlers::~MasterPathHandlers() {
}

void MasterPathHandlers::HandleTabletServers(const Webserver::WebRequest& req,
                                             std::stringstream* output) {
  vector<std::tr1::shared_ptr<TSDescriptor> > descs;
  master_->ts_manager()->GetAllDescriptors(&descs);

  *output << "
Tablet Servers
\n";

  *output << "
\n";
  *output << "
UUID	Time since heartbeat	Registration
\n";
  BOOST_FOREACH(const std::tr1::shared_ptr<TSDescriptor>& desc, descs) {
    const string time_since_hb = StringPrintf("%.1fs", desc->TimeSinceHeartbeat().ToSeconds());
    TSRegistrationPB reg;
    desc->GetRegistration(&reg);
    *output << Substitute("
$0	$1	$2
\n",
                          RegistrationToHtml(reg, desc->permanent_uuid()),
                          time_since_hb,
                          EscapeForHtmlToString(reg.ShortDebugString()));
  }
  *output << "
\n";
}

void MasterPathHandlers::HandleCatalogManager(const Webserver::WebRequest& req,
                                              std::stringstream* output) {
  *output << "
Catalog Manager
\n";

  std::vector<scoped_refptr<TableInfo> > tables;
  master_->catalog_manager()->GetAllTables(&tables);

  *output << "
\n";
  *output << "
Table Name	Table Id	State
\n";
  BOOST_FOREACH(const scoped_refptr<TableInfo>& table, tables) {
    TableMetadataLock l(table.get(), TableMetadataLock::READ);
    *output << Substitute(
        "
$0	$1	$2 $3
\n",
        EscapeForHtmlToString(l.data().name()),
        EscapeForHtmlToString(table->id()),
        SysTablesEntryPB_State_Name(l.data().pb.state()).substr(kSysTablesEntryStatePrefixLen),
        EscapeForHtmlToString(l.data().pb.state_msg()));
  }
  *output << "
\n";
}

void MasterPathHandlers::HandleTablePage(const Webserver::WebRequest& req,
                                         std::stringstream *output) {
  // Parse argument.
  string table_id;
  if (!FindCopy(req.parsed_args, "id", &table_id)) {
    // TODO: webserver should give a way to return a non-200 response code
    *output << "Missing 'id' argument";
    return;
  }

  scoped_refptr<TableInfo> table;
  if (!master_->catalog_manager()->GetTableInfo(table_id, &table)) {
    *output << "Table not found";
    return;
  }

  Schema schema;
  string table_name;
  vector<scoped_refptr<TabletInfo> > tablets;
  {
    TableMetadataLock l(table.get(), TableMetadataLock::READ);
    table_name = l.data().name();
    *output << "
Table: " << EscapeForHtmlToString(table_name)
            << " (" << EscapeForHtmlToString(table_id) << ")
\n";

    *output << "
\n";
    *output << "
Version:	" << l.data().pb.version() << "
\n";
    *output << "
State:	"
          << SysTablesEntryPB_State_Name(l.data().pb.state()).substr(kSysTablesEntryStatePrefixLen)
          << EscapeForHtmlToString(l.data().pb.state_msg())
          << "
\n";
    *output << "
\n";

    SchemaFromPB(l.data().pb.schema(), &schema);
    table->GetAllTablets(&tablets);
  }

  HtmlOutputSchemaTable(schema, output);

  *output << "
\n";
  *output << "
Tablet ID	Start-Key	End-Key	State	"
      "Quorum
\n";
  BOOST_FOREACH(const scoped_refptr<TabletInfo>& tablet, tablets) {
    vector<TabletReplica> locations;
    tablet->GetLocations(&locations);
    TabletMetadataLock l(tablet.get(), TabletMetadataLock::READ);
    *output << Substitute(
        "
$0	$1	$2	$3 $4	$5
\n",
        tablet->tablet_id(),
        EscapeForHtmlToString(schema.DebugEncodedRowKey(l.data().pb.start_key())),
        EscapeForHtmlToString(schema.DebugEncodedRowKey(l.data().pb.end_key())),
        SysTabletsEntryPB_State_Name(l.data().pb.state()).substr(kSysTabletsEntryStatePrefixLen),
        EscapeForHtmlToString(l.data().pb.state_msg()),
        QuorumToHtml(locations));
  }
  *output << "
\n";

  *output << "
Impala CREATE TABLE statement
\n";
  const string master_addr = master_->first_rpc_address().ToString();
  HtmlOutputImpalaSchema(table_name, schema, master_addr, output);

  std::vector<scoped_refptr<MonitoredTask> > task_list;
  table->GetTaskList(&task_list);
  HtmlOutputTaskList(task_list, output);
}

void MasterPathHandlers::HandleMasters(const Webserver::WebRequest& req,
                                       std::stringstream* output) {
  vector<ServerEntryPB> masters;
  Status s = master_->ListMasters(&masters);
  if (!s.ok()) {
    s = s.CloneAndPrepend("Unable to list Masters");
    LOG(WARNING) << s.ToString();
    *output << "
" << s.ToString() << "
\n";
    return;
  }
  *output << "
 Masters
\n";
  *output <<  "
\n";
  *output <<  "
Registration	Role
\n";

  BOOST_FOREACH(const ServerEntryPB& master, masters) {
    if (master.has_error()) {
      Status error = StatusFromPB(master.error());
      *output << Substitute("
$0
\n",
                            EscapeForHtmlToString(error.ToString()));
      continue;
    }
    string reg_text = RegistrationToHtml(master.registration(),
                                         master.instance_id().permanent_uuid());
    if (master.instance_id().permanent_uuid() == master_->instance_pb().permanent_uuid()) {
      reg_text = Substitute("$0", reg_text);
    }
    *output << Substitute("
$0	$1
\n", reg_text,
                          master.has_role() ?  QuorumPeerPB_Role_Name(master.role()) : "N/A");
  }

  *output << "
";
}

Status MasterPathHandlers::Register(Webserver* server) {
  bool is_styled = true;
  bool is_on_nav_bar = true;
  server->RegisterPathHandler("/tablet-servers",
                              boost::bind(&MasterPathHandlers::HandleTabletServers, this, _1, _2),
                              is_styled, is_on_nav_bar);
  server->RegisterPathHandler("/catalog-manager",
                              boost::bind(&MasterPathHandlers::HandleCatalogManager, this, _1, _2),
                              is_styled, is_on_nav_bar);
  server->RegisterPathHandler("/table",
                              boost::bind(&MasterPathHandlers::HandleTablePage, this, _1, _2),
                              is_styled, false);
  server->RegisterPathHandler("/masterz",
                              boost::bind(&MasterPathHandlers::HandleMasters, this, _1, _2),
                              is_styled, is_on_nav_bar);
  return Status::OK();
}

namespace {

bool CompareByRole(const TabletReplica& a, const TabletReplica& b) {
  return a.role < b.role;
}

} // anonymous namespace

string MasterPathHandlers::QuorumToHtml(const std::vector<TabletReplica>& locations) const {
  std::stringstream html;
  vector<TabletReplica> sorted_locations;
  sorted_locations.assign(locations.begin(), locations.end());

  std::sort(sorted_locations.begin(), sorted_locations.end(), &CompareByRole);

  html << "
\n";
  BOOST_FOREACH(const TabletReplica& location, sorted_locations) {
    string location_html = TSDescriptorToHtml(*location.ts_desc);
    if (location.role == QuorumPeerPB::LEADER) {
      html << Substitute("
LEADER: $0
\n", location_html);
    } else {
      html << Substitute("
$0: $1
\n",
                         QuorumPeerPB_Role_Name(location.role), location_html);
    }
  }
  html << "
\n";
  return html.str();
}

string MasterPathHandlers::TSDescriptorToHtml(const TSDescriptor& desc) const {
  TSRegistrationPB reg;
  desc.GetRegistration(&reg);

  string link_text = desc.permanent_uuid();
  if (reg.rpc_addresses().size() > 0) {
    link_text = reg.rpc_addresses(0).host();
  }
  return RegistrationToHtml(reg, link_text);
}

template<class RegistrationType>
string MasterPathHandlers::RegistrationToHtml(const RegistrationType& reg,
                                              const std::string& link_text) const {
  string link_html = EscapeForHtmlToString(link_text);
  if (reg.http_addresses().size() > 0) {
    link_html = Substitute("$2",
                           reg.http_addresses(0).host(),
                           reg.http_addresses(0).port(), link_html);
  }
  return link_html;
}

} // namespace master
} // namespace kudu
<commit_msg>Rename /catalog-manager endpoint to /tablez<commit_after>// Copyright (c) 2013, Cloudera, inc.
// Confidential Cloudera Information: Covered by NDA.

#include "kudu/master/master-path-handlers.h"

#include <algorithm>
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <string>
#include <vector>

#include "kudu/common/schema.h"
#include "kudu/common/wire_protocol.h"
#include "kudu/gutil/map-util.h"
#include "kudu/gutil/stringprintf.h"
#include "kudu/gutil/strings/substitute.h"
#include "kudu/server/webui_util.h"
#include "kudu/master/catalog_manager.h"
#include "kudu/master/master.h"
#include "kudu/master/master.pb.h"
#include "kudu/master/ts_descriptor.h"
#include "kudu/master/ts_manager.h"
#include "kudu/util/url-coding.h"

namespace kudu {

using std::vector;
using std::string;
using strings::Substitute;
using metadata::QuorumPeerPB;

namespace master {

const int kSysTablesEntryStatePrefixLen = 11;  // kTableState
const int kSysTabletsEntryStatePrefixLen = 12; // kTabletState

MasterPathHandlers::~MasterPathHandlers() {
}

void MasterPathHandlers::HandleTabletServers(const Webserver::WebRequest& req,
                                             std::stringstream* output) {
  vector<std::tr1::shared_ptr<TSDescriptor> > descs;
  master_->ts_manager()->GetAllDescriptors(&descs);

  *output << "
Tablet Servers
\n";

  *output << "
\n";
  *output << "
UUID	Time since heartbeat	Registration
\n";
  BOOST_FOREACH(const std::tr1::shared_ptr<TSDescriptor>& desc, descs) {
    const string time_since_hb = StringPrintf("%.1fs", desc->TimeSinceHeartbeat().ToSeconds());
    TSRegistrationPB reg;
    desc->GetRegistration(&reg);
    *output << Substitute("
$0	$1	$2
\n",
                          RegistrationToHtml(reg, desc->permanent_uuid()),
                          time_since_hb,
                          EscapeForHtmlToString(reg.ShortDebugString()));
  }
  *output << "
\n";
}

void MasterPathHandlers::HandleCatalogManager(const Webserver::WebRequest& req,
                                              std::stringstream* output) {
  *output << "
Tables
\n";

  std::vector<scoped_refptr<TableInfo> > tables;
  master_->catalog_manager()->GetAllTables(&tables);

  *output << "
\n";
  *output << "
Table Name	Table Id	State
\n";
  BOOST_FOREACH(const scoped_refptr<TableInfo>& table, tables) {
    TableMetadataLock l(table.get(), TableMetadataLock::READ);
    *output << Substitute(
        "
$0	$1	$2 $3
\n",
        EscapeForHtmlToString(l.data().name()),
        EscapeForHtmlToString(table->id()),
        SysTablesEntryPB_State_Name(l.data().pb.state()).substr(kSysTablesEntryStatePrefixLen),
        EscapeForHtmlToString(l.data().pb.state_msg()));
  }
  *output << "
\n";
}

void MasterPathHandlers::HandleTablePage(const Webserver::WebRequest& req,
                                         std::stringstream *output) {
  // Parse argument.
  string table_id;
  if (!FindCopy(req.parsed_args, "id", &table_id)) {
    // TODO: webserver should give a way to return a non-200 response code
    *output << "Missing 'id' argument";
    return;
  }

  scoped_refptr<TableInfo> table;
  if (!master_->catalog_manager()->GetTableInfo(table_id, &table)) {
    *output << "Table not found";
    return;
  }

  Schema schema;
  string table_name;
  vector<scoped_refptr<TabletInfo> > tablets;
  {
    TableMetadataLock l(table.get(), TableMetadataLock::READ);
    table_name = l.data().name();
    *output << "
Table: " << EscapeForHtmlToString(table_name)
            << " (" << EscapeForHtmlToString(table_id) << ")
\n";

    *output << "
\n";
    *output << "
Version:	" << l.data().pb.version() << "
\n";
    *output << "
State:	"
          << SysTablesEntryPB_State_Name(l.data().pb.state()).substr(kSysTablesEntryStatePrefixLen)
          << EscapeForHtmlToString(l.data().pb.state_msg())
          << "
\n";
    *output << "
\n";

    SchemaFromPB(l.data().pb.schema(), &schema);
    table->GetAllTablets(&tablets);
  }

  HtmlOutputSchemaTable(schema, output);

  *output << "
\n";
  *output << "
Tablet ID	Start-Key	End-Key	State	"
      "Quorum
\n";
  BOOST_FOREACH(const scoped_refptr<TabletInfo>& tablet, tablets) {
    vector<TabletReplica> locations;
    tablet->GetLocations(&locations);
    TabletMetadataLock l(tablet.get(), TabletMetadataLock::READ);
    *output << Substitute(
        "
$0	$1	$2	$3 $4	$5
\n",
        tablet->tablet_id(),
        EscapeForHtmlToString(schema.DebugEncodedRowKey(l.data().pb.start_key())),
        EscapeForHtmlToString(schema.DebugEncodedRowKey(l.data().pb.end_key())),
        SysTabletsEntryPB_State_Name(l.data().pb.state()).substr(kSysTabletsEntryStatePrefixLen),
        EscapeForHtmlToString(l.data().pb.state_msg()),
        QuorumToHtml(locations));
  }
  *output << "
\n";

  *output << "
Impala CREATE TABLE statement
\n";
  const string master_addr = master_->first_rpc_address().ToString();
  HtmlOutputImpalaSchema(table_name, schema, master_addr, output);

  std::vector<scoped_refptr<MonitoredTask> > task_list;
  table->GetTaskList(&task_list);
  HtmlOutputTaskList(task_list, output);
}

void MasterPathHandlers::HandleMasters(const Webserver::WebRequest& req,
                                       std::stringstream* output) {
  vector<ServerEntryPB> masters;
  Status s = master_->ListMasters(&masters);
  if (!s.ok()) {
    s = s.CloneAndPrepend("Unable to list Masters");
    LOG(WARNING) << s.ToString();
    *output << "
" << s.ToString() << "
\n";
    return;
  }
  *output << "
 Masters
\n";
  *output <<  "
\n";
  *output <<  "
Registration	Role
\n";

  BOOST_FOREACH(const ServerEntryPB& master, masters) {
    if (master.has_error()) {
      Status error = StatusFromPB(master.error());
      *output << Substitute("
$0
\n",
                            EscapeForHtmlToString(error.ToString()));
      continue;
    }
    string reg_text = RegistrationToHtml(master.registration(),
                                         master.instance_id().permanent_uuid());
    if (master.instance_id().permanent_uuid() == master_->instance_pb().permanent_uuid()) {
      reg_text = Substitute("$0", reg_text);
    }
    *output << Substitute("
$0	$1
\n", reg_text,
                          master.has_role() ?  QuorumPeerPB_Role_Name(master.role()) : "N/A");
  }

  *output << "
";
}

Status MasterPathHandlers::Register(Webserver* server) {
  bool is_styled = true;
  bool is_on_nav_bar = true;
  server->RegisterPathHandler("/tablet-servers",
                              boost::bind(&MasterPathHandlers::HandleTabletServers, this, _1, _2),
                              is_styled, is_on_nav_bar);
  server->RegisterPathHandler("/tablez",
                              boost::bind(&MasterPathHandlers::HandleCatalogManager, this, _1, _2),
                              is_styled, is_on_nav_bar);
  server->RegisterPathHandler("/table",
                              boost::bind(&MasterPathHandlers::HandleTablePage, this, _1, _2),
                              is_styled, false);
  server->RegisterPathHandler("/masterz",
                              boost::bind(&MasterPathHandlers::HandleMasters, this, _1, _2),
                              is_styled, is_on_nav_bar);
  return Status::OK();
}

namespace {

bool CompareByRole(const TabletReplica& a, const TabletReplica& b) {
  return a.role < b.role;
}

} // anonymous namespace

string MasterPathHandlers::QuorumToHtml(const std::vector<TabletReplica>& locations) const {
  std::stringstream html;
  vector<TabletReplica> sorted_locations;
  sorted_locations.assign(locations.begin(), locations.end());

  std::sort(sorted_locations.begin(), sorted_locations.end(), &CompareByRole);

  html << "
\n";
  BOOST_FOREACH(const TabletReplica& location, sorted_locations) {
    string location_html = TSDescriptorToHtml(*location.ts_desc);
    if (location.role == QuorumPeerPB::LEADER) {
      html << Substitute("
LEADER: $0
\n", location_html);
    } else {
      html << Substitute("
$0: $1
\n",
                         QuorumPeerPB_Role_Name(location.role), location_html);
    }
  }
  html << "
\n";
  return html.str();
}

string MasterPathHandlers::TSDescriptorToHtml(const TSDescriptor& desc) const {
  TSRegistrationPB reg;
  desc.GetRegistration(&reg);

  string link_text = desc.permanent_uuid();
  if (reg.rpc_addresses().size() > 0) {
    link_text = reg.rpc_addresses(0).host();
  }
  return RegistrationToHtml(reg, link_text);
}

template<class RegistrationType>
string MasterPathHandlers::RegistrationToHtml(const RegistrationType& reg,
                                              const std::string& link_text) const {
  string link_html = EscapeForHtmlToString(link_text);
  if (reg.http_addresses().size() > 0) {
    link_html = Substitute("$2",
                           reg.http_addresses(0).host(),
                           reg.http_addresses(0).port(), link_html);
  }
  return link_html;
}

} // namespace master
} // namespace kudu
<|endoftext|>


<commit_before><commit_msg>Perception: simplify Process of LidarObstacleSegmentation<commit_after><|endoftext|>


<commit_before><commit_msg>Planning: fix generate fallback path profile<commit_after><|endoftext|>


<commit_before><commit_msg>Prediction: fix infinite loop on search curr_lane<commit_after><|endoftext|>


<commit_before><commit_msg>prediction: fix an error when polyline_num > 450<commit_after><|endoftext|>


<commit_before>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/predictor/sequence/sequence_predictor.h"

#include <cmath>
#include <limits>
#include <memory>
#include <utility>

#include "modules/common/adapters/proto/adapter_config.pb.h"

#include "modules/common/math/vec2d.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/road_graph.h"
#include "modules/prediction/container/adc_trajectory/adc_trajectory_container.h"
#include "modules/prediction/container/container_manager.h"
#include "modules/prediction/container/pose/pose_container.h"

namespace apollo {
namespace prediction {

using apollo::common::PathPoint;
using apollo::common::TrajectoryPoint;
using apollo::common::adapter::AdapterConfig;
using apollo::common::math::Vec2d;
using apollo::hdmap::LaneInfo;

void SequencePredictor::Predict(Obstacle* obstacle) {
  Clear();

  CHECK_NOTNULL(obstacle);
  CHECK_GT(obstacle->history_size(), 0);
}

void SequencePredictor::Clear() { Predictor::Clear(); }

std::string SequencePredictor::ToString(const LaneSequence& sequence) {
  std::string str_lane_sequence = "";
  if (sequence.lane_segment_size() > 0) {
    str_lane_sequence += sequence.lane_segment(0).lane_id();
  }
  for (int i = 1; i < sequence.lane_segment_size(); ++i) {
    str_lane_sequence += ("->" + sequence.lane_segment(i).lane_id());
  }
  return str_lane_sequence;
}

void SequencePredictor::FilterLaneSequences(
    const Feature& feature, const std::string& lane_id,
    std::vector<bool>* enable_lane_sequence) {
  if (!feature.has_lane() || !feature.lane().has_lane_graph()) {
    return;
  }
  const LaneGraph& lane_graph = feature.lane().lane_graph();
  int num_lane_sequence = lane_graph.lane_sequence_size();
  std::vector<LaneChangeType> lane_change_type(num_lane_sequence,
                                               LaneChangeType::INVALID);
  std::pair<int, double> change(-1, -1.0);
  std::pair<int, double> all(-1, -1.0);

  /**
    * Filter out those obstacles that are close to the ADC
    * so that we will ignore them and drive normally unless
    * they really kick into our lane.
    */
  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);
    lane_change_type[i] = GetLaneChangeType(lane_id, sequence);

    if (lane_change_type[i] != LaneChangeType::LEFT &&
        lane_change_type[i] != LaneChangeType::RIGHT &&
        lane_change_type[i] != LaneChangeType::ONTO_LANE) {
      ADEBUG "Ignore lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    // The obstacle has interference with ADC within a small distance
    double distance = GetLaneChangeDistanceWithADC(sequence);
    ADEBUG << "Distance to ADC " << std::fixed << std::setprecision(6)
           << distance;
    if (distance > 0.0 && distance < FLAGS_lane_change_dist) {
      bool obs_within_its_own_lane = true;
      for (int j = 0; j < feature.polygon_point_size(); j ++) {
        Eigen::Vector2d position
            (feature.polygon_point(j).x(), feature.polygon_point(j).y());
        std::shared_ptr<const LaneInfo> lane_info =
            PredictionMap::LaneById(lane_id);
        double lane_s = 0.0;
        double lane_l = 0.0;
        PredictionMap::GetProjection(position, lane_info, &lane_s, &lane_l);

        double left = 0.0;
        double right = 0.0;
        lane_info->GetWidth(lane_s, &left, &right);

        if (lane_l > left || lane_l < -right) {
          obs_within_its_own_lane = false;
          break;
        }
      }

      if (obs_within_its_own_lane) {
        (*enable_lane_sequence)[i] = false;
        ADEBUG << "Filter trajectory [" << ToString(sequence)
               << "] due to small distance " << distance << ".";
      }
    }
  }

  /**
    * Pick the most probable lane-sequence and lane-change
    */
  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (LaneSequenceWithMaxProb(lane_change_type[i], probability, all.second)) {
      all.first = i;
      all.second = probability;
    }
    if (LaneChangeWithMaxProb(lane_change_type[i], probability,
                              change.second)) {
      change.first = i;
      change.second = probability;
    }
  }

  double lane_sequence_threshold = FLAGS_lane_sequence_threshold_cruise;
  if (feature.has_junction_feature()) {
    lane_sequence_threshold = FLAGS_lane_sequence_threshold_junction;
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (probability < lane_sequence_threshold && i != all.first) {
      (*enable_lane_sequence)[i] = false;
    } else if (change.first >= 0 && change.first < num_lane_sequence &&
               (lane_change_type[i] == LaneChangeType::LEFT ||
                lane_change_type[i] == LaneChangeType::RIGHT) &&
               lane_change_type[i] != lane_change_type[change.first]) {
      (*enable_lane_sequence)[i] = false;
    }
  }
}

SequencePredictor::LaneChangeType SequencePredictor::GetLaneChangeType(
    const std::string& lane_id, const LaneSequence& lane_sequence) {
  if (lane_id.empty()) {
    return LaneChangeType::ONTO_LANE;
  }

  std::string lane_change_id = lane_sequence.lane_segment(0).lane_id();
  if (lane_id == lane_change_id) {
    return LaneChangeType::STRAIGHT;
  } else {
    auto ptr_change_lane = PredictionMap::LaneById(lane_change_id);
    auto ptr_current_lane = PredictionMap::LaneById(lane_id);
    if (PredictionMap::IsLeftNeighborLane(ptr_change_lane, ptr_current_lane)) {
      return LaneChangeType::LEFT;
    } else if (PredictionMap::IsRightNeighborLane(ptr_change_lane,
        ptr_current_lane)) {
      return LaneChangeType::RIGHT;
    }
  }
  return LaneChangeType::INVALID;
}

double SequencePredictor::GetLaneChangeDistanceWithADC(
    const LaneSequence& lane_sequence) {
  auto pose_container =
      ContainerManager::Instance()->GetContainer<PoseContainer>(
          AdapterConfig::LOCALIZATION);
  auto adc_container = ContainerManager::Instance()->GetContainer<
      ADCTrajectoryContainer>(AdapterConfig::PLANNING_TRAJECTORY);

  CHECK_NOTNULL(pose_container);
  CHECK_NOTNULL(adc_container);

  if (!adc_container->HasOverlap(lane_sequence)) {
    ADEBUG << "The sequence [" << ToString(lane_sequence)
           << "] has no overlap with ADC.";
    return std::numeric_limits<double>::max();
  }

  Eigen::Vector2d adc_position;
  if (pose_container->ToPerceptionObstacle() != nullptr) {
    adc_position[0] = pose_container->ToPerceptionObstacle()->position().x();
    adc_position[1] = pose_container->ToPerceptionObstacle()->position().y();

    std::string obstacle_lane_id = lane_sequence.lane_segment(0).lane_id();
    double obstacle_lane_s = lane_sequence.lane_segment(0).start_s();
    double lane_s = 0.0;
    double lane_l = 0.0;
    if (PredictionMap::GetProjection(adc_position,
                                     PredictionMap::LaneById(obstacle_lane_id),
                                     &lane_s, &lane_l)) {
      ADEBUG << "Distance with ADC is " << std::fabs(lane_s - obstacle_lane_s);
      return obstacle_lane_s - lane_s;
    }
  }

  ADEBUG << "Invalid ADC pose.";
  return std::numeric_limits<double>::max();
}

bool SequencePredictor::LaneSequenceWithMaxProb(const LaneChangeType& type,
                                                const double probability,
                                                const double max_prob) {
  if (probability > max_prob) {
    return true;
  } else {
    double prob_diff = std::fabs(probability - max_prob);
    if (prob_diff <= std::numeric_limits<double>::epsilon() &&
        type == LaneChangeType::STRAIGHT) {
      return true;
    }
  }
  return false;
}

bool SequencePredictor::LaneChangeWithMaxProb(const LaneChangeType& type,
                                              const double probability,
                                              const double max_prob) {
  if (type == LaneChangeType::LEFT || type == LaneChangeType::RIGHT) {
    if (probability > max_prob) {
      return true;
    }
  }
  return false;
}

}  // namespace prediction
}  // namespace apollo
<commit_msg>Prediction: Fixed a nullptr issue.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include "modules/prediction/predictor/sequence/sequence_predictor.h"

#include <cmath>
#include <limits>
#include <memory>
#include <utility>

#include "modules/common/adapters/proto/adapter_config.pb.h"

#include "modules/common/math/vec2d.h"
#include "modules/prediction/common/prediction_gflags.h"
#include "modules/prediction/common/prediction_map.h"
#include "modules/prediction/common/road_graph.h"
#include "modules/prediction/container/adc_trajectory/adc_trajectory_container.h"
#include "modules/prediction/container/container_manager.h"
#include "modules/prediction/container/pose/pose_container.h"

namespace apollo {
namespace prediction {

using apollo::common::PathPoint;
using apollo::common::TrajectoryPoint;
using apollo::common::adapter::AdapterConfig;
using apollo::common::math::Vec2d;
using apollo::hdmap::LaneInfo;

void SequencePredictor::Predict(Obstacle* obstacle) {
  Clear();

  CHECK_NOTNULL(obstacle);
  CHECK_GT(obstacle->history_size(), 0);
}

void SequencePredictor::Clear() { Predictor::Clear(); }

std::string SequencePredictor::ToString(const LaneSequence& sequence) {
  std::string str_lane_sequence = "";
  if (sequence.lane_segment_size() > 0) {
    str_lane_sequence += sequence.lane_segment(0).lane_id();
  }
  for (int i = 1; i < sequence.lane_segment_size(); ++i) {
    str_lane_sequence += ("->" + sequence.lane_segment(i).lane_id());
  }
  return str_lane_sequence;
}

void SequencePredictor::FilterLaneSequences(
    const Feature& feature, const std::string& lane_id,
    std::vector<bool>* enable_lane_sequence) {
  if (!feature.has_lane() || !feature.lane().has_lane_graph()) {
    return;
  }
  const LaneGraph& lane_graph = feature.lane().lane_graph();
  int num_lane_sequence = lane_graph.lane_sequence_size();
  std::vector<LaneChangeType> lane_change_type(num_lane_sequence,
                                               LaneChangeType::INVALID);
  std::pair<int, double> change(-1, -1.0);
  std::pair<int, double> all(-1, -1.0);

  /**
    * Filter out those obstacles that are close to the ADC
    * so that we will ignore them and drive normally unless
    * they really kick into our lane.
    */
  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);
    lane_change_type[i] = GetLaneChangeType(lane_id, sequence);

    if (lane_change_type[i] != LaneChangeType::LEFT &&
        lane_change_type[i] != LaneChangeType::RIGHT &&
        lane_change_type[i] != LaneChangeType::ONTO_LANE) {
      ADEBUG "Ignore lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    // The obstacle has interference with ADC within a small distance
    double distance = GetLaneChangeDistanceWithADC(sequence);
    ADEBUG << "Distance to ADC " << std::fixed << std::setprecision(6)
           << distance;
    if (distance > 0.0 && distance < FLAGS_lane_change_dist) {
      bool obs_within_its_own_lane = true;
      for (int j = 0; j < feature.polygon_point_size(); j ++) {
        Eigen::Vector2d position
            (feature.polygon_point(j).x(), feature.polygon_point(j).y());
        std::shared_ptr<const LaneInfo> lane_info =
            PredictionMap::LaneById(lane_id);
        if (lane_info == nullptr) {
          obs_within_its_own_lane = false;
          break;
        }

        double lane_s = 0.0;
        double lane_l = 0.0;
        PredictionMap::GetProjection(position, lane_info, &lane_s, &lane_l);

        double left = 0.0;
        double right = 0.0;
        lane_info->GetWidth(lane_s, &left, &right);

        if (lane_l > left || lane_l < -right) {
          obs_within_its_own_lane = false;
          break;
        }
      }

      if (obs_within_its_own_lane) {
        (*enable_lane_sequence)[i] = false;
        ADEBUG << "Filter trajectory [" << ToString(sequence)
               << "] due to small distance " << distance << ".";
      }
    }
  }

  /**
    * Pick the most probable lane-sequence and lane-change
    */
  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (LaneSequenceWithMaxProb(lane_change_type[i], probability, all.second)) {
      all.first = i;
      all.second = probability;
    }
    if (LaneChangeWithMaxProb(lane_change_type[i], probability,
                              change.second)) {
      change.first = i;
      change.second = probability;
    }
  }

  double lane_sequence_threshold = FLAGS_lane_sequence_threshold_cruise;
  if (feature.has_junction_feature()) {
    lane_sequence_threshold = FLAGS_lane_sequence_threshold_junction;
  }

  for (int i = 0; i < num_lane_sequence; ++i) {
    const LaneSequence& sequence = lane_graph.lane_sequence(i);

    if (!(*enable_lane_sequence)[i]) {
      ADEBUG << "Disabled lane sequence [" << ToString(sequence) << "].";
      continue;
    }

    double probability = sequence.probability();
    if (probability < lane_sequence_threshold && i != all.first) {
      (*enable_lane_sequence)[i] = false;
    } else if (change.first >= 0 && change.first < num_lane_sequence &&
               (lane_change_type[i] == LaneChangeType::LEFT ||
                lane_change_type[i] == LaneChangeType::RIGHT) &&
               lane_change_type[i] != lane_change_type[change.first]) {
      (*enable_lane_sequence)[i] = false;
    }
  }
}

SequencePredictor::LaneChangeType SequencePredictor::GetLaneChangeType(
    const std::string& lane_id, const LaneSequence& lane_sequence) {
  if (lane_id.empty()) {
    return LaneChangeType::ONTO_LANE;
  }

  std::string lane_change_id = lane_sequence.lane_segment(0).lane_id();
  if (lane_id == lane_change_id) {
    return LaneChangeType::STRAIGHT;
  } else {
    auto ptr_change_lane = PredictionMap::LaneById(lane_change_id);
    auto ptr_current_lane = PredictionMap::LaneById(lane_id);
    if (PredictionMap::IsLeftNeighborLane(ptr_change_lane, ptr_current_lane)) {
      return LaneChangeType::LEFT;
    } else if (PredictionMap::IsRightNeighborLane(ptr_change_lane,
        ptr_current_lane)) {
      return LaneChangeType::RIGHT;
    }
  }
  return LaneChangeType::INVALID;
}

double SequencePredictor::GetLaneChangeDistanceWithADC(
    const LaneSequence& lane_sequence) {
  auto pose_container =
      ContainerManager::Instance()->GetContainer<PoseContainer>(
          AdapterConfig::LOCALIZATION);
  auto adc_container = ContainerManager::Instance()->GetContainer<
      ADCTrajectoryContainer>(AdapterConfig::PLANNING_TRAJECTORY);

  CHECK_NOTNULL(pose_container);
  CHECK_NOTNULL(adc_container);

  if (!adc_container->HasOverlap(lane_sequence)) {
    ADEBUG << "The sequence [" << ToString(lane_sequence)
           << "] has no overlap with ADC.";
    return std::numeric_limits<double>::max();
  }

  Eigen::Vector2d adc_position;
  if (pose_container->ToPerceptionObstacle() != nullptr) {
    adc_position[0] = pose_container->ToPerceptionObstacle()->position().x();
    adc_position[1] = pose_container->ToPerceptionObstacle()->position().y();

    std::string obstacle_lane_id = lane_sequence.lane_segment(0).lane_id();
    double obstacle_lane_s = lane_sequence.lane_segment(0).start_s();
    double lane_s = 0.0;
    double lane_l = 0.0;
    if (PredictionMap::GetProjection(adc_position,
                                     PredictionMap::LaneById(obstacle_lane_id),
                                     &lane_s, &lane_l)) {
      ADEBUG << "Distance with ADC is " << std::fabs(lane_s - obstacle_lane_s);
      return obstacle_lane_s - lane_s;
    }
  }

  ADEBUG << "Invalid ADC pose.";
  return std::numeric_limits<double>::max();
}

bool SequencePredictor::LaneSequenceWithMaxProb(const LaneChangeType& type,
                                                const double probability,
                                                const double max_prob) {
  if (probability > max_prob) {
    return true;
  } else {
    double prob_diff = std::fabs(probability - max_prob);
    if (prob_diff <= std::numeric_limits<double>::epsilon() &&
        type == LaneChangeType::STRAIGHT) {
      return true;
    }
  }
  return false;
}

bool SequencePredictor::LaneChangeWithMaxProb(const LaneChangeType& type,
                                              const double probability,
                                              const double max_prob) {
  if (type == LaneChangeType::LEFT || type == LaneChangeType::RIGHT) {
    if (probability > max_prob) {
      return true;
    }
  }
  return false;
}

}  // namespace prediction
}  // namespace apollo
<|endoftext|>