<commit_before>#include "StorageAsyncList.h"
#include "System/Threading/ThreadPool.h"
#include "System/IO/IOProcessor.h"
#include "StorageMemoChunkLister.h"
#include "StorageFileChunkLister.h"
#include "StorageUnwrittenChunkLister.h"
#include "StorageShard.h"
#include "StorageEnvironment.h"

#define MAX_RESULT_SIZE     1024*KiB

StorageAsyncListResult::StorageAsyncListResult(StorageAsyncList* asyncList_) :
 dataPage(NULL, 0)
{
    asyncList = asyncList_;
    final = false;
}

// this is called from main thread
void StorageAsyncListResult::OnComplete()
{
    asyncList->lastResult = this;
    Call(onComplete);
    asyncList->lastResult = NULL;
    if (final)
    {
        asyncList->env->DecreaseNumCursors();
        asyncList->Clear();
    }
    delete this;
}

void StorageAsyncListResult::Append(StorageFileKeyValue* kv)
{
    dataPage.Append(kv);
}

uint32_t StorageAsyncListResult::GetSize()
{
    return dataPage.GetPageBufferSize();
}

StorageAsyncList::StorageAsyncList()
{
    count = 0;
    offset = 0;
    Init();
}

void StorageAsyncList::Init()
{
    ret = false;
    completed = false;
    aborted = false;
    num = 0;
    stage = START;
    threadPool = NULL;
    iterators = NULL;
    listers = NULL;
    numListers = 0;
    lastResult = NULL;
    env = NULL;
}

void StorageAsyncList::Clear()
{
    unsigned    i;

    for (i = 0; i < numListers; i++)
        delete listers[i];
    delete[] listers;
    listers = NULL;
    delete[] iterators;
    iterators = NULL;
    numListers = 0;

    Init();
}

void StorageAsyncList::ExecuteAsyncList()
{
    unsigned                        numChunks;
    uint64_t                        preloadBufferSize;
    StorageChunk**                  itChunk;
    StorageFileChunk*               fileChunk;
    StorageFileChunkLister*         fileLister;
    StorageMemoChunkLister*         memoLister;
    StorageUnwrittenChunkLister*    unwrittenLister;
    Buffer*                         filename;
    StorageChunk::ChunkState        chunkState;
    ReadBuffer                      firstKey;

    Log_Debug("StorageAsyncList START");
    firstKey.Wrap(shardFirstKey);

    if (stage == START)
    {
        shardLastKey.Write(shard->GetLastKey());
        numChunks = shard->GetChunks().GetLength() + 1;

        listers = new StorageChunkLister*[numChunks];
        iterators = new StorageFileKeyValue*[numChunks];
        numListers = 0;
        preloadBufferSize = env->GetConfig().mergeBufferSize / numChunks;

        FOREACH (itChunk, shard->GetChunks())
        {
            chunkState = (*itChunk)->GetChunkState();

            if (chunkState == StorageChunk::Serialized)
            {
                memoLister = new StorageMemoChunkLister;
                memoLister->Init((StorageMemoChunk*) *itChunk, firstKey, count, offset);
                listers[numListers] = memoLister;
                numListers++;
            }
            else if (chunkState == StorageChunk::Unwritten)
            {
                unwrittenLister = new StorageUnwrittenChunkLister;
                unwrittenLister->Init((StorageFileChunk*) *itChunk, firstKey, count, offset);
                listers[numListers] = unwrittenLister;
                numListers++;
            }
            else if (chunkState == StorageChunk::Written)
            {
                fileChunk = (StorageFileChunk*) *itChunk;
                filename = &fileChunk->GetFilename();
                fileLister = new StorageFileChunkLister;
                fileLister->Init(
                 fileChunk->GetFilename(), (type == KEY || type == COUNT), preloadBufferSize);
                listers[numListers] = fileLister;
                numListers++;
            }
        }

        stage = MEMO_CHUNK;
    }

    Log_Debug("StorageAsyncList MEMO_CHUNK");

    if (stage == MEMO_CHUNK)
    {
        LoadMemoChunk();
        stage = FILE_CHUNK;
    }

    Log_Debug("StorageAsyncList FILE_CHUNK");

    if (stage == FILE_CHUNK)
    {
        threadPool->Execute(MFUNC(StorageAsyncList, AsyncLoadChunks));
    }
}

void StorageAsyncList::LoadMemoChunk()
{
    StorageMemoChunkLister* memoLister;
    ReadBuffer              firstKey;

    firstKey.Wrap(shardFirstKey);

    memoLister = new StorageMemoChunkLister;
    memoLister->Init(shard->GetMemoChunk(), firstKey, count, offset);

    // memochunk is always on the last position, because it is the most current
    listers[numListers] = memoLister;

    numListers++;
}

void StorageAsyncList::AsyncLoadChunks()
{
    unsigned    i;
    ReadBuffer  firstKey;

    firstKey.Wrap(shardFirstKey);
    for (i = 0; i < numListers; i++)
    {
        listers[i]->Load();
        iterators[i] = listers[i]->First(firstKey);
    }

    stage = MERGE;
    AsyncMergeResult();
}

void StorageAsyncList::AsyncMergeResult()
{
    StorageFileKeyValue*    it;
    StorageAsyncListResult* result;

    result = new StorageAsyncListResult(this);

    while(!IsDone())
    {
        // TODO: Yield
        if (count != 0 && num >= count)
            break;

        it = Next();
        if (it == NULL)
            break;

        if (endKey.GetLength() != 0 && STORAGE_KEY_GREATER_THAN(it->GetKey(), endKey))
            break;

        if (prefix.GetLength() != 0 && !it->GetKey().BeginsWith(prefix))
            break;

        if (offset > 0)
        {
            offset--;
            continue;
        }

        result->Append(it);
        num++;

        if (result->GetSize() > MAX_RESULT_SIZE)
        {
            OnResult(result);
            result = new StorageAsyncListResult(this);
        }
    }

    result->final = true;
    OnResult(result);
}

void StorageAsyncList::OnResult(StorageAsyncListResult* result)
{
    Callable    callable;

    result->dataPage.Finalize();
    result->onComplete = onComplete;
    callable = MFunc<StorageAsyncListResult, &StorageAsyncListResult::OnComplete>(result);
    IOProcessor::Complete(&callable);
}

bool StorageAsyncList::IsDone()
{
    unsigned    i;
    unsigned    numActive;

    if (env->IsShuttingDown())
        return true;

    if (IsAborted())
        return true;

    numActive = 0;
    for (i = 0; i < numListers; i++)
    {
        if (iterators[i] != NULL)
            numActive++;
    }
    if (numActive == 0)
        return true;

    return false;
}

bool StorageAsyncList::IsAborted()
{
    return aborted;
}

void StorageAsyncList::SetAborted(bool aborted_)
{
    aborted = aborted_;
}

StorageFileKeyValue* StorageAsyncList::Next()
{
    unsigned                i;
    unsigned                smallest;
    StorageFileKeyValue*    it;
    ReadBuffer              key;

Restart:
    key.Reset();
    it = NULL;
    smallest = 0;

    // special case when there is only one chunk
    if (numListers == 1)
    {
        it = iterators[0];
        goto Done;
    }

    // listers are sorted by relevance, first is the oldest, last is the latest
    for (i = 0; i < numListers; i++)
    {
        if (iterators[i] != NULL)
        {
            // check that keys are still in the merged interval
            if (shardLastKey.GetLength() > 0 &&
             ReadBuffer::Cmp(iterators[i]->GetKey(), shardLastKey) >= 0)
            {
                iterators[i] = NULL;
                continue;
            }

            // in case of key equality, the lister with the highest chunkID wins
            if (it != NULL && ReadBuffer::Cmp(iterators[i]->GetKey(), key) == 0)
            {
                // in case of DELETE, restart scanning from the first lister
                if (iterators[i]->GetType() == STORAGE_KEYVALUE_TYPE_DELETE)
                {
                    iterators[smallest] = listers[smallest]->Next(iterators[smallest]);
                    iterators[i] = listers[i]->Next(iterators[i]);
                    goto Restart;
                }

                iterators[smallest] = listers[smallest]->Next(iterators[smallest]);
                it = iterators[i];
                smallest = i;
                continue;
            }

            // find the next smallest key
            if (STORAGE_KEY_LESS_THAN(iterators[i]->GetKey(), key))
            {
                if (iterators[i]->GetType() == STORAGE_KEYVALUE_TYPE_DELETE)
                {
                    iterators[i] = listers[i]->Next(iterators[i]);
                    goto Restart;
                }

                it = iterators[i];
                key = it->GetKey();
                smallest =  i;
            }
        }
    }

Done:
    // make progress in the lister that contained the smallest key
    if (it != NULL)
        iterators[smallest] = listers[smallest]->Next(iterators[smallest]);

    return it;
}
<commit_msg>Atka: fixed bug where if there is only one chunk and it contains DELETEs they are returned and an error is triggered.<commit_after>#include "StorageAsyncList.h"
#include "System/Threading/ThreadPool.h"
#include "System/IO/IOProcessor.h"
#include "StorageMemoChunkLister.h"
#include "StorageFileChunkLister.h"
#include "StorageUnwrittenChunkLister.h"
#include "StorageShard.h"
#include "StorageEnvironment.h"

#define MAX_RESULT_SIZE     1024*KiB

StorageAsyncListResult::StorageAsyncListResult(StorageAsyncList* asyncList_) :
 dataPage(NULL, 0)
{
    asyncList = asyncList_;
    final = false;
}

// this is called from main thread
void StorageAsyncListResult::OnComplete()
{
    asyncList->lastResult = this;
    Call(onComplete);
    asyncList->lastResult = NULL;
    if (final)
    {
        asyncList->env->DecreaseNumCursors();
        asyncList->Clear();
    }
    delete this;
}

void StorageAsyncListResult::Append(StorageFileKeyValue* kv)
{
    dataPage.Append(kv);
}

uint32_t StorageAsyncListResult::GetSize()
{
    return dataPage.GetPageBufferSize();
}

StorageAsyncList::StorageAsyncList()
{
    count = 0;
    offset = 0;
    Init();
}

void StorageAsyncList::Init()
{
    ret = false;
    completed = false;
    aborted = false;
    num = 0;
    stage = START;
    threadPool = NULL;
    iterators = NULL;
    listers = NULL;
    numListers = 0;
    lastResult = NULL;
    env = NULL;
}

void StorageAsyncList::Clear()
{
    unsigned    i;

    for (i = 0; i < numListers; i++)
        delete listers[i];
    delete[] listers;
    listers = NULL;
    delete[] iterators;
    iterators = NULL;
    numListers = 0;

    Init();
}

void StorageAsyncList::ExecuteAsyncList()
{
    unsigned                        numChunks;
    uint64_t                        preloadBufferSize;
    StorageChunk**                  itChunk;
    StorageFileChunk*               fileChunk;
    StorageFileChunkLister*         fileLister;
    StorageMemoChunkLister*         memoLister;
    StorageUnwrittenChunkLister*    unwrittenLister;
    Buffer*                         filename;
    StorageChunk::ChunkState        chunkState;
    ReadBuffer                      firstKey;

    Log_Debug("StorageAsyncList START");
    firstKey.Wrap(shardFirstKey);

    if (stage == START)
    {
        shardLastKey.Write(shard->GetLastKey());
        numChunks = shard->GetChunks().GetLength() + 1;

        listers = new StorageChunkLister*[numChunks];
        iterators = new StorageFileKeyValue*[numChunks];
        numListers = 0;
        preloadBufferSize = env->GetConfig().mergeBufferSize / numChunks;

        FOREACH (itChunk, shard->GetChunks())
        {
            chunkState = (*itChunk)->GetChunkState();

            if (chunkState == StorageChunk::Serialized)
            {
                memoLister = new StorageMemoChunkLister;
                memoLister->Init((StorageMemoChunk*) *itChunk, firstKey, count, offset);
                listers[numListers] = memoLister;
                numListers++;
            }
            else if (chunkState == StorageChunk::Unwritten)
            {
                unwrittenLister = new StorageUnwrittenChunkLister;
                unwrittenLister->Init((StorageFileChunk*) *itChunk, firstKey, count, offset);
                listers[numListers] = unwrittenLister;
                numListers++;
            }
            else if (chunkState == StorageChunk::Written)
            {
                fileChunk = (StorageFileChunk*) *itChunk;
                filename = &fileChunk->GetFilename();
                fileLister = new StorageFileChunkLister;
                fileLister->Init(
                 fileChunk->GetFilename(), (type == KEY || type == COUNT), preloadBufferSize);
                listers[numListers] = fileLister;
                numListers++;
            }
        }

        stage = MEMO_CHUNK;
    }

    Log_Debug("StorageAsyncList MEMO_CHUNK");

    if (stage == MEMO_CHUNK)
    {
        LoadMemoChunk();
        stage = FILE_CHUNK;
    }

    Log_Debug("StorageAsyncList FILE_CHUNK");

    if (stage == FILE_CHUNK)
    {
        threadPool->Execute(MFUNC(StorageAsyncList, AsyncLoadChunks));
    }
}

void StorageAsyncList::LoadMemoChunk()
{
    StorageMemoChunkLister* memoLister;
    ReadBuffer              firstKey;

    firstKey.Wrap(shardFirstKey);

    memoLister = new StorageMemoChunkLister;
    memoLister->Init(shard->GetMemoChunk(), firstKey, count, offset);

    // memochunk is always on the last position, because it is the most current
    listers[numListers] = memoLister;

    numListers++;
}

void StorageAsyncList::AsyncLoadChunks()
{
    unsigned    i;
    ReadBuffer  firstKey;

    firstKey.Wrap(shardFirstKey);
    for (i = 0; i < numListers; i++)
    {
        listers[i]->Load();
        iterators[i] = listers[i]->First(firstKey);
    }

    stage = MERGE;
    AsyncMergeResult();
}

void StorageAsyncList::AsyncMergeResult()
{
    StorageFileKeyValue*    it;
    StorageAsyncListResult* result;

    result = new StorageAsyncListResult(this);

    while(!IsDone())
    {
        // TODO: Yield
        if (count != 0 && num >= count)
            break;

        it = Next();
        if (it == NULL)
            break;

        if (endKey.GetLength() != 0 && STORAGE_KEY_GREATER_THAN(it->GetKey(), endKey))
            break;

        if (prefix.GetLength() != 0 && !it->GetKey().BeginsWith(prefix))
            break;

        if (offset > 0)
        {
            offset--;
            continue;
        }

        result->Append(it);
        num++;

        if (result->GetSize() > MAX_RESULT_SIZE)
        {
            OnResult(result);
            result = new StorageAsyncListResult(this);
        }
    }

    result->final = true;
    OnResult(result);
}

void StorageAsyncList::OnResult(StorageAsyncListResult* result)
{
    Callable    callable;

    result->dataPage.Finalize();
    result->onComplete = onComplete;
    callable = MFunc<StorageAsyncListResult, &StorageAsyncListResult::OnComplete>(result);
    IOProcessor::Complete(&callable);
}

bool StorageAsyncList::IsDone()
{
    unsigned    i;
    unsigned    numActive;

    if (env->IsShuttingDown())
        return true;

    if (IsAborted())
        return true;

    numActive = 0;
    for (i = 0; i < numListers; i++)
    {
        if (iterators[i] != NULL)
            numActive++;
    }
    if (numActive == 0)
        return true;

    return false;
}

bool StorageAsyncList::IsAborted()
{
    return aborted;
}

void StorageAsyncList::SetAborted(bool aborted_)
{
    aborted = aborted_;
}

StorageFileKeyValue* StorageAsyncList::Next()
{
    unsigned                i;
    unsigned                smallest;
    StorageFileKeyValue*    it;
    ReadBuffer              key;

Restart:
    key.Reset();
    it = NULL;
    smallest = 0;

    // TODO: special case when there is only one chunk

    // listers are sorted by relevance, first is the oldest, last is the latest
    for (i = 0; i < numListers; i++)
    {
        if (iterators[i] != NULL)
        {
            // check that keys are still in the merged interval
            if (shardLastKey.GetLength() > 0 &&
             ReadBuffer::Cmp(iterators[i]->GetKey(), shardLastKey) >= 0)
            {
                iterators[i] = NULL;
                continue;
            }

            // in case of key equality, the lister with the highest chunkID wins
            if (it != NULL && ReadBuffer::Cmp(iterators[i]->GetKey(), key) == 0)
            {
                // in case of DELETE, restart scanning from the first lister
                if (iterators[i]->GetType() == STORAGE_KEYVALUE_TYPE_DELETE)
                {
                    iterators[smallest] = listers[smallest]->Next(iterators[smallest]);
                    iterators[i] = listers[i]->Next(iterators[i]);
                    goto Restart;
                }

                iterators[smallest] = listers[smallest]->Next(iterators[smallest]);
                it = iterators[i];
                smallest = i;
                continue;
            }

            // find the next smallest key
            if (STORAGE_KEY_LESS_THAN(iterators[i]->GetKey(), key))
            {
                if (iterators[i]->GetType() == STORAGE_KEYVALUE_TYPE_DELETE)
                {
                    iterators[i] = listers[i]->Next(iterators[i]);
                    goto Restart;
                }

                it = iterators[i];
                key = it->GetKey();
                smallest =  i;
            }
        }
    }

Done:
    // make progress in the lister that contained the smallest key
    if (it != NULL)
        iterators[smallest] = listers[smallest]->Next(iterators[smallest]);

    return it;
}
<|endoftext|>


<commit_before>#include <new>
#include <boost/assign/std/vector.hpp>
#include <despoof/config.h>
#include "command_line.h"
#include <despoof/argtable.h>

using namespace std;
using namespace boost::assign;
using namespace despoof;

#define STR2(x) #x
#define STR(x) STR2(x)

void despoof::command_line_to_configuration(configuration &config, int argc, char **argv)
{
	auto interval = alloc_check(arg_int0("i", "interval", "<n>", "Time of one despoof iteration in milliseconds; Default: " STR(DESPOOF_DEFAULT_INTERVAL)));
	auto log_module = alloc_check(arg_str0("o", "log", "<mod>", "Name of the log module, without the \"log\" prefix; Default: " DESPOOF_DEFAULT_LOG_MODULE));
	auto nw_module = alloc_check(arg_str0("n", "network", "<mod>", "Name of the network module, without the \"nw\" prefix; Default: " DESPOOF_DEFAULT_NET_MODULE));
	auto help = alloc_check(arg_lit0("h", "help", "Displays this help text"));
	auto version = alloc_check(arg_lit0("V", "version", "Displays version information"));

	auto end = alloc_check(arg_end(20));
	auto table = make_shared<argtable>();

#ifndef BUILD_SERVICE
	(*table) += help, version;
#endif
	(*table) += interval, log_module, nw_module, end;

	if(arg_parse(argc, argv, table->data()) > 0) {
		throw argtable_error(argv[0], table, end);
	}

	if(interval->count > 0) {
		config.interval = interval->ival[0];
	}
	if(log_module->count > 0) {
		config.log_module = log_module->sval[0];
	}
	if(nw_module->count > 0) {
		config.nw_module = nw_module->sval[0];
	}
	if(help->count > 0) {
		print_help(*table, argv[0]);
		config._nostart = true;
	}
	if(version->count > 0) {
		printf("%s\n%s\n\n", "Despoof " DESPOOF_VERSION, "Copyright (c) 2011 - 2012 Raphael Robatsch. All rights reserved.");
		printf("%s\n%s\n", "See the accompanying \"COPYING.txt\" file for the license agreement", "of this software.");
		printf("%s\n\"%s\".\n", "If there is no COPYING.txt in your software distribution, see", "https://raw.github.com/raphaelr/despoof/master/COPYING.txt", ".");
		config._nostart = true;
	}
}
<commit_msg>prettier --version output<commit_after>#include <new>
#include <boost/assign/std/vector.hpp>
#include <despoof/config.h>
#include "command_line.h"
#include <despoof/argtable.h>

using namespace std;
using namespace boost::assign;
using namespace despoof;

#define STR2(x) #x
#define STR(x) STR2(x)

void despoof::command_line_to_configuration(configuration &config, int argc, char **argv)
{
	auto interval = alloc_check(arg_int0("i", "interval", "<n>", "Time of one despoof iteration in milliseconds; Default: " STR(DESPOOF_DEFAULT_INTERVAL)));
	auto log_module = alloc_check(arg_str0("o", "log", "<mod>", "Name of the log module, without the \"log\" prefix; Default: " DESPOOF_DEFAULT_LOG_MODULE));
	auto nw_module = alloc_check(arg_str0("n", "network", "<mod>", "Name of the network module, without the \"nw\" prefix; Default: " DESPOOF_DEFAULT_NET_MODULE));
	auto help = alloc_check(arg_lit0("h", "help", "Displays this help text"));
	auto version = alloc_check(arg_lit0("V", "version", "Displays version information"));

	auto end = alloc_check(arg_end(20));
	auto table = make_shared<argtable>();

#ifndef BUILD_SERVICE
	(*table) += help, version;
#endif
	(*table) += interval, log_module, nw_module, end;

	if(arg_parse(argc, argv, table->data()) > 0) {
		throw argtable_error(argv[0], table, end);
	}

	if(interval->count > 0) {
		config.interval = interval->ival[0];
	}
	if(log_module->count > 0) {
		config.log_module = log_module->sval[0];
	}
	if(nw_module->count > 0) {
		config.nw_module = nw_module->sval[0];
	}
	if(help->count > 0) {
		print_help(*table, argv[0]);
		config._nostart = true;
	}
	if(version->count > 0) {
		printf("%s\n%s\n\n", "Despoof " DESPOOF_VERSION, "Copyright (c) 2011 - 2012 Raphael Robatsch. All rights reserved.");
		printf("%s\n%s\n", "See the accompanying \"COPYING.txt\" file for the license agreement", "of this software. If there is no COPYING.txt in your software distribution, see");
		printf("\"%s\".\n", "https://raw.github.com/raphaelr/despoof/master/COPYING.txt", ".");
		config._nostart = true;
	}
}
<|endoftext|>


<commit_before>#include "../include/CVC4solver.hpp"

#include <math.h>

using namespace CVC4;
using namespace std;

vector<int> CVC4Solver::solve(vector<double>& coef,
                              vector<int>& free,
                              vector<vector<int>>& clauses,
                              int n,
                              bool v)
{
    ExprManager em;
    SmtEngine smt(&em);

    vector<int> result;

    smt.setOption("incremental", SExpr("true"));
    smt.setOption("produce-models", SExpr("true"));
    GetModelCommand cExample = GetModelCommand();

    vector<Expr> A = Avector(coef, &em);

    vector<Expr> X = Xvector(n, free, &em);

    Expr X_EQ_1_OR_0 = XDomain(X, &em);

    Expr restrictions = makeClauses(X, clauses, &em);

    Expr inequation  = CVC4Solver::inequation(X, A, free, &em);

    smt.assertFormula(em.mkExpr(Kind::AND, X_EQ_1_OR_0, restrictions));

    smt.push();
    string isSat = smt.checkSat(inequation).toString();
    bool sat = isSat.compare("unsat");

    if(v)
    {
        cout << "\nThe inequation is "<< isSat;
        if(sat)
        {
            cout << " and a solution is:" << "\n";
            cExample.invoke(&smt);
            cExample.printResult(cout);
        }
        cout << "\n\n";

        cout << "The inequation:" << "\n";
        cout << inequation  << "\n\n";
        cout << "The Domain for the variables:" << "\n";
        cout << X_EQ_1_OR_0 << "\n\n";
    }

    if(sat)
    {
        result.push_back(1);
        for(int i = 0, j = 0; i < X.size(); i++)
        {
            if(free.size() > 0 && i == free[j])
                j++;
            else
            {
                string temp = smt.getValue(X[i]).toString();
                if(temp.at(0) == '(')
                    result.push_back(atoi(temp.substr(16).c_str()));
                else
                    result.push_back(atoi(temp.substr(0).c_str()));
            }
        }
    }
    else
    {
        result.push_back(0);
        for(int i = 0; i < X.size(); i++)
            result.push_back(0);
    }
    smt.pop();

    return result;

}

vector<Expr> CVC4Solver::Xvector(int n,
                                 vector<int>& free,
                                 ExprManager* em)
{
    vector<Expr> X;

    for(int i = 0; i < n + free.size(); i++)
        X.push_back(em->mkVar("x" + to_string(i+1),
                              em->integerType()));

    return X;
}

vector<Expr> CVC4Solver::Avector(vector<double>& coef, ExprManager* em)
{
    vector<Expr> A;

    for(int i = 0; i < coef.size(); i++)
    {
        int temp = 100000;
        A.push_back(em->mkConst(Rational(ceil(temp*coef[i]), temp)));
    }

    return A;
}

Expr CVC4Solver::XDomain(vector<Expr>& X, ExprManager* em)
{
    vector<Expr> X_domain;

    Expr one  = em->mkConst(Rational(1));
    Expr zero = em->mkConst(Rational(0));

    Expr Xi_EQ_one;
    Expr Xi_EQ_zero;

    for(int i = 0; i < X.size(); i++)
    {
        Xi_EQ_one  = em->mkExpr(Kind::EQUAL, X[i], one );
        Xi_EQ_zero = em->mkExpr(Kind::EQUAL, X[i], zero);
        X_domain.push_back(em->mkExpr(Kind::OR,
                                      Xi_EQ_one,
                                      Xi_EQ_zero));
    }

    return em->mkExpr(Kind::AND, X_domain);
}

Expr CVC4Solver::makeClauses(vector<Expr>&        X,
                             vector<vector<int>>& clauses,
                             ExprManager*         em)
{
    vector<Expr> temp;
    vector<Expr> assertions;
    Expr         expression;

    Expr one  = em->mkConst(Rational(1));
    Expr zero = em->mkConst(Rational(0));

    for(int i = 0; i < clauses.size(); i++)
    {
        for(int j = 0; j < clauses[i].size(); j++)
        {
            if(clauses[i][j] < 0)
            {
                int index = -clauses[i][j];
                expression = em->mkExpr(Kind::EQUAL, X[index-1], zero);
            }
            else
            {
                int index  = clauses[i][j];
                expression = em->mkExpr(Kind::EQUAL, X[index-1], one);
            }
            temp.push_back(expression);
        }
        if(temp.size() > 1)
            assertions.push_back(em->mkExpr(Kind::OR, temp));
        else
            assertions.push_back(temp[0]);
        temp.clear();
    }

    return em->mkExpr(Kind::AND, assertions);
}

Expr CVC4Solver::inequation(vector<Expr>& X,
                            vector<Expr>& A,
                            vector<int>& free,
                            ExprManager* em)
{
    Rational error((int) A.size() + 10, delta);

    Expr x_MUL_a;
    Expr zero = em->mkConst(error);
    Expr inequation;

    vector<Expr> Xi_MUL_Ai;

    Xi_MUL_Ai.push_back(A[0]);

    for(int i = 0, j = 0; i < X.size(); i++)
    {
        if(free.size() > 0 && i == free[j])
            j++;
        else
        {
            x_MUL_a = em->mkExpr(Kind::MULT, X[i], A[i+1-j]);
            Xi_MUL_Ai.push_back(x_MUL_a);
        }
    }

    inequation = em->mkExpr(Kind::PLUS, Xi_MUL_Ai);

    return em->mkExpr(Kind::GT, inequation, zero);
}
<commit_msg>working on test<commit_after>#include "../include/CVC4solver.hpp"

#include <math.h>

using namespace CVC4;
using namespace std;

vector<int> CVC4Solver::solve(vector<double>& coef,
                              vector<int>& free,
                              vector<vector<int>>& clauses,
                              int n,
                              bool v)
{
    ExprManager em;
    SmtEngine smt(&em);

    vector<int> result;

    smt.setOption("incremental", SExpr("true"));
    smt.setOption("produce-models", SExpr("true"));
    GetModelCommand cExample = GetModelCommand();

    vector<Expr> A = Avector(coef, &em);

    vector<Expr> X = Xvector(n, free, &em);

    Expr X_EQ_1_OR_0 = XDomain(X, &em);

    Expr restrictions = makeClauses(X, clauses, &em);

    Expr inequation  = CVC4Solver::inequation(X, A, free, &em);

    smt.assertFormula(em.mkExpr(Kind::AND, X_EQ_1_OR_0, restrictions));

    smt.push();
    string isSat = smt.checkSat(inequation).toString();
    bool sat = isSat.compare("unsat");

    if(v)
    {
        cout << "\nThe inequation is "<< isSat;
        if(sat)
        {
            cout << " and a solution is:" << "\n";
            cExample.invoke(&smt);
            cExample.printResult(cout);
        }
        cout << "\n\n";

        cout << "The inequation:" << "\n";
        cout << inequation  << "\n\n";
        cout << "The Domain for the variables:" << "\n";
        cout << X_EQ_1_OR_0 << "\n\n";
    }

    if(sat)
    {
        result.push_back(1);
        for(int i = 0, j = 0; i < X.size(); i++)
        {
            if(free.size() > 0 && i == free[j])
                j++;
            else
            {
                string temp = smt.getValue(X[i]).toString();
                if(temp.at(0) == '(')
                    result.push_back(atoi(temp.substr(16).c_str()));
                else
                    result.push_back(atoi(temp.substr(0).c_str()));
            }
        }
    }
    else
    {
        result.push_back(0);
        for(int i = 0; i < X.size(); i++)
            result.push_back(0);
    }
    smt.pop();

    return result;

}

vector<Expr> CVC4Solver::Xvector(int n,
                                 vector<int>& free,
                                 ExprManager* em)
{
    vector<Expr> X;

    for(int i = 0; i < n + free.size(); i++)
        X.push_back(em->mkVar("x" + to_string(i+1),
                              em->integerType()));

    return X;
}

vector<Expr> CVC4Solver::Avector(vector<double>& coef, ExprManager* em)
{
    vector<Expr> A;

    for(int i = 0; i < coef.size(); i++)
    {
        int temp = 100000;
        A.push_back(em->mkConst(Rational(ceil(temp*coef[i]), temp)));
    }

    return A;
}

Expr CVC4Solver::XDomain(vector<Expr>& X, ExprManager* em)
{
    vector<Expr> X_domain;

    Expr one  = em->mkConst(Rational(1));
    Expr zero = em->mkConst(Rational(0));

    Expr Xi_EQ_one;
    Expr Xi_EQ_zero;

    for(int i = 0; i < X.size(); i++)
    {
        Xi_EQ_one  = em->mkExpr(Kind::EQUAL, X[i], one );
        Xi_EQ_zero = em->mkExpr(Kind::EQUAL, X[i], zero);
        X_domain.push_back(em->mkExpr(Kind::OR,
                                      Xi_EQ_one,
                                      Xi_EQ_zero));
    }

    return em->mkExpr(Kind::AND, X_domain);
}

Expr CVC4Solver::makeClauses(vector<Expr>&        X,
                             vector<vector<int>>& clauses,
                             ExprManager*         em)
{
    vector<Expr> temp;
    vector<Expr> assertions;
    Expr         expression;

    Expr one  = em->mkConst(Rational(1));
    Expr zero = em->mkConst(Rational(0));

    for(int i = 0; i < clauses.size(); i++)
    {
        for(int j = 0; j < clauses[i].size(); j++)
        {
            if(clauses[i][j] < 0)
            {
                int index = -clauses[i][j];
                expression = em->mkExpr(Kind::EQUAL, X[index-1], zero);
            }
            else
            {
                int index  = clauses[i][j];
                expression = em->mkExpr(Kind::EQUAL, X[index-1], one);
            }
            temp.push_back(expression);
        }
        if(temp.size() > 1)
            assertions.push_back(em->mkExpr(Kind::OR, temp));
        else
            assertions.push_back(temp[0]);
        temp.clear();
    }

    return em->mkExpr(Kind::AND, assertions);
}

Expr CVC4Solver::inequation(vector<Expr>& X,
                            vector<Expr>& A,
                            vector<int>& free,
                            ExprManager* em)
{
    Rational error((int) A.size() + 100, delta);

    Expr x_MUL_a;
    Expr zero = em->mkConst(error);
    Expr inequation;

    vector<Expr> Xi_MUL_Ai;

    Xi_MUL_Ai.push_back(A[0]);

    for(int i = 0, j = 0; i < X.size(); i++)
    {
        if(free.size() > 0 && i == free[j])
            j++;
        else
        {
            x_MUL_a = em->mkExpr(Kind::MULT, X[i], A[i+1-j]);
            Xi_MUL_Ai.push_back(x_MUL_a);
        }
    }

    inequation = em->mkExpr(Kind::PLUS, Xi_MUL_Ai);

    return em->mkExpr(Kind::GT, inequation, zero);
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2006 The Regents of The University of Michigan
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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
 * OWNER 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 <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>

#include <string>

#include "sim/pseudo_inst.hh"
#include "arch/vtophys.hh"
#include "cpu/base.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/exec_context.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
#include "sim/param.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
#include "sim/stat_control.hh"
#include "sim/stats.hh"
#include "sim/system.hh"
#include "sim/debug.hh"
#include "sim/vptr.hh"

using namespace std;

extern Sampler *SampCPU;

using namespace Stats;
using namespace TheISA;

namespace AlphaPseudo
{
    bool doStatisticsInsts;
    bool doCheckpointInsts;
    bool doQuiesce;

    void
    arm(ExecContext *xc)
    {
        if (xc->getKernelStats())
            xc->getKernelStats()->arm();
    }

    void
    quiesce(ExecContext *xc)
    {
        if (!doQuiesce)
            return;

        xc->suspend();
        if (xc->getKernelStats())
            xc->getKernelStats()->arm();
    }

    void
    quiesceNs(ExecContext *xc, uint64_t ns)
    {
        if (!doQuiesce || ns == 0)
            return;

        EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();

        if (quiesceEvent->scheduled())
            quiesceEvent->reschedule(curTick + Clock::Int::ns * ns);
        else
            quiesceEvent->schedule(curTick + Clock::Int::ns * ns);

        xc->suspend();
        if (xc->getKernelStats())
            xc->getKernelStats()->quiesce();
    }

    void
    quiesceCycles(ExecContext *xc, uint64_t cycles)
    {
        if (!doQuiesce || cycles == 0)
            return;

        EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();

        if (quiesceEvent->scheduled())
            quiesceEvent->reschedule(curTick +
                                     xc->getCpuPtr()->cycles(cycles));
        else
            quiesceEvent->schedule(curTick +
                                   xc->getCpuPtr()->cycles(cycles));

        xc->suspend();
        if (xc->getKernelStats())
            xc->getKernelStats()->quiesce();
    }

    uint64_t
    quiesceTime(ExecContext *xc)
    {
        return (xc->readLastActivate() - xc->readLastSuspend()) / Clock::Int::ns;
    }

    void
    ivlb(ExecContext *xc)
    {
        if (xc->getKernelStats())
            xc->getKernelStats()->ivlb();
    }

    void
    ivle(ExecContext *xc)
    {
    }

    void
    m5exit_old(ExecContext *xc)
    {
        SimExit(curTick, "m5_exit_old instruction encountered");
    }

    void
    m5exit(ExecContext *xc, Tick delay)
    {
        Tick when = curTick + delay * Clock::Int::ns;
        SimExit(when, "m5_exit instruction encountered");
    }

    void
    resetstats(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doStatisticsInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        using namespace Stats;
        SetupEvent(Reset, when, repeat);
    }

    void
    dumpstats(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doStatisticsInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        using namespace Stats;
        SetupEvent(Dump, when, repeat);
    }

    void
    addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr)
    {
        char symb[100];
        CopyString(xc, symb, symbolAddr, 100);
        std::string symbol(symb);

        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);

        xc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
    }

    void
    dumpresetstats(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doStatisticsInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        using namespace Stats;
        SetupEvent(Dump|Reset, when, repeat);
    }

    void
    m5checkpoint(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doCheckpointInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        Checkpoint::setup(when, repeat);
    }

    uint64_t
    readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset)
    {
        const string &file = xc->getCpuPtr()->system->params()->readfile;
        if (file.empty()) {
            return ULL(0);
        }

        uint64_t result = 0;

        int fd = ::open(file.c_str(), O_RDONLY, 0);
        if (fd < 0)
            panic("could not open file %s\n", file);

        if (::lseek(fd, offset, SEEK_SET) < 0)
            panic("could not seek: %s", strerror(errno));

        char *buf = new char[len];
        char *p = buf;
        while (len > 0) {
            int bytes = ::read(fd, p, len);
            if (bytes <= 0)
                break;

            p += bytes;
            result += bytes;
            len -= bytes;
        }

        close(fd);
        CopyIn(xc, vaddr, buf, result);
        delete [] buf;
        return result;
    }

    class Context : public ParamContext
    {
      public:
        Context(const string &section) : ParamContext(section) {}
        void checkParams();
    };

    Context context("pseudo_inst");

    Param<bool> __quiesce(&context, "quiesce",
                          "enable quiesce instructions",
                          true);
    Param<bool> __statistics(&context, "statistics",
                             "enable statistics pseudo instructions",
                             true);
    Param<bool> __checkpoint(&context, "checkpoint",
                             "enable checkpoint pseudo instructions",
                             true);

    void
    Context::checkParams()
    {
        doQuiesce = __quiesce;
        doStatisticsInsts = __statistics;
        doCheckpointInsts = __checkpoint;
    }

    void debugbreak(ExecContext *xc)
    {
        debug_break();
    }

    void switchcpu(ExecContext *xc)
    {
        if (SampCPU)
            SampCPU->switchCPUs();
    }
}
<commit_msg>Fix stat typo.<commit_after>/*
 * Copyright (c) 2003-2006 The Regents of The University of Michigan
 * 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;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * 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
 * OWNER 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 <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>

#include <string>

#include "sim/pseudo_inst.hh"
#include "arch/vtophys.hh"
#include "cpu/base.hh"
#include "cpu/sampler/sampler.hh"
#include "cpu/exec_context.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
#include "sim/param.hh"
#include "sim/serialize.hh"
#include "sim/sim_exit.hh"
#include "sim/stat_control.hh"
#include "sim/stats.hh"
#include "sim/system.hh"
#include "sim/debug.hh"
#include "sim/vptr.hh"

using namespace std;

extern Sampler *SampCPU;

using namespace Stats;
using namespace TheISA;

namespace AlphaPseudo
{
    bool doStatisticsInsts;
    bool doCheckpointInsts;
    bool doQuiesce;

    void
    arm(ExecContext *xc)
    {
        if (xc->getKernelStats())
            xc->getKernelStats()->arm();
    }

    void
    quiesce(ExecContext *xc)
    {
        if (!doQuiesce)
            return;

        xc->suspend();
        if (xc->getKernelStats())
            xc->getKernelStats()->quiesce();
    }

    void
    quiesceNs(ExecContext *xc, uint64_t ns)
    {
        if (!doQuiesce || ns == 0)
            return;

        EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();

        if (quiesceEvent->scheduled())
            quiesceEvent->reschedule(curTick + Clock::Int::ns * ns);
        else
            quiesceEvent->schedule(curTick + Clock::Int::ns * ns);

        xc->suspend();
        if (xc->getKernelStats())
            xc->getKernelStats()->quiesce();
    }

    void
    quiesceCycles(ExecContext *xc, uint64_t cycles)
    {
        if (!doQuiesce || cycles == 0)
            return;

        EndQuiesceEvent *quiesceEvent = xc->getQuiesceEvent();

        if (quiesceEvent->scheduled())
            quiesceEvent->reschedule(curTick +
                                     xc->getCpuPtr()->cycles(cycles));
        else
            quiesceEvent->schedule(curTick +
                                   xc->getCpuPtr()->cycles(cycles));

        xc->suspend();
        if (xc->getKernelStats())
            xc->getKernelStats()->quiesce();
    }

    uint64_t
    quiesceTime(ExecContext *xc)
    {
        return (xc->readLastActivate() - xc->readLastSuspend()) / Clock::Int::ns;
    }

    void
    ivlb(ExecContext *xc)
    {
        if (xc->getKernelStats())
            xc->getKernelStats()->ivlb();
    }

    void
    ivle(ExecContext *xc)
    {
    }

    void
    m5exit_old(ExecContext *xc)
    {
        SimExit(curTick, "m5_exit_old instruction encountered");
    }

    void
    m5exit(ExecContext *xc, Tick delay)
    {
        Tick when = curTick + delay * Clock::Int::ns;
        SimExit(when, "m5_exit instruction encountered");
    }

    void
    resetstats(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doStatisticsInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        using namespace Stats;
        SetupEvent(Reset, when, repeat);
    }

    void
    dumpstats(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doStatisticsInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        using namespace Stats;
        SetupEvent(Dump, when, repeat);
    }

    void
    addsymbol(ExecContext *xc, Addr addr, Addr symbolAddr)
    {
        char symb[100];
        CopyString(xc, symb, symbolAddr, 100);
        std::string symbol(symb);

        DPRINTF(Loader, "Loaded symbol: %s @ %#llx\n", symbol, addr);

        xc->getSystemPtr()->kernelSymtab->insert(addr,symbol);
    }

    void
    dumpresetstats(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doStatisticsInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        using namespace Stats;
        SetupEvent(Dump|Reset, when, repeat);
    }

    void
    m5checkpoint(ExecContext *xc, Tick delay, Tick period)
    {
        if (!doCheckpointInsts)
            return;

        Tick when = curTick + delay * Clock::Int::ns;
        Tick repeat = period * Clock::Int::ns;

        Checkpoint::setup(when, repeat);
    }

    uint64_t
    readfile(ExecContext *xc, Addr vaddr, uint64_t len, uint64_t offset)
    {
        const string &file = xc->getCpuPtr()->system->params()->readfile;
        if (file.empty()) {
            return ULL(0);
        }

        uint64_t result = 0;

        int fd = ::open(file.c_str(), O_RDONLY, 0);
        if (fd < 0)
            panic("could not open file %s\n", file);

        if (::lseek(fd, offset, SEEK_SET) < 0)
            panic("could not seek: %s", strerror(errno));

        char *buf = new char[len];
        char *p = buf;
        while (len > 0) {
            int bytes = ::read(fd, p, len);
            if (bytes <= 0)
                break;

            p += bytes;
            result += bytes;
            len -= bytes;
        }

        close(fd);
        CopyIn(xc, vaddr, buf, result);
        delete [] buf;
        return result;
    }

    class Context : public ParamContext
    {
      public:
        Context(const string &section) : ParamContext(section) {}
        void checkParams();
    };

    Context context("pseudo_inst");

    Param<bool> __quiesce(&context, "quiesce",
                          "enable quiesce instructions",
                          true);
    Param<bool> __statistics(&context, "statistics",
                             "enable statistics pseudo instructions",
                             true);
    Param<bool> __checkpoint(&context, "checkpoint",
                             "enable checkpoint pseudo instructions",
                             true);

    void
    Context::checkParams()
    {
        doQuiesce = __quiesce;
        doStatisticsInsts = __statistics;
        doCheckpointInsts = __checkpoint;
    }

    void debugbreak(ExecContext *xc)
    {
        debug_break();
    }

    void switchcpu(ExecContext *xc)
    {
        if (SampCPU)
            SampCPU->switchCPUs();
    }
}
<|endoftext|>


<commit_before>#pragma once

#include "filesystem.hpp"
#include "json_utility.hpp"
#include "logger.hpp"
#include "types.hpp"
#include <fstream>
#include <iostream>
#include <json/json.hpp>
#include <string>

namespace krbn {
class manipulator_environment final {
public:
  class frontmost_application final {
  public:
    frontmost_application(void) {
    }

    frontmost_application(const std::string& bundle_identifier,
                          const std::string& file_path) : bundle_identifier_(bundle_identifier),
                                                          file_path_(file_path) {
    }

    frontmost_application(const nlohmann::json& json) {
      if (json.is_object()) {
        for (auto it = std::begin(json); it != std::end(json); std::advance(it, 1)) {
          // it.key() is always std::string.
          const auto& key = it.key();
          const auto& value = it.value();

          if (key == "bundle_identifier") {
            if (value.is_string()) {
              bundle_identifier_ = value.get<std::string>();
            } else {
              logger::get_logger().error("bundle_identifier should be string: {0}", json.dump());
            }
          } else if (key == "file_path") {
            if (value.is_string()) {
              file_path_ = value.get<std::string>();
            } else {
              logger::get_logger().error("file_path should be string: {0}", json.dump());
            }
          } else {
            logger::get_logger().error("json error: Unknown key: {0} in {1}", key, json.dump());
          }
        }
      } else {
        logger::get_logger().error("frontmost_application should be object: {0}", json.dump());
      }
    }

    nlohmann::json to_json(void) const {
      return nlohmann::json({
          {"bundle_identifier", bundle_identifier_},
          {"file_path", file_path_},
      });
    }

    const std::string& get_bundle_identifier(void) const {
      return bundle_identifier_;
    }

    const std::string& get_file_path(void) const {
      return file_path_;
    }

    bool operator==(const frontmost_application& other) const {
      return bundle_identifier_ == other.bundle_identifier_ &&
             file_path_ == other.file_path_;
    }

  private:
    std::string bundle_identifier_;
    std::string file_path_;
  };

  manipulator_environment(const manipulator_environment&) = delete;

  manipulator_environment(void) {
  }

  nlohmann::json to_json(void) const {
    return nlohmann::json({
        {"frontmost_application", frontmost_application_.to_json()},
        {"input_source_identifiers", input_source_identifiers_.to_json()},
        {"variables", variables_},
        {"keyboard_type", keyboard_type_},
    });
  }

  void enable_json_output(const std::string& output_json_file_path) {
    output_json_file_path_ = output_json_file_path;
  }

  void disable_json_output(void) {
    output_json_file_path_.clear();
  }

  const frontmost_application& get_frontmost_application(void) const {
    return frontmost_application_;
  }

  void set_frontmost_application(const frontmost_application& value) {
    frontmost_application_ = value;
    save_to_file();
  }

  const input_source_identifiers& get_input_source_identifiers(void) const {
    return input_source_identifiers_;
  }

  void set_input_source_identifiers(const input_source_identifiers& value) {
    input_source_identifiers_ = value;
    save_to_file();
  }

  int get_variable(const std::string& name) const {
    auto it = variables_.find(name);
    if (it != std::end(variables_)) {
      return it->second;
    }
    return 0;
  }

  void set_variable(const std::string& name, int value) {
    // logger::get_logger().info("set_variable {0} {1}", name, value);
    variables_[name] = value;
    save_to_file();
  }

  const std::string& get_keyboard_type(void) const {
    return keyboard_type_;
  }

  void set_keyboard_type(const std::string& value) {
    keyboard_type_ = value;
    save_to_file();
  }

private:
  void save_to_file(void) const {
    if (!output_json_file_path_.empty()) {
      filesystem::create_directory_with_intermediate_directories(filesystem::dirname(output_json_file_path_), 0755);
      json_utility::save_to_file(to_json(), output_json_file_path_);
    }
  }

  std::string output_json_file_path_;
  frontmost_application frontmost_application_;
  input_source_identifiers input_source_identifiers_;
  std::unordered_map<std::string, int> variables_;
  std::string keyboard_type_;
};

inline std::ostream& operator<<(std::ostream& stream, const manipulator_environment::frontmost_application& value) {
  stream << value.get_bundle_identifier() << "," << value.get_file_path();
  return stream;
}
} // namespace krbn
<commit_msg>add frontmost_application::hash_value<commit_after>#pragma once

#include "boost_defs.hpp"

#include "filesystem.hpp"
#include "json_utility.hpp"
#include "logger.hpp"
#include "types.hpp"
#include <boost/functional/hash.hpp>
#include <fstream>
#include <iostream>
#include <json/json.hpp>
#include <string>

namespace krbn {
class manipulator_environment final {
public:
  class frontmost_application final {
  public:
    frontmost_application(void) {
    }

    frontmost_application(const std::string& bundle_identifier,
                          const std::string& file_path) : bundle_identifier_(bundle_identifier),
                                                          file_path_(file_path) {
    }

    frontmost_application(const nlohmann::json& json) {
      if (json.is_object()) {
        for (auto it = std::begin(json); it != std::end(json); std::advance(it, 1)) {
          // it.key() is always std::string.
          const auto& key = it.key();
          const auto& value = it.value();

          if (key == "bundle_identifier") {
            if (value.is_string()) {
              bundle_identifier_ = value.get<std::string>();
            } else {
              logger::get_logger().error("bundle_identifier should be string: {0}", json.dump());
            }
          } else if (key == "file_path") {
            if (value.is_string()) {
              file_path_ = value.get<std::string>();
            } else {
              logger::get_logger().error("file_path should be string: {0}", json.dump());
            }
          } else {
            logger::get_logger().error("json error: Unknown key: {0} in {1}", key, json.dump());
          }
        }
      } else {
        logger::get_logger().error("frontmost_application should be object: {0}", json.dump());
      }
    }

    nlohmann::json to_json(void) const {
      return nlohmann::json({
          {"bundle_identifier", bundle_identifier_},
          {"file_path", file_path_},
      });
    }

    const std::string& get_bundle_identifier(void) const {
      return bundle_identifier_;
    }

    const std::string& get_file_path(void) const {
      return file_path_;
    }

    size_t hash_value(void) const {
      size_t h = 0;
      boost::hash_combine(h, bundle_identifier_);
      boost::hash_combine(h, file_path_);
      return h;
    }

    bool operator==(const frontmost_application& other) const {
      return bundle_identifier_ == other.bundle_identifier_ &&
             file_path_ == other.file_path_;
    }

  private:
    std::string bundle_identifier_;
    std::string file_path_;
  };

  manipulator_environment(const manipulator_environment&) = delete;

  manipulator_environment(void) {
  }

  nlohmann::json to_json(void) const {
    return nlohmann::json({
        {"frontmost_application", frontmost_application_.to_json()},
        {"input_source_identifiers", input_source_identifiers_.to_json()},
        {"variables", variables_},
        {"keyboard_type", keyboard_type_},
    });
  }

  void enable_json_output(const std::string& output_json_file_path) {
    output_json_file_path_ = output_json_file_path;
  }

  void disable_json_output(void) {
    output_json_file_path_.clear();
  }

  const frontmost_application& get_frontmost_application(void) const {
    return frontmost_application_;
  }

  void set_frontmost_application(const frontmost_application& value) {
    frontmost_application_ = value;
    save_to_file();
  }

  const input_source_identifiers& get_input_source_identifiers(void) const {
    return input_source_identifiers_;
  }

  void set_input_source_identifiers(const input_source_identifiers& value) {
    input_source_identifiers_ = value;
    save_to_file();
  }

  int get_variable(const std::string& name) const {
    auto it = variables_.find(name);
    if (it != std::end(variables_)) {
      return it->second;
    }
    return 0;
  }

  void set_variable(const std::string& name, int value) {
    // logger::get_logger().info("set_variable {0} {1}", name, value);
    variables_[name] = value;
    save_to_file();
  }

  const std::string& get_keyboard_type(void) const {
    return keyboard_type_;
  }

  void set_keyboard_type(const std::string& value) {
    keyboard_type_ = value;
    save_to_file();
  }

private:
  void save_to_file(void) const {
    if (!output_json_file_path_.empty()) {
      filesystem::create_directory_with_intermediate_directories(filesystem::dirname(output_json_file_path_), 0755);
      json_utility::save_to_file(to_json(), output_json_file_path_);
    }
  }

  std::string output_json_file_path_;
  frontmost_application frontmost_application_;
  input_source_identifiers input_source_identifiers_;
  std::unordered_map<std::string, int> variables_;
  std::string keyboard_type_;
};

inline std::ostream& operator<<(std::ostream& stream, const manipulator_environment::frontmost_application& value) {
  stream << value.get_bundle_identifier() << "," << value.get_file_path();
  return stream;
}
} // namespace krbn

namespace std {
template <>
struct hash<krbn::manipulator_environment::frontmost_application> {
  std::size_t operator()(const krbn::manipulator_environment::frontmost_application& v) const {
    return v.hash_value();
  }
};
} // namespace std
<|endoftext|>


<commit_before>#include <cmath>
#include <iostream>
#include <ale_interface.hpp>
#include <glog/logging.h>
#include <gflags/gflags.h>
#include "prettyprint.hpp"
#include "dqn.hpp"

// DQN Parameters
DEFINE_bool(gpu, true, "Use GPU to brew Caffe");
DEFINE_bool(gui, false, "Open a GUI window");
DEFINE_string(rom, "roms/pong.bin", "Atari 2600 ROM to play");
DEFINE_int32(memory, 400000, "Capacity of replay memory");
DEFINE_int32(explore, 1000000, "Number of iterations needed for epsilon to reach given value.");
DEFINE_double(epsilon, 0.05, "Value of epsilon reached after explore iterations.");
DEFINE_double(gamma, 0.95, "Discount factor of future rewards (0,1]");
DEFINE_int32(memory_threshold, 100, "Enough amount of transitions to start learning");
DEFINE_int32(skip_frame, 3, "Number of frames skipped");
DEFINE_bool(show_frame, false, "Show the current frame in CUI");
DEFINE_string(save_screen, "", "File prefix in to save frames");
DEFINE_string(save_binary_screen, "", "File prefix in to save binary frames");
DEFINE_string(weights, "", "The pretrained weights load (*.caffemodel).");
DEFINE_string(snapshot, "", "The solver state to load (*.solverstate).");
DEFINE_bool(evaluate, false, "Evaluation mode: only playing a game, no updates");
DEFINE_double(evaluate_with_epsilon, 0.05, "Epsilon value to be used in evaluation mode");
DEFINE_double(repeat_games, 10, "Number of games played in evaluation mode");
// Solver Parameters
DEFINE_string(solver, "", "Solver parameter file (*.prototxt)");
DEFINE_string(solver_type, "ADADELTA", "Type of solver.");
DEFINE_string(model, "dqn.prototxt", "The model definition (*.prototxt).");
DEFINE_double(momentum, 0.95, "Solver momentum");
DEFINE_double(base_lr, 0.1, "Solver base learning rate");
DEFINE_string(lr_policy, "step", "Solver lr policy");
DEFINE_double(solver_gamma, 0.1, "Solver gamma");
DEFINE_int32(stepsize, 10000000, "Solver stepsize");
DEFINE_int32(max_iter, 10000000, "Maximum number of iterations");
DEFINE_int32(snapshot_frequency, 1000000, "Snapshot frequency in iterations");
DEFINE_int32(display, 10000, "Display frequency in iterations");
DEFINE_string(snapshot_prefix, "state/dqn", "Prefix for saving snapshots");

double CalculateEpsilon(const int iter) {
  if (iter < FLAGS_explore) {
    return 1.0 - (1.0 - FLAGS_epsilon) * (static_cast<double>(iter) / FLAGS_explore);
  } else {
    return FLAGS_epsilon;
  }
}

void SaveScreen(const ALEScreen& screen, const ALEInterface& ale,
                const string filename) {
  IntMatrix screen_matrix;
  for (auto row = 0; row < screen.height(); row++) {
    IntVect row_vec;
    for (auto col = 0; col < screen.width(); col++) {
      int pixel = screen.get(row, col);
      row_vec.emplace_back(pixel);
    }
    screen_matrix.emplace_back(row_vec);
  }
  // ale.theOSystem->p_export_screen->save_png(&screen_matrix, filename);
}

void SaveInputFrames(const dqn::InputFrames& frames, const string filename) {
  std::ofstream ofs;
  ofs.open(filename, ios::out | ios::binary);
  for (int i = 0; i < dqn::kInputFrameCount; ++i) {
    const dqn::FrameData& frame = *frames[i];
    for (int j = 0; j < dqn::kCroppedFrameDataSize; ++j) {
      ofs.write((char*) &frame[j], sizeof(uint8_t));
    }
  }
  ofs.close();
}

/**
 * Play one episode and return the total score
 */
double PlayOneEpisode(ALEInterface& ale, dqn::DQN& dqn, const double epsilon,
                      const bool update) {
  CHECK(!ale.game_over());
  std::deque<dqn::FrameDataSp> past_frames;
  auto total_score = 0.0;
  for (auto frame = 0; !ale.game_over(); ++frame) {
    const ALEScreen& screen = ale.getScreen();
    const auto current_frame = dqn::PreprocessScreen(screen);
    if (FLAGS_show_frame) {
      std::cout << dqn::DrawFrame(*current_frame) << std::endl;
    }
    if (!FLAGS_save_screen.empty()) {
      std::stringstream ss;
      ss << FLAGS_save_screen << setfill('0') << setw(5) <<
          std::to_string(frame) << ".png";
      SaveScreen(screen, ale, ss.str());
    }
    past_frames.push_back(current_frame);
    if (past_frames.size() < dqn::kInputFrameCount) {
      // If there are not past frames enough for DQN input, just select NOOP
      for (auto i = 0; i < FLAGS_skip_frame + 1 && !ale.game_over(); ++i) {
        total_score += ale.act(PLAYER_A_NOOP);
      }
    } else {
      while (past_frames.size() > dqn::kInputFrameCount) {
        past_frames.pop_front();
      }
      dqn::InputFrames input_frames;
      std::copy(past_frames.begin(), past_frames.end(), input_frames.begin());
      if (!FLAGS_save_binary_screen.empty()) {
        static int binary_save_num = 0;
        string fname = FLAGS_save_binary_screen +
            std::to_string(binary_save_num++) + ".bin";
        SaveInputFrames(input_frames, fname);
      }
      const auto action = dqn.SelectAction(input_frames, epsilon);
      auto immediate_score = 0.0;
      for (auto i = 0; i < FLAGS_skip_frame + 1 && !ale.game_over(); ++i) {
        // Last action is repeated on skipped frames
        immediate_score += ale.act(action);
      }
      total_score += immediate_score;
      // Rewards for DQN are normalized as follows:
      // 1 for any positive score, -1 for any negative score, otherwise 0
      const auto reward =
          immediate_score == 0 ?
              0 :
              immediate_score /= std::abs(immediate_score);
      if (update) {
        // Add the current transition to replay memory
        const auto transition = ale.game_over() ?
            dqn::Transition(input_frames, action, reward, boost::none) :
            dqn::Transition(
                input_frames,
                action,
                reward,
                dqn::PreprocessScreen(ale.getScreen()));
        dqn.AddTransition(transition);
        // If the size of replay memory is enough, update DQN
        if (dqn.memory_size() > FLAGS_memory_threshold) {
          dqn.Update();
        }
      }
    }
  }
  ale.reset_game();
  return total_score;
}

/**
 * Evaluate the current player
 */
void Evaluate(ALEInterface& ale, dqn::DQN& dqn) {
  auto total_score = 0.0;
  std::stringstream ss;
  for (auto i = 0; i < FLAGS_repeat_games; ++i) {
    const auto score =
        PlayOneEpisode(ale, dqn, FLAGS_evaluate_with_epsilon, false);
    ss << score << " ";
    total_score += score;
  }
  LOG(INFO) << "Evaluation scores: " << ss.str();
  LOG(INFO) << "Average score: " <<
      total_score / static_cast<double>(FLAGS_repeat_games) << std::endl;
}

int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);
  google::InstallFailureSignalHandler();
  google::LogToStderr();

  if (FLAGS_gpu) {
    caffe::Caffe::set_mode(caffe::Caffe::GPU);
  } else {
    caffe::Caffe::set_mode(caffe::Caffe::CPU);
  }

  ALEInterface ale;
  ale.setBool("display_screen", FLAGS_gui);
  ale.setBool("disable_color_averaging", true);

  // Load the ROM file
  ale.loadROM(FLAGS_rom);

  // Get the vector of legal actions
  const auto legal_actions = ale.getMinimalActionSet();

  CHECK(FLAGS_snapshot.empty() || FLAGS_weights.empty())
      << "Give a snapshot to resume training or weights to finetune "
      "but not both.";

  // Construct the solver either from file or params
  caffe::SolverParameter solver_param;
  if (!FLAGS_solver.empty()) {
    LOG(INFO) << "Reading solver prototxt from " << FLAGS_solver;
    caffe::ReadProtoFromTextFileOrDie(FLAGS_solver, &solver_param);
  } else {
    LOG(INFO) << "Creating solver from scratch.";
    solver_param.set_net(FLAGS_model);
    ::caffe::SolverParameter_SolverType solver_type;
    CHECK(::caffe::SolverParameter_SolverType_Parse(FLAGS_solver_type, &solver_type))
        << "Invalid Solver Type " << FLAGS_solver_type;
    solver_param.set_solver_type(solver_type);
    solver_param.set_momentum(FLAGS_momentum);
    solver_param.set_base_lr(FLAGS_base_lr);
    solver_param.set_lr_policy(FLAGS_lr_policy);
    solver_param.set_gamma(FLAGS_solver_gamma);
    solver_param.set_stepsize(FLAGS_stepsize);
    solver_param.set_max_iter(FLAGS_max_iter);
    solver_param.set_display(FLAGS_display);
    solver_param.set_snapshot(FLAGS_snapshot_frequency);
    solver_param.set_snapshot_prefix(FLAGS_snapshot_prefix);
  }

  dqn::DQN dqn(legal_actions, solver_param, FLAGS_memory, FLAGS_gamma);
  dqn.Initialize();

  if (!FLAGS_save_screen.empty()) {
    LOG(INFO) << "Saving screens to: " << FLAGS_save_screen;
  }

  if (!FLAGS_snapshot.empty()) {
    LOG(INFO) << "Resuming from " << FLAGS_snapshot;
    dqn.RestoreSolver(FLAGS_snapshot);
  } else if (!FLAGS_weights.empty()) {
    LOG(INFO) << "Finetuning from " << FLAGS_weights;
    dqn.LoadTrainedModel(FLAGS_weights);
  }

  if (FLAGS_evaluate) {
    Evaluate(ale, dqn);
    return 0;
  }

  auto episode = 0;
  while (dqn.current_iteration() < solver_param.max_iter()) {
    const auto epsilon = CalculateEpsilon(dqn.current_iteration());
    const auto score = PlayOneEpisode(ale, dqn, epsilon, true);
    LOG(INFO) << "Episode " << episode << ", score = " << score
              << ", epsilon = " << epsilon << ", iter = "
              << dqn.current_iteration();
    episode++;
  }
  Evaluate(ale, dqn);
};
<commit_msg>Updated to reflect current ale.<commit_after>#include <cmath>
#include <iostream>
#include <ale_interface.hpp>
#include <glog/logging.h>
#include <gflags/gflags.h>
#include "prettyprint.hpp"
#include "dqn.hpp"

// DQN Parameters
DEFINE_bool(gpu, true, "Use GPU to brew Caffe");
DEFINE_bool(gui, false, "Open a GUI window");
DEFINE_string(rom, "roms/pong.bin", "Atari 2600 ROM to play");
DEFINE_int32(memory, 400000, "Capacity of replay memory");
DEFINE_int32(explore, 1000000, "Number of iterations needed for epsilon to reach given value.");
DEFINE_double(epsilon, 0.05, "Value of epsilon reached after explore iterations.");
DEFINE_double(gamma, 0.95, "Discount factor of future rewards (0,1]");
DEFINE_int32(memory_threshold, 100, "Enough amount of transitions to start learning");
DEFINE_int32(skip_frame, 3, "Number of frames skipped");
DEFINE_bool(show_frame, false, "Show the current frame in CUI");
DEFINE_string(save_screen, "", "File prefix in to save frames");
DEFINE_string(save_binary_screen, "", "File prefix in to save binary frames");
DEFINE_string(weights, "", "The pretrained weights load (*.caffemodel).");
DEFINE_string(snapshot, "", "The solver state to load (*.solverstate).");
DEFINE_bool(evaluate, false, "Evaluation mode: only playing a game, no updates");
DEFINE_double(evaluate_with_epsilon, 0.05, "Epsilon value to be used in evaluation mode");
DEFINE_double(repeat_games, 10, "Number of games played in evaluation mode");
// Solver Parameters
DEFINE_string(solver, "", "Solver parameter file (*.prototxt)");
DEFINE_string(solver_type, "ADADELTA", "Type of solver.");
DEFINE_string(model, "dqn.prototxt", "The model definition (*.prototxt).");
DEFINE_double(momentum, 0.95, "Solver momentum");
DEFINE_double(base_lr, 0.1, "Solver base learning rate");
DEFINE_string(lr_policy, "step", "Solver lr policy");
DEFINE_double(solver_gamma, 0.1, "Solver gamma");
DEFINE_int32(stepsize, 10000000, "Solver stepsize");
DEFINE_int32(max_iter, 10000000, "Maximum number of iterations");
DEFINE_int32(snapshot_frequency, 1000000, "Snapshot frequency in iterations");
DEFINE_int32(display, 10000, "Display frequency in iterations");
DEFINE_string(snapshot_prefix, "state/dqn", "Prefix for saving snapshots");

double CalculateEpsilon(const int iter) {
  if (iter < FLAGS_explore) {
    return 1.0 - (1.0 - FLAGS_epsilon) * (static_cast<double>(iter) / FLAGS_explore);
  } else {
    return FLAGS_epsilon;
  }
}

void SaveScreen(const ALEScreen& screen, const ALEInterface& ale,
                const string filename) {
  IntMatrix screen_matrix;
  for (auto row = 0; row < screen.height(); row++) {
    IntVect row_vec;
    for (auto col = 0; col < screen.width(); col++) {
      int pixel = screen.get(row, col);
      row_vec.emplace_back(pixel);
    }
    screen_matrix.emplace_back(row_vec);
  }
  // ale.theOSystem->p_export_screen->save_png(&screen_matrix, filename);
}

void SaveInputFrames(const dqn::InputFrames& frames, const string filename) {
  std::ofstream ofs;
  ofs.open(filename, ios::out | ios::binary);
  for (int i = 0; i < dqn::kInputFrameCount; ++i) {
    const dqn::FrameData& frame = *frames[i];
    for (int j = 0; j < dqn::kCroppedFrameDataSize; ++j) {
      ofs.write((char*) &frame[j], sizeof(uint8_t));
    }
  }
  ofs.close();
}

/**
 * Play one episode and return the total score
 */
double PlayOneEpisode(ALEInterface& ale, dqn::DQN& dqn, const double epsilon,
                      const bool update) {
  CHECK(!ale.game_over());
  std::deque<dqn::FrameDataSp> past_frames;
  auto total_score = 0.0;
  for (auto frame = 0; !ale.game_over(); ++frame) {
    const ALEScreen& screen = ale.getScreen();
    const auto current_frame = dqn::PreprocessScreen(screen);
    if (FLAGS_show_frame) {
      std::cout << dqn::DrawFrame(*current_frame) << std::endl;
    }
    if (!FLAGS_save_screen.empty()) {
      std::stringstream ss;
      ss << FLAGS_save_screen << setfill('0') << setw(5) <<
          std::to_string(frame) << ".png";
      SaveScreen(screen, ale, ss.str());
    }
    past_frames.push_back(current_frame);
    if (past_frames.size() < dqn::kInputFrameCount) {
      // If there are not past frames enough for DQN input, just select NOOP
      for (auto i = 0; i < FLAGS_skip_frame + 1 && !ale.game_over(); ++i) {
        total_score += ale.act(PLAYER_A_NOOP);
      }
    } else {
      while (past_frames.size() > dqn::kInputFrameCount) {
        past_frames.pop_front();
      }
      dqn::InputFrames input_frames;
      std::copy(past_frames.begin(), past_frames.end(), input_frames.begin());
      if (!FLAGS_save_binary_screen.empty()) {
        static int binary_save_num = 0;
        string fname = FLAGS_save_binary_screen +
            std::to_string(binary_save_num++) + ".bin";
        SaveInputFrames(input_frames, fname);
      }
      const auto action = dqn.SelectAction(input_frames, epsilon);
      auto immediate_score = 0.0;
      for (auto i = 0; i < FLAGS_skip_frame + 1 && !ale.game_over(); ++i) {
        // Last action is repeated on skipped frames
        immediate_score += ale.act(action);
      }
      total_score += immediate_score;
      // Rewards for DQN are normalized as follows:
      // 1 for any positive score, -1 for any negative score, otherwise 0
      const auto reward =
          immediate_score == 0 ?
              0 :
              immediate_score /= std::abs(immediate_score);
      if (update) {
        // Add the current transition to replay memory
        const auto transition = ale.game_over() ?
            dqn::Transition(input_frames, action, reward, boost::none) :
            dqn::Transition(
                input_frames,
                action,
                reward,
                dqn::PreprocessScreen(ale.getScreen()));
        dqn.AddTransition(transition);
        // If the size of replay memory is enough, update DQN
        if (dqn.memory_size() > FLAGS_memory_threshold) {
          dqn.Update();
        }
      }
    }
  }
  ale.reset_game();
  return total_score;
}

/**
 * Evaluate the current player
 */
void Evaluate(ALEInterface& ale, dqn::DQN& dqn) {
  auto total_score = 0.0;
  std::stringstream ss;
  for (auto i = 0; i < FLAGS_repeat_games; ++i) {
    const auto score =
        PlayOneEpisode(ale, dqn, FLAGS_evaluate_with_epsilon, false);
    ss << score << " ";
    total_score += score;
  }
  LOG(INFO) << "Evaluation scores: " << ss.str();
  LOG(INFO) << "Average score: " <<
      total_score / static_cast<double>(FLAGS_repeat_games) << std::endl;
}

int main(int argc, char** argv) {
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  google::InitGoogleLogging(argv[0]);
  google::InstallFailureSignalHandler();
  google::LogToStderr();

  if (FLAGS_gpu) {
    caffe::Caffe::set_mode(caffe::Caffe::GPU);
  } else {
    caffe::Caffe::set_mode(caffe::Caffe::CPU);
  }

  ALEInterface ale;
  ale.set("display_screen", FLAGS_gui);
  ale.set("disable_color_averaging", true);

  // Load the ROM file
  ale.loadROM(FLAGS_rom);

  // Get the vector of legal actions
  const auto legal_actions = ale.getMinimalActionSet();

  CHECK(FLAGS_snapshot.empty() || FLAGS_weights.empty())
      << "Give a snapshot to resume training or weights to finetune "
      "but not both.";

  // Construct the solver either from file or params
  caffe::SolverParameter solver_param;
  if (!FLAGS_solver.empty()) {
    LOG(INFO) << "Reading solver prototxt from " << FLAGS_solver;
    caffe::ReadProtoFromTextFileOrDie(FLAGS_solver, &solver_param);
  } else {
    LOG(INFO) << "Creating solver from scratch.";
    solver_param.set_net(FLAGS_model);
    ::caffe::SolverParameter_SolverType solver_type;
    CHECK(::caffe::SolverParameter_SolverType_Parse(FLAGS_solver_type, &solver_type))
        << "Invalid Solver Type " << FLAGS_solver_type;
    solver_param.set_solver_type(solver_type);
    solver_param.set_momentum(FLAGS_momentum);
    solver_param.set_base_lr(FLAGS_base_lr);
    solver_param.set_lr_policy(FLAGS_lr_policy);
    solver_param.set_gamma(FLAGS_solver_gamma);
    solver_param.set_stepsize(FLAGS_stepsize);
    solver_param.set_max_iter(FLAGS_max_iter);
    solver_param.set_display(FLAGS_display);
    solver_param.set_snapshot(FLAGS_snapshot_frequency);
    solver_param.set_snapshot_prefix(FLAGS_snapshot_prefix);
  }

  dqn::DQN dqn(legal_actions, solver_param, FLAGS_memory, FLAGS_gamma);
  dqn.Initialize();

  if (!FLAGS_save_screen.empty()) {
    LOG(INFO) << "Saving screens to: " << FLAGS_save_screen;
  }

  if (!FLAGS_snapshot.empty()) {
    LOG(INFO) << "Resuming from " << FLAGS_snapshot;
    dqn.RestoreSolver(FLAGS_snapshot);
  } else if (!FLAGS_weights.empty()) {
    LOG(INFO) << "Finetuning from " << FLAGS_weights;
    dqn.LoadTrainedModel(FLAGS_weights);
  }

  if (FLAGS_evaluate) {
    Evaluate(ale, dqn);
    return 0;
  }

  auto episode = 0;
  while (dqn.current_iteration() < solver_param.max_iter()) {
    const auto epsilon = CalculateEpsilon(dqn.current_iteration());
    const auto score = PlayOneEpisode(ale, dqn, epsilon, true);
    LOG(INFO) << "Episode " << episode << ", score = " << score
              << ", epsilon = " << epsilon << ", iter = "
              << dqn.current_iteration();
    episode++;
  }
  Evaluate(ale, dqn);
};
<|endoftext|>


<commit_before>#include "Precompiled.hpp"
#include "MarketOrdersCache.hpp"
#include "Error.hpp"
#include "model/EveRegions.hpp"
#include <thread>
#include <boost/filesystem.hpp>
namespace crest
{
    namespace
    {
        namespace fs = boost::filesystem;
        const auto EMPTY_ORDERS = std::make_shared<const MarketOrdersSlim>();
        static const int MAX_UPDATES_IN_PROGRESS = 50;
        const std::string CACHE_DIR = "cache/market_orders/";

        void delete_dir_contents(const std::string &dir)
        {
            fs::path path(dir);
            if (fs::exists(path))
            {
                for (fs::directory_iterator i(path), end; i != end; ++i)
                {
                    fs::remove_all(i->path());
                }
            }
        }
        std::string get_region_cache_path(int region_id)
        {
            return CACHE_DIR + std::to_string(region_id);
        }
    }

    std::unordered_map<int, MarketOrdersCache::Region> MarketOrdersCache::create_regions_map()
    {
        std::unordered_map<int, Region> ret;
        for (auto id : EVE_REGION_IDS)
        {
            ret.emplace(id, id);
        }
        return ret;
    }
    MarketOrdersCache::MarketOrdersCache(GetOrdersFunc get_region_orders)
        : get_region_orders(get_region_orders), regions(create_regions_map())
        , update_thread(), update_thread_exit(false), update_thread_exit_cv(), update_thread_exit_cv_mutex()
    {
        delete_dir_contents(CACHE_DIR);
        update_thread = std::thread(std::bind(&MarketOrdersCache::update_thread_main, this));
    }

    MarketOrdersCache::~MarketOrdersCache()
    {
        exit();
    }

    void MarketOrdersCache::exit()
    {
        if (update_thread.joinable())
        {
            update_thread_exit = true;
            update_thread_exit_cv.notify_all();
            update_thread.join();
        }
    }

    std::shared_ptr<const MarketOrdersSlim> MarketOrdersCache::get_orders(int region_id, int type_id, bool buy)
    {
        //Get cache entry, and create a blank placeholder if needed
        auto it = regions.find(region_id);
        if (it == regions.end()) throw std::runtime_error("Unknown region " + std::to_string(region_id));
        auto &region = it->second;

        std::unique_lock<std::mutex> lock(region.access_mutex);
        //Find entry
        auto id = type_id;
        if (buy) id = -id;
        auto entry = std::lower_bound(
            region.entries.begin(),
            region.entries.end(),
            id,
            [](const Region::Entry &entry, int id) { return entry.id < id; });
        if (entry == region.entries.end() || entry->id != id)
            return EMPTY_ORDERS;
        //Read cache
        auto bytes = entry->count * sizeof(MarketOrderSlim);
        region.fs.seekg(entry->start_byte);
        auto data = std::make_shared<MarketOrdersSlim>();
        data->resize(entry->count);
        region.fs.read((char*)data->data(), bytes);
        if (region.fs.gcount() != bytes) throw std::runtime_error("Failed to read cache file");
        //Done
        return data;
    }

    void MarketOrdersCache::update_thread_main()
    {
        set_thread_name("MarketOrdersCache update");
        auto update_next = regions.begin();
        while (true)
        {
            if (update_next == regions.end()) update_next = regions.begin();
            auto &region = update_next->second;

            auto now = time(nullptr);
            if (now < region.expires)
            {
                log_debug() << "Waiting " << (region.expires - now) << " seconds until next region update" << std::endl;
                std::this_thread::sleep_until(std::chrono::system_clock::from_time_t(region.expires));
                assert(time(nullptr) >= region.expires);
            }

            update_region(region);

            ++update_next;
        }
    }

    void MarketOrdersCache::update_region(Region &region)
    {
        assert(region.expires <= time(nullptr));
        //Get updated data
        try
        {
            std::unordered_map<int, std::vector<MarketOrderSlim>> files;
            get_region_orders(region.region_id, [&files](const MarketOrderSlim &order) -> void
            {
                int id = order.type;
                if (order.buy) id = -id;

                auto &file = files[id];
                file.push_back(order);
            });

            //Got all data ready, just hold lock while updating Region and the filesystem
            std::unique_lock<std::mutex> lock(region.access_mutex);
            region.entries.clear();
            region.entries.reserve(files.size());

            auto path = get_region_cache_path(region.region_id);
            fs::create_directories(CACHE_DIR);
            region.fs.close();
            region.fs.open(path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
            if (!region.fs.good()) throw std::runtime_error("Failed to open cache file");
            for (auto &type : files)
            {
                Region::Entry entry = {
                    type.first,
                    (unsigned)region.fs.tellp(),
                    (unsigned)type.second.size()
                };
                region.entries.push_back(entry);
                region.fs.write((const char*)type.second.data(), sizeof(MarketOrderSlim)*type.second.size());
            }
            std::sort(region.entries.begin(), region.entries.end());
            if (!region.fs.good()) throw std::runtime_error("Failed to write cache file");

            region.expires = time(nullptr) + 300;
        }
        catch (const std::exception &e)
        {
            log_error() << "Failed to update orders cache for " << region.region_id << ": " << e.what() << std::endl;
        }
    }
}
<commit_msg>Fixed GCC 4.8 build<commit_after>#include "Precompiled.hpp"
#include "MarketOrdersCache.hpp"
#include "Error.hpp"
#include "model/EveRegions.hpp"
#include <thread>
#include <boost/filesystem.hpp>
namespace crest
{
    namespace
    {
        namespace fs = boost::filesystem;
        const auto EMPTY_ORDERS = std::make_shared<const MarketOrdersSlim>();
        static const int MAX_UPDATES_IN_PROGRESS = 50;
        const std::string CACHE_DIR = "cache/market_orders/";

        void delete_dir_contents(const std::string &dir)
        {
            fs::path path(dir);
            if (fs::exists(path))
            {
                for (fs::directory_iterator i(path), end; i != end; ++i)
                {
                    fs::remove_all(i->path());
                }
            }
        }
        std::string get_region_cache_path(int region_id)
        {
            return CACHE_DIR + std::to_string(region_id);
        }
    }

    std::unordered_map<int, MarketOrdersCache::Region> MarketOrdersCache::create_regions_map()
    {
        std::unordered_map<int, Region> ret;
        for (auto id : EVE_REGION_IDS)
        {
            ret.emplace(std::piecewise_construct, std::make_tuple(id), std::make_tuple(id));
        }
        return ret;
    }
    MarketOrdersCache::MarketOrdersCache(GetOrdersFunc get_region_orders)
        : get_region_orders(get_region_orders), regions(create_regions_map())
        , update_thread(), update_thread_exit(false), update_thread_exit_cv(), update_thread_exit_cv_mutex()
    {
        delete_dir_contents(CACHE_DIR);
        update_thread = std::thread(std::bind(&MarketOrdersCache::update_thread_main, this));
    }

    MarketOrdersCache::~MarketOrdersCache()
    {
        exit();
    }

    void MarketOrdersCache::exit()
    {
        if (update_thread.joinable())
        {
            update_thread_exit = true;
            update_thread_exit_cv.notify_all();
            update_thread.join();
        }
    }

    std::shared_ptr<const MarketOrdersSlim> MarketOrdersCache::get_orders(int region_id, int type_id, bool buy)
    {
        //Get cache entry, and create a blank placeholder if needed
        auto it = regions.find(region_id);
        if (it == regions.end()) throw std::runtime_error("Unknown region " + std::to_string(region_id));
        auto &region = it->second;

        std::unique_lock<std::mutex> lock(region.access_mutex);
        //Find entry
        auto id = type_id;
        if (buy) id = -id;
        auto entry = std::lower_bound(
            region.entries.begin(),
            region.entries.end(),
            id,
            [](const Region::Entry &entry, int id) { return entry.id < id; });
        if (entry == region.entries.end() || entry->id != id)
            return EMPTY_ORDERS;
        //Read cache
        auto bytes = entry->count * sizeof(MarketOrderSlim);
        region.fs.seekg(entry->start_byte);
        auto data = std::make_shared<MarketOrdersSlim>();
        data->resize(entry->count);
        region.fs.read((char*)data->data(), bytes);
        if (region.fs.gcount() != bytes) throw std::runtime_error("Failed to read cache file");
        //Done
        return data;
    }

    void MarketOrdersCache::update_thread_main()
    {
        set_thread_name("MarketOrdersCache update");
        auto update_next = regions.begin();
        while (true)
        {
            if (update_next == regions.end()) update_next = regions.begin();
            auto &region = update_next->second;

            auto now = time(nullptr);
            if (now < region.expires)
            {
                log_debug() << "Waiting " << (region.expires - now) << " seconds until next region update" << std::endl;
                std::this_thread::sleep_until(std::chrono::system_clock::from_time_t(region.expires));
                assert(time(nullptr) >= region.expires);
            }

            update_region(region);

            ++update_next;
        }
    }

    void MarketOrdersCache::update_region(Region &region)
    {
        assert(region.expires <= time(nullptr));
        //Get updated data
        try
        {
            std::unordered_map<int, std::vector<MarketOrderSlim>> files;
            get_region_orders(region.region_id, [&files](const MarketOrderSlim &order) -> void
            {
                int id = order.type;
                if (order.buy) id = -id;

                auto &file = files[id];
                file.push_back(order);
            });

            //Got all data ready, just hold lock while updating Region and the filesystem
            std::unique_lock<std::mutex> lock(region.access_mutex);
            region.entries.clear();
            region.entries.reserve(files.size());

            auto path = get_region_cache_path(region.region_id);
            fs::create_directories(CACHE_DIR);
            region.fs.close();
            region.fs.open(path, std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary);
            if (!region.fs.good()) throw std::runtime_error("Failed to open cache file");
            for (auto &type : files)
            {
                Region::Entry entry = {
                    type.first,
                    (unsigned)region.fs.tellp(),
                    (unsigned)type.second.size()
                };
                region.entries.push_back(entry);
                region.fs.write((const char*)type.second.data(), sizeof(MarketOrderSlim)*type.second.size());
            }
            std::sort(region.entries.begin(), region.entries.end());
            if (!region.fs.good()) throw std::runtime_error("Failed to write cache file");

            region.expires = time(nullptr) + 300;
        }
        catch (const std::exception &e)
        {
            log_error() << "Failed to update orders cache for " << region.region_id << ": " << e.what() << std::endl;
        }
    }
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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.

*/

#ifndef TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <list>

namespace libtorrent
{

	bool is_local(address const& a);
	bool is_loopback(address const& addr);
	bool is_multicast(address const& addr);
	bool is_any(address const& addr);

	address guess_local_address(asio::io_service&);

	typedef boost::function<void(udp::endpoint const& from
		, char* buffer, int size)> receive_handler_t;

	class broadcast_socket
	{
	public:
		broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint
			, receive_handler_t const& handler, bool loopback = true);
		~broadcast_socket() { close(); }

		void send(char const* buffer, int size, asio::error_code& ec);
		void close();

	private:

		struct socket_entry
		{
			socket_entry(boost::shared_ptr<datagram_socket> const& s): socket(s) {}
			boost::shared_ptr<datagram_socket> socket;
			char buffer[1024];
			udp::endpoint remote;
			void close() { socket->close(); }
		};

		void on_receive(socket_entry* s, asio::error_code const& ec
			, std::size_t bytes_transferred);
		void open_unicast_socket(io_service& ios, address const& addr);

		// these sockets are used to
		// join the multicast group (on each interface)
		// and receive multicast messages
		std::list<socket_entry> m_sockets;
		// these sockets are not bound to any
		// specific port and are used to
		// send messages to the multicast group
		// and receive unicast responses
		std::list<socket_entry> m_unicast_sockets;
		udp::endpoint m_multicast_endpoint;
		receive_handler_t m_on_receive;

	};
}

#endif

<commit_msg>support in broadcast_socket to be built without exception support<commit_after>/*

Copyright (c) 2007, Arvid Norberg
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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.

*/

#ifndef TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED

#include "libtorrent/socket.hpp"
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <list>

namespace libtorrent
{

	bool is_local(address const& a);
	bool is_loopback(address const& addr);
	bool is_multicast(address const& addr);
	bool is_any(address const& addr);

	address guess_local_address(asio::io_service&);

	typedef boost::function<void(udp::endpoint const& from
		, char* buffer, int size)> receive_handler_t;

	class broadcast_socket
	{
	public:
		broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint
			, receive_handler_t const& handler, bool loopback = true);
		~broadcast_socket() { close(); }

		void send(char const* buffer, int size, asio::error_code& ec);
		void close();

	private:

		struct socket_entry
		{
			socket_entry(boost::shared_ptr<datagram_socket> const& s): socket(s) {}
			boost::shared_ptr<datagram_socket> socket;
			char buffer[1024];
			udp::endpoint remote;
			void close()
			{
				asio::error_code ec;
				socket->close(ec);
			}
		};

		void on_receive(socket_entry* s, asio::error_code const& ec
			, std::size_t bytes_transferred);
		void open_unicast_socket(io_service& ios, address const& addr);

		// these sockets are used to
		// join the multicast group (on each interface)
		// and receive multicast messages
		std::list<socket_entry> m_sockets;
		// these sockets are not bound to any
		// specific port and are used to
		// send messages to the multicast group
		// and receive unicast responses
		std::list<socket_entry> m_unicast_sockets;
		udp::endpoint m_multicast_endpoint;
		receive_handler_t m_on_receive;

	};
}

#endif

<|endoftext|>