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

#include <chrono>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
#include <vector>

#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>

#include "src/core/lib/profiling/timers.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/cpp/qps/client.h"
#include "test/cpp/qps/interarrival.h"
#include "test/cpp/qps/usage_timer.h"

namespace grpc {
namespace testing {

static std::unique_ptr<BenchmarkService::Stub> BenchmarkStubCreator(
    std::shared_ptr<Channel> ch) {
  return BenchmarkService::NewStub(ch);
}

class SynchronousClient
    : public ClientImpl<BenchmarkService::Stub, SimpleRequest> {
 public:
  SynchronousClient(const ClientConfig& config)
      : ClientImpl<BenchmarkService::Stub, SimpleRequest>(
            config, BenchmarkStubCreator) {
    num_threads_ =
        config.outstanding_rpcs_per_channel() * config.client_channels();
    responses_.resize(num_threads_);
    SetupLoadTest(config, num_threads_);
  }

  virtual ~SynchronousClient(){};

  virtual bool InitThreadFuncImpl(size_t thread_idx) = 0;
  virtual bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) = 0;

  void ThreadFunc(size_t thread_idx, Thread* t) override {
    if (!InitThreadFuncImpl(thread_idx)) {
      return;
    }
    for (;;) {
      // run the loop body
      HistogramEntry entry;
      const bool thread_still_ok = ThreadFuncImpl(&entry, thread_idx);
      t->UpdateHistogram(&entry);
      if (!thread_still_ok) {
        gpr_log(GPR_ERROR, "Finishing client thread due to RPC error");
      }
      if (!thread_still_ok || ThreadCompleted()) {
        return;
      }
    }
  }

 protected:
  // WaitToIssue returns false if we realize that we need to break out
  bool WaitToIssue(int thread_idx) {
    if (!closed_loop_) {
      const gpr_timespec next_issue_time = NextIssueTime(thread_idx);
      // Avoid sleeping for too long continuously because we might
      // need to terminate before then. This is an issue since
      // exponential distribution can occasionally produce bad outliers
      while (true) {
        const gpr_timespec one_sec_delay =
            gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                         gpr_time_from_seconds(1, GPR_TIMESPAN));
        if (gpr_time_cmp(next_issue_time, one_sec_delay) <= 0) {
          gpr_sleep_until(next_issue_time);
          return true;
        } else {
          gpr_sleep_until(one_sec_delay);
          if (gpr_atm_acq_load(&thread_pool_done_) != static_cast<gpr_atm>(0)) {
            return false;
          }
        }
      }
    }
    return true;
  }

  size_t num_threads_;
  std::vector<SimpleResponse> responses_;
};

class SynchronousUnaryClient final : public SynchronousClient {
 public:
  SynchronousUnaryClient(const ClientConfig& config)
      : SynchronousClient(config) {
    StartThreads(num_threads_);
  }
  ~SynchronousUnaryClient() {}

  bool InitThreadFuncImpl(size_t thread_idx) override { return true; }

  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    if (!WaitToIssue(thread_idx)) {
      return true;
    }
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    double start = UsageTimer::Now();
    GPR_TIMER_SCOPE("SynchronousUnaryClient::ThreadFunc", 0);
    grpc::ClientContext context;
    grpc::Status s =
        stub->UnaryCall(&context, request_, &responses_[thread_idx]);
    if (s.ok()) {
      entry->set_value((UsageTimer::Now() - start) * 1e9);
    }
    entry->set_status(s.error_code());
    return true;
  }

 private:
  void DestroyMultithreading() override final { EndThreads(); }
};

template <class StreamType>
class SynchronousStreamingClient : public SynchronousClient {
 public:
  SynchronousStreamingClient(const ClientConfig& config)
      : SynchronousClient(config),
        context_(num_threads_),
        stream_(num_threads_),
        stream_mu_(num_threads_),
        shutdown_(num_threads_),
        messages_per_stream_(config.messages_per_stream()),
        messages_issued_(num_threads_) {
    StartThreads(num_threads_);
  }
  virtual ~SynchronousStreamingClient() {
    OnAllStreams([](ClientContext* ctx, StreamType* s) -> bool {
      // don't log any kind of error since we might have canceled it
      s->Finish().IgnoreError();
      return true;
    });
  }

 protected:
  std::vector<grpc::ClientContext> context_;
  std::vector<std::unique_ptr<StreamType>> stream_;
  // stream_mu_ is only needed when changing an element of stream_ or context_
  std::vector<std::mutex> stream_mu_;
  struct Bool {
    bool val;
    Bool() : val(false) {}
  };
  std::vector<Bool> shutdown_;
  const int messages_per_stream_;
  std::vector<int> messages_issued_;

  void FinishStream(HistogramEntry* entry, size_t thread_idx) {
    Status s = stream_[thread_idx]->Finish();
    // don't set the value since the stream is failed and shouldn't be timed
    entry->set_status(s.error_code());
    if (!s.ok()) {
      gpr_log(GPR_ERROR, "Stream %" PRIuPTR " received an error %s", thread_idx,
              s.error_message().c_str());
    }
    // Lock the stream_mu_ now because the client context could change
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    context_[thread_idx].~ClientContext();
    new (&context_[thread_idx]) ClientContext();
  }
  void OnAllStreams(std::function<bool(ClientContext*, StreamType*)> cleaner) {
    std::vector<std::thread> cleanup_threads;
    for (size_t i = 0; i < num_threads_; i++) {
      cleanup_threads.emplace_back([this, i, cleaner]() {
        std::lock_guard<std::mutex> l(stream_mu_[i]);
        if (stream_[i]) {
          shutdown_[i].val = cleaner(&context_[i], stream_[i].get());
        }
      });
    }
    for (auto& th : cleanup_threads) {
      th.join();
    }
  }

 private:
  void DestroyMultithreading() override final {
    OnAllStreams([](ClientContext* ctx, StreamType* s) -> bool {
      ctx->TryCancel();
      return true;
    });
    EndThreads();
  }
};

class SynchronousStreamingPingPongClient final
    : public SynchronousStreamingClient<
          grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>> {
 public:
  SynchronousStreamingPingPongClient(const ClientConfig& config)
      : SynchronousStreamingClient(config) {}
  ~SynchronousStreamingPingPongClient() {
    OnAllStreams(
        [](ClientContext* ctx,
           grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>* s) -> bool {
          s->WritesDone();
          return true;
        });
  }

  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
    } else {
      return false;
    }
    messages_issued_[thread_idx] = 0;
    return true;
  }

  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    if (!WaitToIssue(thread_idx)) {
      return true;
    }
    GPR_TIMER_SCOPE("SynchronousStreamingPingPongClient::ThreadFunc", 0);
    double start = UsageTimer::Now();
    if (stream_[thread_idx]->Write(request_) &&
        stream_[thread_idx]->Read(&responses_[thread_idx])) {
      entry->set_value((UsageTimer::Now() - start) * 1e9);
      // don't set the status since there isn't one yet
      if ((messages_per_stream_ != 0) &&
          (++messages_issued_[thread_idx] < messages_per_stream_)) {
        return true;
      } else if (messages_per_stream_ == 0) {
        return true;
      } else {
        // Fall through to the below resetting code after finish
      }
    }
    stream_[thread_idx]->WritesDone();
    FinishStream(entry, thread_idx);
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
    } else {
      stream_[thread_idx].reset();
      return false;
    }
    messages_issued_[thread_idx] = 0;
    return true;
  }
};

class SynchronousStreamingFromClientClient final
    : public SynchronousStreamingClient<grpc::ClientWriter<SimpleRequest>> {
 public:
  SynchronousStreamingFromClientClient(const ClientConfig& config)
      : SynchronousStreamingClient(config), last_issue_(num_threads_) {}
  ~SynchronousStreamingFromClientClient() {
    OnAllStreams(
        [](ClientContext* ctx, grpc::ClientWriter<SimpleRequest>* s) -> bool {
          s->WritesDone();
          return true;
        });
  }

  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingFromClient(&context_[thread_idx],
                                                      &responses_[thread_idx]);
    } else {
      return false;
    }
    last_issue_[thread_idx] = UsageTimer::Now();
    return true;
  }

  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    // Figure out how to make histogram sensible if this is rate-paced
    if (!WaitToIssue(thread_idx)) {
      return true;
    }
    GPR_TIMER_SCOPE("SynchronousStreamingFromClientClient::ThreadFunc", 0);
    if (stream_[thread_idx]->Write(request_)) {
      double now = UsageTimer::Now();
      entry->set_value((now - last_issue_[thread_idx]) * 1e9);
      last_issue_[thread_idx] = now;
      return true;
    }
    stream_[thread_idx]->WritesDone();
    FinishStream(entry, thread_idx);
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingFromClient(&context_[thread_idx],
                                                      &responses_[thread_idx]);
    } else {
      stream_[thread_idx].reset();
      return false;
    }
    return true;
  }

 private:
  std::vector<double> last_issue_;
};

class SynchronousStreamingFromServerClient final
    : public SynchronousStreamingClient<grpc::ClientReader<SimpleResponse>> {
 public:
  SynchronousStreamingFromServerClient(const ClientConfig& config)
      : SynchronousStreamingClient(config), last_recv_(num_threads_) {}
  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] =
          stub->StreamingFromServer(&context_[thread_idx], request_);
    } else {
      return false;
    }
    last_recv_[thread_idx] = UsageTimer::Now();
    return true;
  }
  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    GPR_TIMER_SCOPE("SynchronousStreamingFromServerClient::ThreadFunc", 0);
    if (stream_[thread_idx]->Read(&responses_[thread_idx])) {
      double now = UsageTimer::Now();
      entry->set_value((now - last_recv_[thread_idx]) * 1e9);
      last_recv_[thread_idx] = now;
      return true;
    }
    FinishStream(entry, thread_idx);
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] =
          stub->StreamingFromServer(&context_[thread_idx], request_);
    } else {
      stream_[thread_idx].reset();
      return false;
    }
    return true;
  }

 private:
  std::vector<double> last_recv_;
};

class SynchronousStreamingBothWaysClient final
    : public SynchronousStreamingClient<
          grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>> {
 public:
  SynchronousStreamingBothWaysClient(const ClientConfig& config)
      : SynchronousStreamingClient(config) {}
  ~SynchronousStreamingBothWaysClient() {
    OnAllStreams(
        [](ClientContext* ctx,
           grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>* s) -> bool {
          s->WritesDone();
          return true;
        });
  }

  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingBothWays(&context_[thread_idx]);
    } else {
      return false;
    }
    return true;
  }
  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    // TODO (vjpai): Do this
    return true;
  }
};

std::unique_ptr<Client> CreateSynchronousClient(const ClientConfig& config) {
  switch (config.rpc_type()) {
    case UNARY:
      return std::unique_ptr<Client>(new SynchronousUnaryClient(config));
    case STREAMING:
      return std::unique_ptr<Client>(
          new SynchronousStreamingPingPongClient(config));
    case STREAMING_FROM_CLIENT:
      return std::unique_ptr<Client>(
          new SynchronousStreamingFromClientClient(config));
    case STREAMING_FROM_SERVER:
      return std::unique_ptr<Client>(
          new SynchronousStreamingFromServerClient(config));
    case STREAMING_BOTH_WAYS:
      return std::unique_ptr<Client>(
          new SynchronousStreamingBothWaysClient(config));
    default:
      assert(false);
      return nullptr;
  }
}

}  // namespace testing
}  // namespace grpc
<commit_msg>Remove some unneeded and spammy logs<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <chrono>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <thread>
#include <vector>

#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
#include <grpc/support/time.h>

#include "src/core/lib/profiling/timers.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/cpp/qps/client.h"
#include "test/cpp/qps/interarrival.h"
#include "test/cpp/qps/usage_timer.h"

namespace grpc {
namespace testing {

static std::unique_ptr<BenchmarkService::Stub> BenchmarkStubCreator(
    std::shared_ptr<Channel> ch) {
  return BenchmarkService::NewStub(ch);
}

class SynchronousClient
    : public ClientImpl<BenchmarkService::Stub, SimpleRequest> {
 public:
  SynchronousClient(const ClientConfig& config)
      : ClientImpl<BenchmarkService::Stub, SimpleRequest>(
            config, BenchmarkStubCreator) {
    num_threads_ =
        config.outstanding_rpcs_per_channel() * config.client_channels();
    responses_.resize(num_threads_);
    SetupLoadTest(config, num_threads_);
  }

  virtual ~SynchronousClient(){};

  virtual bool InitThreadFuncImpl(size_t thread_idx) = 0;
  virtual bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) = 0;

  void ThreadFunc(size_t thread_idx, Thread* t) override {
    if (!InitThreadFuncImpl(thread_idx)) {
      return;
    }
    for (;;) {
      // run the loop body
      HistogramEntry entry;
      const bool thread_still_ok = ThreadFuncImpl(&entry, thread_idx);
      t->UpdateHistogram(&entry);
      if (!thread_still_ok || ThreadCompleted()) {
        return;
      }
    }
  }

 protected:
  // WaitToIssue returns false if we realize that we need to break out
  bool WaitToIssue(int thread_idx) {
    if (!closed_loop_) {
      const gpr_timespec next_issue_time = NextIssueTime(thread_idx);
      // Avoid sleeping for too long continuously because we might
      // need to terminate before then. This is an issue since
      // exponential distribution can occasionally produce bad outliers
      while (true) {
        const gpr_timespec one_sec_delay =
            gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
                         gpr_time_from_seconds(1, GPR_TIMESPAN));
        if (gpr_time_cmp(next_issue_time, one_sec_delay) <= 0) {
          gpr_sleep_until(next_issue_time);
          return true;
        } else {
          gpr_sleep_until(one_sec_delay);
          if (gpr_atm_acq_load(&thread_pool_done_) != static_cast<gpr_atm>(0)) {
            return false;
          }
        }
      }
    }
    return true;
  }

  size_t num_threads_;
  std::vector<SimpleResponse> responses_;
};

class SynchronousUnaryClient final : public SynchronousClient {
 public:
  SynchronousUnaryClient(const ClientConfig& config)
      : SynchronousClient(config) {
    StartThreads(num_threads_);
  }
  ~SynchronousUnaryClient() {}

  bool InitThreadFuncImpl(size_t thread_idx) override { return true; }

  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    if (!WaitToIssue(thread_idx)) {
      return true;
    }
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    double start = UsageTimer::Now();
    GPR_TIMER_SCOPE("SynchronousUnaryClient::ThreadFunc", 0);
    grpc::ClientContext context;
    grpc::Status s =
        stub->UnaryCall(&context, request_, &responses_[thread_idx]);
    if (s.ok()) {
      entry->set_value((UsageTimer::Now() - start) * 1e9);
    }
    entry->set_status(s.error_code());
    return true;
  }

 private:
  void DestroyMultithreading() override final { EndThreads(); }
};

template <class StreamType>
class SynchronousStreamingClient : public SynchronousClient {
 public:
  SynchronousStreamingClient(const ClientConfig& config)
      : SynchronousClient(config),
        context_(num_threads_),
        stream_(num_threads_),
        stream_mu_(num_threads_),
        shutdown_(num_threads_),
        messages_per_stream_(config.messages_per_stream()),
        messages_issued_(num_threads_) {
    StartThreads(num_threads_);
  }
  virtual ~SynchronousStreamingClient() {
    OnAllStreams([](ClientContext* ctx, StreamType* s) -> bool {
      // don't log any kind of error since we might have canceled it
      s->Finish().IgnoreError();
      return true;
    });
  }

 protected:
  std::vector<grpc::ClientContext> context_;
  std::vector<std::unique_ptr<StreamType>> stream_;
  // stream_mu_ is only needed when changing an element of stream_ or context_
  std::vector<std::mutex> stream_mu_;
  // use struct Bool rather than bool because vector<bool> is not concurrent
  struct Bool {
    bool val;
    Bool() : val(false) {}
  };
  std::vector<Bool> shutdown_;
  const int messages_per_stream_;
  std::vector<int> messages_issued_;

  void FinishStream(HistogramEntry* entry, size_t thread_idx) {
    Status s = stream_[thread_idx]->Finish();
    // don't set the value since the stream is failed and shouldn't be timed
    entry->set_status(s.error_code());
    if (!s.ok()) {
      std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
      if (!shutdown_[thread_idx].val) {
        gpr_log(GPR_ERROR, "Stream %" PRIuPTR " received an error %s",
                thread_idx, s.error_message().c_str());
      }
    }
    // Lock the stream_mu_ now because the client context could change
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    context_[thread_idx].~ClientContext();
    new (&context_[thread_idx]) ClientContext();
  }
  void OnAllStreams(std::function<bool(ClientContext*, StreamType*)> cleaner) {
    std::vector<std::thread> cleanup_threads;
    for (size_t i = 0; i < num_threads_; i++) {
      cleanup_threads.emplace_back([this, i, cleaner]() {
        std::lock_guard<std::mutex> l(stream_mu_[i]);
        if (stream_[i]) {
          shutdown_[i].val = cleaner(&context_[i], stream_[i].get());
        }
      });
    }
    for (auto& th : cleanup_threads) {
      th.join();
    }
  }

 private:
  void DestroyMultithreading() override final {
    OnAllStreams([](ClientContext* ctx, StreamType* s) -> bool {
      ctx->TryCancel();
      return true;
    });
    EndThreads();
  }
};

class SynchronousStreamingPingPongClient final
    : public SynchronousStreamingClient<
          grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>> {
 public:
  SynchronousStreamingPingPongClient(const ClientConfig& config)
      : SynchronousStreamingClient(config) {}
  ~SynchronousStreamingPingPongClient() {
    OnAllStreams(
        [](ClientContext* ctx,
           grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>* s) -> bool {
          s->WritesDone();
          return true;
        });
  }

  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
    } else {
      return false;
    }
    messages_issued_[thread_idx] = 0;
    return true;
  }

  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    if (!WaitToIssue(thread_idx)) {
      return true;
    }
    GPR_TIMER_SCOPE("SynchronousStreamingPingPongClient::ThreadFunc", 0);
    double start = UsageTimer::Now();
    if (stream_[thread_idx]->Write(request_) &&
        stream_[thread_idx]->Read(&responses_[thread_idx])) {
      entry->set_value((UsageTimer::Now() - start) * 1e9);
      // don't set the status since there isn't one yet
      if ((messages_per_stream_ != 0) &&
          (++messages_issued_[thread_idx] < messages_per_stream_)) {
        return true;
      } else if (messages_per_stream_ == 0) {
        return true;
      } else {
        // Fall through to the below resetting code after finish
      }
    }
    stream_[thread_idx]->WritesDone();
    FinishStream(entry, thread_idx);
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingCall(&context_[thread_idx]);
    } else {
      stream_[thread_idx].reset();
      return false;
    }
    messages_issued_[thread_idx] = 0;
    return true;
  }
};

class SynchronousStreamingFromClientClient final
    : public SynchronousStreamingClient<grpc::ClientWriter<SimpleRequest>> {
 public:
  SynchronousStreamingFromClientClient(const ClientConfig& config)
      : SynchronousStreamingClient(config), last_issue_(num_threads_) {}
  ~SynchronousStreamingFromClientClient() {
    OnAllStreams(
        [](ClientContext* ctx, grpc::ClientWriter<SimpleRequest>* s) -> bool {
          s->WritesDone();
          return true;
        });
  }

  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingFromClient(&context_[thread_idx],
                                                      &responses_[thread_idx]);
    } else {
      return false;
    }
    last_issue_[thread_idx] = UsageTimer::Now();
    return true;
  }

  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    // Figure out how to make histogram sensible if this is rate-paced
    if (!WaitToIssue(thread_idx)) {
      return true;
    }
    GPR_TIMER_SCOPE("SynchronousStreamingFromClientClient::ThreadFunc", 0);
    if (stream_[thread_idx]->Write(request_)) {
      double now = UsageTimer::Now();
      entry->set_value((now - last_issue_[thread_idx]) * 1e9);
      last_issue_[thread_idx] = now;
      return true;
    }
    stream_[thread_idx]->WritesDone();
    FinishStream(entry, thread_idx);
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingFromClient(&context_[thread_idx],
                                                      &responses_[thread_idx]);
    } else {
      stream_[thread_idx].reset();
      return false;
    }
    return true;
  }

 private:
  std::vector<double> last_issue_;
};

class SynchronousStreamingFromServerClient final
    : public SynchronousStreamingClient<grpc::ClientReader<SimpleResponse>> {
 public:
  SynchronousStreamingFromServerClient(const ClientConfig& config)
      : SynchronousStreamingClient(config), last_recv_(num_threads_) {}
  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] =
          stub->StreamingFromServer(&context_[thread_idx], request_);
    } else {
      return false;
    }
    last_recv_[thread_idx] = UsageTimer::Now();
    return true;
  }
  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    GPR_TIMER_SCOPE("SynchronousStreamingFromServerClient::ThreadFunc", 0);
    if (stream_[thread_idx]->Read(&responses_[thread_idx])) {
      double now = UsageTimer::Now();
      entry->set_value((now - last_recv_[thread_idx]) * 1e9);
      last_recv_[thread_idx] = now;
      return true;
    }
    FinishStream(entry, thread_idx);
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] =
          stub->StreamingFromServer(&context_[thread_idx], request_);
    } else {
      stream_[thread_idx].reset();
      return false;
    }
    return true;
  }

 private:
  std::vector<double> last_recv_;
};

class SynchronousStreamingBothWaysClient final
    : public SynchronousStreamingClient<
          grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>> {
 public:
  SynchronousStreamingBothWaysClient(const ClientConfig& config)
      : SynchronousStreamingClient(config) {}
  ~SynchronousStreamingBothWaysClient() {
    OnAllStreams(
        [](ClientContext* ctx,
           grpc::ClientReaderWriter<SimpleRequest, SimpleResponse>* s) -> bool {
          s->WritesDone();
          return true;
        });
  }

  bool InitThreadFuncImpl(size_t thread_idx) override {
    auto* stub = channels_[thread_idx % channels_.size()].get_stub();
    std::lock_guard<std::mutex> l(stream_mu_[thread_idx]);
    if (!shutdown_[thread_idx].val) {
      stream_[thread_idx] = stub->StreamingBothWays(&context_[thread_idx]);
    } else {
      return false;
    }
    return true;
  }
  bool ThreadFuncImpl(HistogramEntry* entry, size_t thread_idx) override {
    // TODO (vjpai): Do this
    return true;
  }
};

std::unique_ptr<Client> CreateSynchronousClient(const ClientConfig& config) {
  switch (config.rpc_type()) {
    case UNARY:
      return std::unique_ptr<Client>(new SynchronousUnaryClient(config));
    case STREAMING:
      return std::unique_ptr<Client>(
          new SynchronousStreamingPingPongClient(config));
    case STREAMING_FROM_CLIENT:
      return std::unique_ptr<Client>(
          new SynchronousStreamingFromClientClient(config));
    case STREAMING_FROM_SERVER:
      return std::unique_ptr<Client>(
          new SynchronousStreamingFromServerClient(config));
    case STREAMING_BOTH_WAYS:
      return std::unique_ptr<Client>(
          new SynchronousStreamingBothWaysClient(config));
    default:
      assert(false);
      return nullptr;
  }
}

}  // namespace testing
}  // namespace grpc
<|endoftext|>


<commit_before>// Copyright(c) Andre Caron, 2009-2011
//
// This document is covered by the an Open Source Initiative approved software
// license.  A copy of the license should have been provided alongside
// this software package (see "license.txt").  If not, the license is available
// online at "http://www.opensource.org/licenses/mit-license".

#include "Client.hpp"
#include "Server.hpp"

#include <iostream>

namespace {

}

int main ( int, char ** )
{
    demo::Client client_;
    demo::Server server_;

      // negotiation.
    client_ >> server_, server_ >> client_;
    client_ >> server_, server_ >> client_;
    std::cout << "-----" << std::endl;

      // exchange.
#if 0
    client_ << "Hello, server!";
    client_ >> server_;
    { std::string message;
        server_ >> message;
        std::cout << "Server: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;
#endif

      // re-negotiation.
#if 0
    client_.renegotiate();
    client_ >> server_, server_ >> client_;
    client_ >> server_, server_ >> client_;
    client_ >> server_, server_ >> client_;
    std::cout << "-----" << std::endl;
      // exchange.
    server_ << "Hello, client!";
    server_ >> client_;
    { std::string message;
        client_ >> message;
        std::cout << "Client: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;
#endif

      // re-negotiation.
    server_.renegotiate();
    server_ >> client_;
    client_ >> server_, server_ >> client_;
    client_ >> server_, server_ >> client_;
    std::cout << "-----" << std::endl;

      // exchange.
    server_ << "Hello, client!";
    server_ >> client_;
    { std::string message;
        client_ >> message;
        std::cout << "Client: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;

      // exchange.
#if 0
    client_ << "Hello, server!";
    client_ >> server_;
    { std::string message;
        server_ >> message;
        std::cout << "Server: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;
#endif

      // shutdown.
    server_.shutdown();
    server_ >> client_;
}

#pragma comment ( lib, "Crypt32.lib" )
#pragma comment ( lib, "Secur32.lib" )
<commit_msg>Trailing '_' on variable names.<commit_after>// Copyright(c) Andre Caron, 2009-2011
//
// This document is covered by the an Open Source Initiative approved software
// license.  A copy of the license should have been provided alongside
// this software package (see "license.txt").  If not, the license is available
// online at "http://www.opensource.org/licenses/mit-license".

#include "Client.hpp"
#include "Server.hpp"

#include <iostream>

namespace {

}

int main ( int, char ** )
{
    demo::Client client;
    demo::Server server;

      // negotiation.
    client >> server, server >> client;
    client >> server, server >> client;
    std::cout << "-----" << std::endl;

      // exchange.
#if 0
    client << "Hello, server!";
    client >> server;
    { std::string message;
        server >> message;
        std::cout << "Server: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;
#endif

      // re-negotiation.
#if 0
    client.renegotiate();
    client >> server, server >> client;
    client >> server, server >> client;
    client >> server, server >> client;
    std::cout << "-----" << std::endl;
      // exchange.
    server << "Hello, client!";
    server >> client;
    { std::string message;
        client >> message;
        std::cout << "Client: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;
#endif

      // re-negotiation.
    server.renegotiate();
    server >> client;
    client >> server, server >> client;
    client >> server, server >> client;
    std::cout << "-----" << std::endl;

      // exchange.
    server << "Hello, client!";
    server >> client;
    { std::string message;
        client >> message;
        std::cout << "Client: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;

      // exchange.
#if 0
    client << "Hello, server!";
    client >> server;
    { std::string message;
        server >> message;
        std::cout << "Server: data='" << message << "'." << std::endl;
    }
    std::cout << "-----" << std::endl;
#endif

      // shutdown.
    server.shutdown();
    server >> client;
}

#pragma comment ( lib, "Crypt32.lib" )
#pragma comment ( lib, "Secur32.lib" )
<|endoftext|>


<commit_before>/*
 * This file is part of the SPLINTER library.
 * Copyright (C) 2012 Bjarne Grimstad (bjarne.grimstad@gmail.com).
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <serializer.h>
#include "polynomialregression.h"
#include "linearsolvers.h"
#include "unsupported/Eigen/KroneckerProduct"

namespace SPLINTER
{

PolynomialRegression::PolynomialRegression()
{
}

PolynomialRegression::PolynomialRegression(const char *fileName)
    : PolynomialRegression(std::string(fileName))
{
}

PolynomialRegression::PolynomialRegression(const std::string fileName)
{
    load(fileName);
}

PolynomialRegression::PolynomialRegression(const DataTable &samples, unsigned int degree)
    : PolynomialRegression(samples, std::vector<unsigned int>(samples.getNumVariables(), degree))
{
}

PolynomialRegression::PolynomialRegression(const DataTable &samples, std::vector<unsigned int> degrees)
    : degrees(degrees),
      numVariables(samples.getNumVariables()),
      numCoefficients(0)
{
    if (degrees.size() != numVariables)
        throw Exception("PolynomialRegression::PolynomialRegression: Inconsistent input data!");

    // Check that a minimum number of samples is provided
    numCoefficients = 1;
    for (auto deg : degrees)
        numCoefficients *= (deg+1);

    if (numCoefficients > samples.getNumSamples())
        throw Exception("PolynomialRegression::PolynomialRegression: Insufficient number of samples!");

    // Compute coefficients
    computeCoefficients(samples);
}

double PolynomialRegression::eval(DenseVector x) const
{
    DenseMatrix monomials = evalMonomials(x);
    DenseMatrix res = coefficients*monomials;
    return res(0,0);
}

void PolynomialRegression::computeCoefficients(const DataTable &samples)
{
    // Left hand side
    DenseMatrix X = computeDesignMatrix(samples);
    DenseMatrix Xt = X.transpose();
    DenseMatrix XtX = Xt*X;

    // Right-hand side
    auto yvec = samples.getVectorY();
    DenseVector y(yvec.size());
    for (unsigned int i = 0; i < yvec.size(); ++i)
        y(i) = yvec.at(i);
    DenseMatrix Xty = Xt*y;

    // Solve for coefficients
    DenseQR s;
    if (!s.solve(XtX, Xty, coefficients))
        throw Exception("PolynomialRegression::computeCoefficients: Failed to solve for coefficients.");

    // Transpose coefficients matrix
    coefficients.transposeInPlace();
}

/*
 * Computes Vandermonde matrix
 * TODO: centering and scaling can improve the numerical properties
 */
DenseMatrix PolynomialRegression::computeDesignMatrix(const DataTable &samples) const
{
    DenseMatrix X = DenseMatrix::Zero(samples.getNumSamples(), numCoefficients);

    unsigned int i = 0;
    for (auto it = samples.cbegin(); it != samples.cend(); ++it, ++i)
    {
        // Get point x
        auto xvec = it->getX();
        DenseVector x(xvec.size());
        for (unsigned int j = 0; j < xvec.size(); ++j)
            x(j) = xvec.at(j);

        // Evaluate monomials at x
        DenseVector Xi = evalMonomials(x);
        assert(Xi.cols() == numCoefficients);

        // Add row to design matrix X
        X.block(i,0,1,numCoefficients) = Xi.transpose();
    }

    return X;
}

DenseVector PolynomialRegression::evalMonomials(DenseVector x) const
{
    std::vector<DenseVector> powers;

    for (unsigned int i = 0; i < numVariables; ++i)
    {
        unsigned int deg = degrees.at(i);
        DenseVector powi = DenseVector::Zero(deg+1);
        for (unsigned int j = 0; j <= deg; ++j)
            powi(j) = std::pow(x(i), j);
        powers.push_back(powi);
    }

    // Kronecker product of monovariable power basis
    DenseVector monomials = DenseVector::Ones(1);

    for (unsigned int i = 0; i < numVariables; ++i)
    {
        DenseVector temp = monomials;
        monomials = kroneckerProduct(temp, powers.at(i));
    }

    assert(monomials.cols() == numCoefficients);

    return monomials;
}

void PolynomialRegression::save(const std::string fileName) const
{
    Serializer s;
    s.serialize(*this);
    s.saveToFile(fileName);
}

void PolynomialRegression::load(const std::string fileName)
{
    Serializer s(fileName);
    s.deserialize(*this);
}

const std::string PolynomialRegression::getDescription() const
{
    std::string description("PolynomialRegression of degree");

    // See if all degrees are the same.
    bool equal = true;
    for(size_t i = 1; i < degrees.size(); ++i) {
        equal = equal && (degrees.at(i) == degrees.at(i-1));
    }

    if(equal) {
        description.append(" ");
        description.append(std::to_string(degrees.at(0)));

    } else {
        description.append("s (");
        for(size_t i = 0; i < degrees.size(); ++i) {
            description.append(std::to_string(degrees.at(i)));
            if(i + 1 < degrees.size()) {
                description.append(", ");
            }
        }
        description.append(")");
    }

    return description;
}

} // namespace SPLINTER
<commit_msg>Replace assertions with exceptions<commit_after>/*
 * This file is part of the SPLINTER library.
 * Copyright (C) 2012 Bjarne Grimstad (bjarne.grimstad@gmail.com).
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

#include <serializer.h>
#include "polynomialregression.h"
#include "linearsolvers.h"
#include "unsupported/Eigen/KroneckerProduct"

namespace SPLINTER
{

PolynomialRegression::PolynomialRegression()
{
}

PolynomialRegression::PolynomialRegression(const char *fileName)
    : PolynomialRegression(std::string(fileName))
{
}

PolynomialRegression::PolynomialRegression(const std::string fileName)
{
    load(fileName);
}

PolynomialRegression::PolynomialRegression(const DataTable &samples, unsigned int degree)
    : PolynomialRegression(samples, std::vector<unsigned int>(samples.getNumVariables(), degree))
{
}

PolynomialRegression::PolynomialRegression(const DataTable &samples, std::vector<unsigned int> degrees)
    : degrees(degrees),
      numVariables(samples.getNumVariables()),
      numCoefficients(0)
{
    if (degrees.size() != numVariables)
        throw Exception("PolynomialRegression::PolynomialRegression: Inconsistent input data!");

    // Check that a minimum number of samples is provided
    numCoefficients = 1;
    for (auto deg : degrees)
        numCoefficients *= (deg+1);

    if (numCoefficients > samples.getNumSamples())
        throw Exception("PolynomialRegression::PolynomialRegression: Insufficient number of samples!");

    // Compute coefficients
    computeCoefficients(samples);
}

double PolynomialRegression::eval(DenseVector x) const
{
    DenseMatrix monomials = evalMonomials(x);
    DenseMatrix res = coefficients*monomials;
    return res(0,0);
}

void PolynomialRegression::computeCoefficients(const DataTable &samples)
{
    // Left hand side
    DenseMatrix X = computeDesignMatrix(samples);
    DenseMatrix Xt = X.transpose();
    DenseMatrix XtX = Xt*X;

    // Right-hand side
    auto yvec = samples.getVectorY();
    DenseVector y(yvec.size());
    for (unsigned int i = 0; i < yvec.size(); ++i)
        y(i) = yvec.at(i);
    DenseMatrix Xty = Xt*y;

    // Solve for coefficients
    DenseQR s;
    if (!s.solve(XtX, Xty, coefficients))
        throw Exception("PolynomialRegression::computeCoefficients: Failed to solve for coefficients.");

    // Transpose coefficients matrix
    coefficients.transposeInPlace();
}

/*
 * Computes Vandermonde matrix
 * TODO: centering and scaling can improve the numerical properties
 */
DenseMatrix PolynomialRegression::computeDesignMatrix(const DataTable &samples) const
{
    DenseMatrix X = DenseMatrix::Zero(samples.getNumSamples(), numCoefficients);

    unsigned int i = 0;
    for (auto it = samples.cbegin(); it != samples.cend(); ++it, ++i)
    {
        // Get point x
        auto xvec = it->getX();
        DenseVector x(xvec.size());
        for (unsigned int j = 0; j < xvec.size(); ++j)
            x(j) = xvec.at(j);

        // Evaluate monomials at x
        DenseVector Xi = evalMonomials(x);

        if (Xi.rows() != numCoefficients)
        {
            throw Exception("PolynomialRegression::computeDesignMatrix: Xi.rows() != numCoefficients.");
        }

        // Add row to design matrix X
        X.block(i,0,1,numCoefficients) = Xi.transpose();
    }

    return X;
}

DenseVector PolynomialRegression::evalMonomials(DenseVector x) const
{
    std::vector<DenseVector> powers;

    for (unsigned int i = 0; i < numVariables; ++i)
    {
        unsigned int deg = degrees.at(i);
        DenseVector powi = DenseVector::Zero(deg+1);
        for (unsigned int j = 0; j <= deg; ++j)
            powi(j) = std::pow(x(i), j);
        powers.push_back(powi);
    }

    // Kronecker product of monovariable power basis
    DenseVector monomials = DenseVector::Ones(1);

    for (unsigned int i = 0; i < numVariables; ++i)
    {
        DenseVector temp = monomials;
        monomials = kroneckerProduct(temp, powers.at(i));
    }

    if (monomials.rows() == numCoefficients)
    {
        throw Exception("PolynomialRegression::evalMonomials: monomials.rows() != numCoefficients.");
    }

    return monomials;
}

void PolynomialRegression::save(const std::string fileName) const
{
    Serializer s;
    s.serialize(*this);
    s.saveToFile(fileName);
}

void PolynomialRegression::load(const std::string fileName)
{
    Serializer s(fileName);
    s.deserialize(*this);
}

const std::string PolynomialRegression::getDescription() const
{
    std::string description("PolynomialRegression of degree");

    // See if all degrees are the same.
    bool equal = true;
    for(size_t i = 1; i < degrees.size(); ++i) {
        equal = equal && (degrees.at(i) == degrees.at(i-1));
    }

    if(equal) {
        description.append(" ");
        description.append(std::to_string(degrees.at(0)));

    } else {
        description.append("s (");
        for(size_t i = 0; i < degrees.size(); ++i) {
            description.append(std::to_string(degrees.at(i)));
            if(i + 1 < degrees.size()) {
                description.append(", ");
            }
        }
        description.append(")");
    }

    return description;
}

} // namespace SPLINTER
<|endoftext|>


<commit_before>// inc order weird for these guys
#include <GL/glew.h>
#include <GLFW/glfw3.h>

//%deps(opengl, glfw)

#include "viewer/gl_aliases.hh"
#include "viewer/primitives/simple_geometry_primitives.hh"
#include "viewer/window_3d.hh"
#include "viewer/window_manager.hh"

#include "eigen_helpers.hh"

#include <map>
#include <thread>

namespace viewer {
namespace {

void apply_view(const OrbitCamera &view, bool show_axes) {
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glTransform(view.camera_from_anchor());
  glScaled(view.zoom(), view.zoom(), view.zoom());
  if (show_axes) {
    draw_axes({SE3(), 0.1 / view.zoom(), 3.0});
  }

  glTransform(view.anchor_from_world());
  if (show_axes) {
    draw_axes({SE3(), 0.2 / view.zoom(), 3.0});
  }
}

void prepare_to_render() {
  //
  // Flag soup
  //

  glShadeModel(GL_SMOOTH);

  // Check depth when rendering
  glEnable(GL_DEPTH_TEST);

  // Turn on lighting
  // glEnable(GL_LIGHTING);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_BLEND);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
  glEnable(GL_LINE_SMOOTH);
  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

  glEnable(GL_MULTISAMPLE);
}

void set_perspective(const GlSize &gl_size, bool ortho = false) {
  glViewport(0, 0, gl_size.width, gl_size.height);
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();

  constexpr double NEAR_CLIP = 0.001;
  constexpr double FAR_CLIP = 1000.0;
  const double aspect_ratio =
      (static_cast<double>(gl_size.width) / static_cast<double>(gl_size.height));
  if (ortho) {
    glOrtho(-aspect_ratio, aspect_ratio, -1.0, 1.0, NEAR_CLIP, FAR_CLIP);
  } else {
    constexpr double FOV = 60.0;
    gluPerspective(FOV, aspect_ratio, NEAR_CLIP, FAR_CLIP);
  }
}

}  // namespace

Window3D::Window3D(const GlSize &gl_size) : gl_size_(gl_size) {
  set_view_preset(ViewSetting::STANDARD);
}

void Window3D::set_view_preset(const ViewSetting &setting) {
  switch (setting) {
    case ViewSetting::STANDARD: {
      set_target_from_world(SE3(SO3::exp(Eigen::Vector3d(-3.1415 * 0.5, 0.0, 0.0)),
                                Eigen::Vector3d::Zero()));
      break;
    }
    case ViewSetting::CAMERA: {
      set_target_from_world(
          SE3(SO3::exp(Eigen::Vector3d::Zero()), Eigen::Vector3d::Zero()));
      break;
    }
  }
}

void Window3D::spin_until_step() {
  while (!should_step_ && !should_continue_ && !should_close()) {
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  if (should_continue_ && !should_close()) {
    std::this_thread::sleep_for(std::chrono::milliseconds(continue_ms_));
  }

  if (should_step_) {
    should_step_ = false;
  }
}

void Window3D::on_key(int key, int scancode, int action, int mods) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  const char key_char = static_cast<char>(key);

  if (action == GLFW_PRESS) {
    //
    // Toggling
    //
    if (key_mappings_.count(key_char) != 0) {
      const std::string toggle_name = key_mappings_.at(key_char);
      toggles_[toggle_name] = !toggles_[toggle_name];
      const bool new_toggle_state = toggles_[toggle_name];
      for (const auto &toggle_callback : toggle_callbacks_[toggle_name]) {
        toggle_callback(new_toggle_state);
      }
    }

    //
    // Navigation UI management
    //
    if (key_char == 'N') {
      should_step_ = true;
    }

    if (key_char == 'C') {
      should_continue_ = !should_continue_;
    }

    if (key_char == 'O') {
      orthogonal_projection_ = !orthogonal_projection_;
    }
    if (key_char == 'H') {
      hide_axes_ = !hide_axes_;
    }
  }
}
void Window3D::on_mouse_button(int button, int action, int mods) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  mouse_pos_last_click_ = mouse_pos();
}

void Window3D::on_mouse_move(const WindowPoint &mouse_pos) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  const bool shift = held_keys().count(GLFW_KEY_LEFT_SHIFT) == 1
                         ? held_keys().at(GLFW_KEY_LEFT_SHIFT)
                         : false;

  const bool left = left_mouse_held() && !shift;
  const bool right = right_mouse_held() || (shift && left_mouse_held());

  // if (left || right) {
  // glfwSetInputMode(get_window(), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  // } else {
  // glfwSetInputMode(get_window(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  // }

  view_.apply_mouse(mouse_pos, mouse_pos_last_click_, left, right);

  if (left || right) {
    mouse_pos_last_click_ = mouse_pos;
  }
}

void Window3D::on_scroll(const double amount) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);
  view_.apply_scroll(amount);
}

void Window3D::resize(const GlSize &gl_size) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  glViewport(0, 0, gl_size.width, gl_size.height);
  gl_size_ = gl_size;
}

void Window3D::draw_all_primitives() const {
  for (const auto &primitive : primitives_) {
    primitive->draw();
  }
}

void Window3D::render() {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  //
  // Render cameras
  //
  for (const auto &camera : cameras_) {
    prepare_to_render();
    camera->prepare_view();
    draw_all_primitives();
    camera->draw();
  }

  {  // Render main scene
    set_perspective(gl_size_, orthogonal_projection_);
    prepare_to_render();
    apply_view(view_, !hide_axes_);
    projection_ = Projection::get_from_current();
    draw_all_primitives();
  }

  const double t_now = glfwGetTime();

  const double dt = std::max(t_now - last_update_time_, 0.02);
  view_.apply_keys(held_keys(), dt);
  view_ = view_.simulate(dt);
  last_update_time_ = t_now;

  glFinish();
}  // namespace viewer

namespace {
struct Window3DGlobalState {
  std::map<std::string, std::shared_ptr<Window3D>> windows;
};

Window3DGlobalState window_3d_state;

Window3DGlobalState &get_global_state() {
  return window_3d_state;
}
}  // namespace

std::shared_ptr<Window3D> get_window3d(const std::string &title) {
  const auto it = get_global_state().windows.find(title);
  if (it != get_global_state().windows.end()) {
    return it->second;
  } else {
    const GlSize gl_size(640, 640);
    auto window = std::make_shared<Window3D>(gl_size);
    get_global_state().windows[title] = window;
    WindowManager::register_window(gl_size, window, title);
    return window;
  }
}
}  // namespace viewer
<commit_msg>Small updates to window<commit_after>// inc order weird for these guys
#include <GL/glew.h>
#include <GLFW/glfw3.h>

//%deps(opengl, glfw)

#include "viewer/gl_aliases.hh"
#include "viewer/primitives/simple_geometry_primitives.hh"
#include "viewer/window_3d.hh"
#include "viewer/window_manager.hh"

#include "eigen_helpers.hh"

#include <map>
#include <thread>

namespace viewer {
namespace {

void apply_view(const OrbitCamera &view, bool show_axes) {
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  glTransform(view.camera_from_anchor());
  glScaled(view.zoom(), view.zoom(), view.zoom());
  if (show_axes) {
    draw_axes({SE3(), 0.1 / view.zoom(), 3.0});
  }

  glTransform(view.anchor_from_world());
  if (show_axes) {
    draw_axes({SE3(), 0.2 / view.zoom(), 3.0});
  }
}

void prepare_to_render() {
  //
  // Flag soup
  //

  glShadeModel(GL_SMOOTH);

  // Check depth when rendering
  glEnable(GL_DEPTH_TEST);

  // Turn on lighting
  // glEnable(GL_LIGHTING);

  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glEnable(GL_BLEND);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
  glEnable(GL_LINE_SMOOTH);
  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);

  glEnable(GL_MULTISAMPLE);
}

void set_perspective(const GlSize &gl_size, bool ortho = false) {
  glViewport(0, 0, gl_size.width, gl_size.height);
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();

  constexpr double NEAR_CLIP = 0.001;
  constexpr double FAR_CLIP = 1000.0;
  const double aspect_ratio =
      (static_cast<double>(gl_size.width) / static_cast<double>(gl_size.height));
  if (ortho) {
    glOrtho(-aspect_ratio, aspect_ratio, -1.0, 1.0, NEAR_CLIP, FAR_CLIP);
  } else {
    constexpr double FOV = 60.0;
    gluPerspective(FOV, aspect_ratio, NEAR_CLIP, FAR_CLIP);
  }
}

}  // namespace

Window3D::Window3D(const GlSize &gl_size) : gl_size_(gl_size) {
  set_view_preset(ViewSetting::STANDARD);
}

void Window3D::set_view_preset(const ViewSetting &setting) {
  switch (setting) {
    case ViewSetting::STANDARD: {
      set_target_from_world(SE3(SO3::exp(Eigen::Vector3d(-3.1415 * 0.5, 0.0, 0.0)),
                                Eigen::Vector3d::Zero()));
      break;
    }
    case ViewSetting::CAMERA: {
      set_target_from_world(
          SE3(SO3::exp(Eigen::Vector3d::Zero()), Eigen::Vector3d::Zero()));
      break;
    }
  }
}

void Window3D::spin_until_step() {
  while (!should_step_ && !should_continue_ && !should_close()) {
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
  }

  if (should_continue_ && !should_close()) {
    std::this_thread::sleep_for(std::chrono::milliseconds(continue_ms_));
  }

  if (should_step_) {
    should_step_ = false;
  }
}

void Window3D::on_key(int key, int scancode, int action, int mods) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  const char key_char = static_cast<char>(key);

  if (action == GLFW_PRESS) {
    //
    // Toggling
    //
    if (key_mappings_.count(key_char) != 0) {
      const std::string toggle_name = key_mappings_.at(key_char);
      toggles_[toggle_name] = !toggles_[toggle_name];
      const bool new_toggle_state = toggles_[toggle_name];
      for (const auto &toggle_callback : toggle_callbacks_[toggle_name]) {
        toggle_callback(new_toggle_state);
      }
    }

    //
    // Navigation UI management
    //
    if (key_char == 'N') {
      should_step_ = true;
    }

    if (key_char == 'C') {
      should_continue_ = !should_continue_;
    }

    if (key_char == 'O') {
      orthogonal_projection_ = !orthogonal_projection_;
    }
    if (key_char == 'H') {
      hide_axes_ = !hide_axes_;
    }
  }
}
void Window3D::on_mouse_button(int button, int action, int mods) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  const auto current_mouse_pos = mouse_pos();
  const auto ray = projection_.unproject(current_mouse_pos);

  ///
  /// TODO: Refactor this out!
  ///
  // click_callback_manager.handle_callbacks(ray);

  mouse_pos_last_click_ = current_mouse_pos;
}

void Window3D::on_mouse_move(const WindowPoint &mouse_pos) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  const bool shift = held_keys().count(GLFW_KEY_LEFT_SHIFT) == 1
                         ? held_keys().at(GLFW_KEY_LEFT_SHIFT)
                         : false;

  const bool left = left_mouse_held() && !shift;
  const bool right = right_mouse_held() || (shift && left_mouse_held());

  // if (left || right) {
  // glfwSetInputMode(get_window(), GLFW_CURSOR, GLFW_CURSOR_DISABLED);
  // } else {
  // glfwSetInputMode(get_window(), GLFW_CURSOR, GLFW_CURSOR_NORMAL);
  // }

  view_.apply_mouse(mouse_pos, mouse_pos_last_click_, left, right);

  if (left || right) {
    mouse_pos_last_click_ = mouse_pos;
  }
}

void Window3D::on_scroll(const double amount) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);
  view_.apply_scroll(amount);
}

void Window3D::resize(const GlSize &gl_size) {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  glViewport(0, 0, gl_size.width, gl_size.height);
  gl_size_ = gl_size;
}

void Window3D::draw_all_primitives() const {
  for (const auto &primitive : primitives_) {
    primitive->draw();
  }
}

void Window3D::render() {
  const std::lock_guard<std::mutex> lk(behavior_mutex_);

  //
  // Render cameras
  //
  for (const auto &camera : cameras_) {
    prepare_to_render();
    camera->prepare_view();
    draw_all_primitives();
    camera->draw();
  }

  {  // Render main scene
    set_perspective(gl_size_, orthogonal_projection_);
    prepare_to_render();
    apply_view(view_, !hide_axes_);
    projection_ = Projection::get_from_current();
    draw_all_primitives();
  }

  const double t_now = glfwGetTime();

  const double dt = std::max(t_now - last_update_time_, 0.02);
  view_.apply_keys(held_keys(), dt);
  view_ = view_.simulate(dt);
  last_update_time_ = t_now;

  glFinish();
}  // namespace viewer

namespace {
struct Window3DGlobalState {
  std::map<std::string, std::shared_ptr<Window3D>> windows;
};

Window3DGlobalState window_3d_state;

Window3DGlobalState &get_global_state() {
  return window_3d_state;
}
}  // namespace

std::shared_ptr<Window3D> get_window3d(const std::string &title) {
  const auto it = get_global_state().windows.find(title);
  if (it != get_global_state().windows.end()) {
    return it->second;
  } else {
    const GlSize gl_size(640, 640);
    auto window = std::make_shared<Window3D>(gl_size);
    get_global_state().windows[title] = window;
    WindowManager::register_window(gl_size, window, title);
    return window;
  }
}
}  // namespace viewer
<|endoftext|>


<commit_before>#ifndef BASE_STAIR_DETECTOR_H_
#define BASE_STAIR_DETECTOR_H_

#include <vector>
#include <algorithm>

#include <pcl/visualization/cloud_viewer.h>

#include "lepp2/VideoObserver.hpp"
#include "lepp2/BaseSegmenter.hpp"
#include "lepp2/NoopSegmenter.hpp"
#include "lepp2/StairSegmenter.hpp"
#include "lepp2/StairAggregator.hpp"
#include "lepp2/ObjectApproximator.hpp"
#include "lepp2/MomentOfInertiaApproximator.hpp"
#include "lepp2/SplitApproximator.hpp"

using namespace lepp;

#include "lepp2/debug/timer.hpp"

template<class PointT>
class StairDetector : public lepp::VideoObserver<PointT> {

  public:
    StairDetector();
    virtual ~StairDetector() {}

    /**
     * VideoObserver interface method implementation.
     */
    virtual void notifyNewFrame(
        int idx,
        const typename pcl::PointCloud<PointT>::ConstPtr& point_cloud);
    /**
       * Attaches a new ObstacleAggregator, which will be notified of newly detected
       * obstacles by this detector.
       */
    void attachStairAggregator(boost::shared_ptr<StairAggregator<PointT> > aggregator);

  protected:
    /// Helper typedefs to make the implementation cleaner
    typedef pcl::PointCloud<PointT> PointCloudT;
    typedef typename PointCloudT::Ptr PointCloudPtr;
    typedef typename PointCloudT::ConstPtr CloudConstPtr;

    /**
     * Notifies any observers about newly detected stairs.
     */
    void notifyStairs(std::vector<CloudConstPtr> stairs);

  private:

    typename pcl::PointCloud<PointT>::ConstPtr cloud_;

    /**
     * Tracks all attached ObstacleAggregators that wish to be notified of newly
     * detected obstacles.
     */
    std::vector<boost::shared_ptr<StairAggregator<PointT> > > aggregators;

    boost::shared_ptr<BaseSegmenter<PointT> > segmenter_;
    boost::shared_ptr<ObjectApproximator<PointT> > approximator_;

    /**
     * Performs a new update of the obstacle approximations.
     * Triggered when the detector is notified of a new frame (i.e. point cloud).
     */
    void update();
};

template<class PointT>
StairDetector<PointT>::StairDetector()
    : approximator_(new SplitObjectApproximator<PointT>(
        boost::shared_ptr<ObjectApproximator<PointT> >(
          new MomentOfInertiaObjectApproximator<PointT>))),
      segmenter_(new StairSegmenter<PointT>()) {
}

template<class PointT>
void StairDetector<PointT>::notifyNewFrame(
    int id,
    const typename pcl::PointCloud<PointT>::ConstPtr& point_cloud) {
  cloud_ = point_cloud;
  try {
    update();
  } catch (...) {
    std::cerr << "ObstacleDetector: Obstacle detection failed ..." << std::endl;
  }
}

template<class PointT>
void StairDetector<PointT>::update() {

  Timer t;
  t.start();
  std::vector<CloudConstPtr> stairs(segmenter_->segment(cloud_));
  t.stop();
  std::cerr << "Stair segmentation took " << t.duration() << std::endl;

  notifyStairs(stairs);

//  // Iteratively approximate the segments
//  size_t segment_count = segments.size();
//  std::vector<ObjectModelPtr> models;
//  for (size_t i = 0; i < segment_count; ++i) {
//    models.push_back(approximator_->approximate(segments[i]));
//  }

//  std::cerr << "Obstacle detection took " << t.duration() << std::endl;
//
//  notifyObstacles(models);
}

template<class PointT>
void StairDetector<PointT>::attachStairAggregator(
    boost::shared_ptr<StairAggregator<PointT> > aggregator) {
  aggregators.push_back(aggregator);
}

template<class PointT>
void StairDetector<PointT>::notifyStairs(std::vector<CloudConstPtr> stairs) {
  size_t sz = aggregators.size();
  for (size_t i = 0; i < sz; ++i) {
    aggregators[i]->updateStairs(stairs);
  }
}

#endif
<commit_msg>Minor Cleanup StairDetector::update()<commit_after>#ifndef BASE_STAIR_DETECTOR_H_
#define BASE_STAIR_DETECTOR_H_

#include <vector>
#include <algorithm>

#include <pcl/visualization/cloud_viewer.h>

#include "lepp2/VideoObserver.hpp"
#include "lepp2/BaseSegmenter.hpp"
#include "lepp2/NoopSegmenter.hpp"
#include "lepp2/StairSegmenter.hpp"
#include "lepp2/StairAggregator.hpp"
#include "lepp2/ObjectApproximator.hpp"
#include "lepp2/MomentOfInertiaApproximator.hpp"
#include "lepp2/SplitApproximator.hpp"

using namespace lepp;

#include "lepp2/debug/timer.hpp"

template<class PointT>
class StairDetector : public lepp::VideoObserver<PointT> {

  public:
    StairDetector();
    virtual ~StairDetector() {}

    /**
     * VideoObserver interface method implementation.
     */
    virtual void notifyNewFrame(
        int idx,
        const typename pcl::PointCloud<PointT>::ConstPtr& point_cloud);
    /**
       * Attaches a new ObstacleAggregator, which will be notified of newly detected
       * obstacles by this detector.
       */
    void attachStairAggregator(boost::shared_ptr<StairAggregator<PointT> > aggregator);

  protected:
    /// Helper typedefs to make the implementation cleaner
    typedef pcl::PointCloud<PointT> PointCloudT;
    typedef typename PointCloudT::Ptr PointCloudPtr;
    typedef typename PointCloudT::ConstPtr CloudConstPtr;

    /**
     * Notifies any observers about newly detected stairs.
     */
    void notifyStairs(std::vector<CloudConstPtr> stairs);

  private:

    typename pcl::PointCloud<PointT>::ConstPtr cloud_;

    /**
     * Tracks all attached ObstacleAggregators that wish to be notified of newly
     * detected obstacles.
     */
    std::vector<boost::shared_ptr<StairAggregator<PointT> > > aggregators;

    boost::shared_ptr<BaseSegmenter<PointT> > segmenter_;
    boost::shared_ptr<ObjectApproximator<PointT> > approximator_;

    /**
     * Performs a new update of the obstacle approximations.
     * Triggered when the detector is notified of a new frame (i.e. point cloud).
     */
    void update();
};

template<class PointT>
StairDetector<PointT>::StairDetector()
    : approximator_(new SplitObjectApproximator<PointT>(
        boost::shared_ptr<ObjectApproximator<PointT> >(
          new MomentOfInertiaObjectApproximator<PointT>))),
      segmenter_(new StairSegmenter<PointT>()) {
}

template<class PointT>
void StairDetector<PointT>::notifyNewFrame(
    int id,
    const typename pcl::PointCloud<PointT>::ConstPtr& point_cloud) {
  cloud_ = point_cloud;
  try {
    update();
  } catch (...) {
    std::cerr << "ObstacleDetector: Obstacle detection failed ..." << std::endl;
  }
}

template<class PointT>
void StairDetector<PointT>::update() {

  Timer t;
  t.start();
  std::vector<CloudConstPtr> stairs(segmenter_->segment(cloud_));
  t.stop();
  std::cerr << "Stair segmentation took " << t.duration() << std::endl;

  t.start();
  notifyStairs(stairs);
  t.stop();
  std::cerr << "visualization took " << t.duration() << std::endl;
}

template<class PointT>
void StairDetector<PointT>::attachStairAggregator(
    boost::shared_ptr<StairAggregator<PointT> > aggregator) {
  aggregators.push_back(aggregator);
}

template<class PointT>
void StairDetector<PointT>::notifyStairs(std::vector<CloudConstPtr> stairs) {
  size_t sz = aggregators.size();
  for (size_t i = 0; i < sz; ++i) {
    aggregators[i]->updateStairs(stairs);
  }
}

#endif
<|endoftext|>


<commit_before>#include "gd.h"
#include "vw.h"
#include "lrq.h"
#include "rand48.h"
#include <float.h>

namespace LRQ {

  struct LRQstate {
    vw* all;
    bool lrindices[256];
    size_t orig_size[256];
    std::vector<std::string> lrpairs;
    bool dropout;
    uint64_t seed;
    uint64_t initial_seed;
  };
}

namespace {
  bool
  valid_int (const char* s)
    {
      char* endptr;

      int v = strtoul (s, &endptr, 0);
      (void) v;

      return (*s != '\0' && *endptr == '\0');
    }

  inline bool
  cheesyrbit (uint64_t& seed)
    {
      return merand48 (seed) > 0.5;
    }

  inline float
  cheesyrand (uint32_t x)
    {
      uint64_t seed = x;

      return merand48 (seed);
    }

  inline bool
  example_is_test (example* ec)
    {
      return ec->test_only || (((label_data*) ec->ld)->label == FLT_MAX);
    }

  void
  reset_seed (void* d)
    {
      LRQ::LRQstate* lrq = (LRQ::LRQstate*) d;

      if (lrq->all->bfgs)
        lrq->seed = lrq->initial_seed;
    }
}

namespace LRQ {

  void learn(void* d, learner& base, example* ec)
  {
    LRQstate* lrq = (LRQstate*) d;
    vw& all = *lrq->all;

    // Remember original features

    for (unsigned char* i = ec->indices.begin; i != ec->indices.end; ++i)
      {
        if (lrq->lrindices[*i])
          lrq->orig_size[*i] = ec->atomics[*i].size ();
      }

    size_t which = ec->example_counter;
    simple_prediction first_prediction;
    float first_loss;
    unsigned int maxiter = (all.training && ! example_is_test (ec)) ? 2 : 1;

    bool do_dropout = lrq->dropout && all.training && ! example_is_test (ec);
    float scale = (! lrq->dropout || do_dropout) ? 1.f : 0.5f;

    for (unsigned int iter = 0; iter < maxiter; ++iter, ++which)
      {
        // Add left LRQ features, holding right LRQ features fixed
        //     and vice versa
        // TODO: what happens with --lrq ab2 --lrq ac2
        //       i.e. namespace occurs multiple times (?)

        for (vector<string>::iterator i = lrq->lrpairs.begin ();
             i != lrq->lrpairs.end ();
             ++i)
          {
            unsigned char left = (*i)[which%2];
            unsigned char right = (*i)[(which+1)%2];
            unsigned int k = atoi (i->c_str () + 2);

            for (unsigned int lfn = 0; lfn < lrq->orig_size[left]; ++lfn)
              {
                feature* lf = ec->atomics[left].begin + lfn;
                float lfx = lf->x;
                size_t lindex = lf->weight_index + ec->ft_offset;

                for (unsigned int n = 1; n <= k; ++n)
                  {
                    if (! do_dropout || cheesyrbit (lrq->seed))
                      {
                        uint32_t lwindex = (uint32_t)(lindex + n * all.reg.stride);

                        float* lw = &all.reg.weight_vector[lwindex & all.reg.weight_mask];

                        // perturb away from saddle point at (0, 0)
                        if (all.training && ! example_is_test (ec) && *lw == 0)
                          *lw = cheesyrand (lwindex);

                        for (unsigned int rfn = 0;
                             rfn < lrq->orig_size[right];
                             ++rfn)
                          {
                            feature* rf = ec->atomics[right].begin + rfn;

                            // NB: ec->ft_offset added by base learner
                            float rfx = rf->x;
                            size_t rindex = rf->weight_index;
                            uint32_t rwindex = (uint32_t)(rindex + n * all.reg.stride);

                            feature lrq;
                            lrq.x = scale * *lw * lfx * rfx;
                            lrq.weight_index = rwindex;

                            ec->atomics[right].push_back (lrq);

                            if (all.audit)
                              {
                                char name[4] = { 'l', 'r', 'q', '\0' };
                                char subname[4] = { left, '^', right, '\0' };
                                audit_data ad = { name, subname, lrq.weight_index, lrq.x, false };
                                ec->audit_features[right].push_back (ad);
                              }
                          }
                      }
                  }
              }
          }

        base.learn(ec);//Recursive Call

        // Restore example

        if (iter == 0)
          {
            first_prediction = ec->final_prediction;
            first_loss = ec->loss;
          }
        else
          {
            ec->final_prediction = first_prediction;
            ec->loss = first_loss;
          }

        for (vector<string>::iterator i = lrq->lrpairs.begin ();
             i != lrq->lrpairs.end ();
             ++i)
          {
            unsigned char right = (*i)[(which+1)%2];

            ec->atomics[right].end =
              ec->atomics[right].begin + lrq->orig_size[right];

            if (all.audit)
              ec->audit_features[right].end =
                ec->audit_features[right].begin + lrq->orig_size[right];
          }
      }
  }

  learner* setup(vw& all, std::vector<std::string>&opts, po::variables_map& vm, po::variables_map& vm_file)
  {//parse and set arguments
    LRQstate* lrq = (LRQstate*) calloc (1, sizeof (LRQstate));
    unsigned int maxk = 0;
    lrq->all = &all;

    size_t random_seed = 0;
    if (vm.count("random_seed")) random_seed = vm["random_seed"].as<size_t> ();
    if (vm_file.count("random_seed")) random_seed = vm_file["random_seed"].as<size_t> ();

    lrq->initial_seed = lrq->seed = random_seed | 8675309;
    lrq->dropout = vm.count("lrqdropout") || vm_file.count("lrqdropout");

    if (lrq->dropout && !vm_file.count("lrqdropout"))
      all.options_from_file.append("--lrqdropout");

    if (!vm_file.count("lrq"))
      {
        lrq->lrpairs = vm["lrq"].as<vector<string> > ();

        // TODO: doesn't work for non-printable stuff

        stringstream ss;
        for (vector<string>::iterator i = lrq->lrpairs.begin ();
             i != lrq->lrpairs.end ();
             ++i)
          {
            ss << " --lrq " << *i;
          }

        all.options_from_file.append(ss.str());
      }
    else
      lrq->lrpairs = vm_file["lrq"].as<vector<string> > ();

    if (! all.quiet)
      {
        cerr << "creating low rank quadratic features for pairs: ";
        if (lrq->dropout)
          cerr << "(using dropout) ";
      }

    for (vector<string>::iterator i = lrq->lrpairs.begin ();
         i != lrq->lrpairs.end ();
         ++i)
      {
        if(!all.quiet){
          if (( i->length() < 3 ) || ! valid_int (i->c_str () + 2)) {
            cerr << endl << "error, low-rank quadratic features must involve two sets and a rank.\n";
            throw exception();
          }
          cerr << *i << " ";
        }
        // TODO: colon-syntax

        unsigned int k = atoi (i->c_str () + 2);

        lrq->lrindices[(int) (*i)[0]] = 1;
        lrq->lrindices[(int) (*i)[1]] = 1;

        maxk = max (maxk, k);
      }

    if(!all.quiet)
      cerr<<endl;

    all.wpp = all.wpp * (1 + maxk);
    learner* l = new learner(lrq, learn, all.l, 1 + maxk);
    l->set_end_pass (reset_seed);

    // TODO: leaks memory ?
    return l;
  }
}
<commit_msg>options save bugfix<commit_after>#include "gd.h"
#include "vw.h"
#include "lrq.h"
#include "rand48.h"
#include <float.h>

namespace LRQ {

  struct LRQstate {
    vw* all;
    bool lrindices[256];
    size_t orig_size[256];
    std::vector<std::string> lrpairs;
    bool dropout;
    uint64_t seed;
    uint64_t initial_seed;
  };
}

namespace {
  bool
  valid_int (const char* s)
    {
      char* endptr;

      int v = strtoul (s, &endptr, 0);
      (void) v;

      return (*s != '\0' && *endptr == '\0');
    }

  inline bool
  cheesyrbit (uint64_t& seed)
    {
      return merand48 (seed) > 0.5;
    }

  inline float
  cheesyrand (uint32_t x)
    {
      uint64_t seed = x;

      return merand48 (seed);
    }

  inline bool
  example_is_test (example* ec)
    {
      return ec->test_only || (((label_data*) ec->ld)->label == FLT_MAX);
    }

  void
  reset_seed (void* d)
    {
      LRQ::LRQstate* lrq = (LRQ::LRQstate*) d;

      if (lrq->all->bfgs)
        lrq->seed = lrq->initial_seed;
    }
}

namespace LRQ {

  void learn(void* d, learner& base, example* ec)
  {
    LRQstate* lrq = (LRQstate*) d;
    vw& all = *lrq->all;

    // Remember original features

    for (unsigned char* i = ec->indices.begin; i != ec->indices.end; ++i)
      {
        if (lrq->lrindices[*i])
          lrq->orig_size[*i] = ec->atomics[*i].size ();
      }

    size_t which = ec->example_counter;
    simple_prediction first_prediction;
    float first_loss;
    unsigned int maxiter = (all.training && ! example_is_test (ec)) ? 2 : 1;

    bool do_dropout = lrq->dropout && all.training && ! example_is_test (ec);
    float scale = (! lrq->dropout || do_dropout) ? 1.f : 0.5f;

    for (unsigned int iter = 0; iter < maxiter; ++iter, ++which)
      {
        // Add left LRQ features, holding right LRQ features fixed
        //     and vice versa
        // TODO: what happens with --lrq ab2 --lrq ac2
        //       i.e. namespace occurs multiple times (?)

        for (vector<string>::iterator i = lrq->lrpairs.begin ();
             i != lrq->lrpairs.end ();
             ++i)
          {
            unsigned char left = (*i)[which%2];
            unsigned char right = (*i)[(which+1)%2];
            unsigned int k = atoi (i->c_str () + 2);

            for (unsigned int lfn = 0; lfn < lrq->orig_size[left]; ++lfn)
              {
                feature* lf = ec->atomics[left].begin + lfn;
                float lfx = lf->x;
                size_t lindex = lf->weight_index + ec->ft_offset;

                for (unsigned int n = 1; n <= k; ++n)
                  {
                    if (! do_dropout || cheesyrbit (lrq->seed))
                      {
                        uint32_t lwindex = (uint32_t)(lindex + n * all.reg.stride);

                        float* lw = &all.reg.weight_vector[lwindex & all.reg.weight_mask];

                        // perturb away from saddle point at (0, 0)
                        if (all.training && ! example_is_test (ec) && *lw == 0)
                          *lw = cheesyrand (lwindex);

                        for (unsigned int rfn = 0;
                             rfn < lrq->orig_size[right];
                             ++rfn)
                          {
                            feature* rf = ec->atomics[right].begin + rfn;

                            // NB: ec->ft_offset added by base learner
                            float rfx = rf->x;
                            size_t rindex = rf->weight_index;
                            uint32_t rwindex = (uint32_t)(rindex + n * all.reg.stride);

                            feature lrq;
                            lrq.x = scale * *lw * lfx * rfx;
                            lrq.weight_index = rwindex;

                            ec->atomics[right].push_back (lrq);

                            if (all.audit)
                              {
                                char name[4] = { 'l', 'r', 'q', '\0' };
                                char subname[4] = { left, '^', right, '\0' };
                                audit_data ad = { name, subname, lrq.weight_index, lrq.x, false };
                                ec->audit_features[right].push_back (ad);
                              }
                          }
                      }
                  }
              }
          }

        base.learn(ec);//Recursive Call

        // Restore example

        if (iter == 0)
          {
            first_prediction = ec->final_prediction;
            first_loss = ec->loss;
          }
        else
          {
            ec->final_prediction = first_prediction;
            ec->loss = first_loss;
          }

        for (vector<string>::iterator i = lrq->lrpairs.begin ();
             i != lrq->lrpairs.end ();
             ++i)
          {
            unsigned char right = (*i)[(which+1)%2];

            ec->atomics[right].end =
              ec->atomics[right].begin + lrq->orig_size[right];

            if (all.audit)
              ec->audit_features[right].end =
                ec->audit_features[right].begin + lrq->orig_size[right];
          }
      }
  }

  learner* setup(vw& all, std::vector<std::string>&opts, po::variables_map& vm, po::variables_map& vm_file)
  {//parse and set arguments
    LRQstate* lrq = (LRQstate*) calloc (1, sizeof (LRQstate));
    unsigned int maxk = 0;
    lrq->all = &all;

    size_t random_seed = 0;
    if (vm.count("random_seed")) random_seed = vm["random_seed"].as<size_t> ();
    if (vm_file.count("random_seed")) random_seed = vm_file["random_seed"].as<size_t> ();

    lrq->initial_seed = lrq->seed = random_seed | 8675309;
    lrq->dropout = vm.count("lrqdropout") || vm_file.count("lrqdropout");

    if (lrq->dropout && !vm_file.count("lrqdropout"))
      all.options_from_file.append(" --lrqdropout");

    if (!vm_file.count("lrq"))
      {
        lrq->lrpairs = vm["lrq"].as<vector<string> > ();

        // TODO: doesn't work for non-printable stuff

        stringstream ss;
        for (vector<string>::iterator i = lrq->lrpairs.begin ();
             i != lrq->lrpairs.end ();
             ++i)
          {
            ss << " --lrq " << *i;
          }

        all.options_from_file.append(ss.str());
      }
    else
      lrq->lrpairs = vm_file["lrq"].as<vector<string> > ();

    if (! all.quiet)
      {
        cerr << "creating low rank quadratic features for pairs: ";
        if (lrq->dropout)
          cerr << "(using dropout) ";
      }

    for (vector<string>::iterator i = lrq->lrpairs.begin ();
         i != lrq->lrpairs.end ();
         ++i)
      {
        if(!all.quiet){
          if (( i->length() < 3 ) || ! valid_int (i->c_str () + 2)) {
            cerr << endl << "error, low-rank quadratic features must involve two sets and a rank.\n";
            throw exception();
          }
          cerr << *i << " ";
        }
        // TODO: colon-syntax

        unsigned int k = atoi (i->c_str () + 2);

        lrq->lrindices[(int) (*i)[0]] = 1;
        lrq->lrindices[(int) (*i)[1]] = 1;

        maxk = max (maxk, k);
      }

    if(!all.quiet)
      cerr<<endl;

    all.wpp = all.wpp * (1 + maxk);
    learner* l = new learner(lrq, learn, all.l, 1 + maxk);
    l->set_end_pass (reset_seed);

    // TODO: leaks memory ?
    return l;
  }
}
<|endoftext|>


<commit_before>/// @file   generalAction.hpp
/// @brief  Defines the base class for any kind of action.
/// @author Enrico Fraccaroli
/// @date   Jul 13 2016
/// @copyright
/// Copyright (c) 2016 Enrico Fraccaroli <enrico.fraccaroli@gmail.com>
/// Permission to use, copy, modify, and distribute this software for any
/// purpose with or without fee is hereby granted, provided that the above
/// copyright notice and this permission notice appear in all copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
/// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
/// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
/// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
/// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
/// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
/// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#pragma once

#include "../production.hpp"
#include "../building.hpp"
#include "../defines.hpp"
#include "../utils.hpp"
#include "../item.hpp"
#include "../opponent.hpp"

/// The list of possible actions.
typedef enum class ActionTypes
{
    /// The character is doing common action.
    Wait,
    /// The character is moving to another location.
    Move,
    /// The character is crafting something.
    Crafting,
    /// The character is crafting something.
    Building,
    /// The character is fighting.
    Combat
} ActionType;

/// The list of possible actions.
typedef enum class ActionStatus_t
{
    /// The action is still running.
    Running,
    /// The action has encountered an error.
    Error
} ActionStatus;

class GeneralAction
{
    protected:
        /// Actor of the action.
        Character * actor;
        /// The time point in the future needed by the action to complete.
        TimeClock actionCooldown;
        /// The status of the action.
        ActionStatus actionStatus;

    public:
        /// @brief Constructor.
        GeneralAction(Character * _actor);

        /// @brief Constructor.
        GeneralAction(Character * _actor, TimeClock _actionCooldown);

        /// @brief Destructor.
        virtual ~GeneralAction();

        /// @brief Check if the cooldown of the action is elapsed.
        /// @return True if the time has passed,

        ///         False otherwise.
        bool checkElapsed() const;

        /// @brief Checks the correctness of the action's values.
        /// @return True if it has correct values,

        ///         False otherwise.
        virtual bool check() const;

        /// @brief Provides the type of the action.
        /// @return The type of action.
        virtual ActionType getType() const;

        /// @brief Provides the description of the action.
        /// @return The string which describe the current action.
        virtual std::string getDescription() const;

        /// @brief Stops the current action and returns a string which describe the intterruption.
        /// @return The stopping description.
        virtual std::string stop();

        /// @brief Performs the current action.
        /// @return True if the action is finished,

        ///         False otherwise.
        virtual bool perform();

        ActionStatus getActionStatus() const;

};

/// @addtogroup EnumToString
/// @{

/// Return the string describing the type of Action.
std::string GetActionTypeName(ActionType type);

/// @}
<commit_msg>Add finish enum to ActionStatus<commit_after>/// @file   generalAction.hpp
/// @brief  Defines the base class for any kind of action.
/// @author Enrico Fraccaroli
/// @date   Jul 13 2016
/// @copyright
/// Copyright (c) 2016 Enrico Fraccaroli <enrico.fraccaroli@gmail.com>
/// Permission to use, copy, modify, and distribute this software for any
/// purpose with or without fee is hereby granted, provided that the above
/// copyright notice and this permission notice appear in all copies.
///
/// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
/// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
/// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
/// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
/// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
/// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
/// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#pragma once

#include "../production.hpp"
#include "../building.hpp"
#include "../defines.hpp"
#include "../utils.hpp"
#include "../item.hpp"
#include "../opponent.hpp"

/// The list of possible actions.
typedef enum class ActionTypes
{
    /// The character is doing common action.
    Wait,
    /// The character is moving to another location.
    Move,
    /// The character is crafting something.
    Crafting,
    /// The character is crafting something.
    Building,
    /// The character is fighting.
    Combat
} ActionType;

/// The list of possible actions.
typedef enum class ActionStatus_t
{
    /// The action is finished.
    Finished,
    /// The action is still running.
    Running,
    /// The action has encountered an error.
    Error
} ActionStatus;

class GeneralAction
{
    protected:
        /// Actor of the action.
        Character * actor;
        /// The time point in the future needed by the action to complete.
        TimeClock actionCooldown;

    public:
        /// @brief Constructor.
        GeneralAction(Character * _actor);

        /// @brief Constructor.
        GeneralAction(Character * _actor, TimeClock _actionCooldown);

        /// @brief Destructor.
        virtual ~GeneralAction();

        /// @brief Check if the cooldown of the action is elapsed.
        /// @return True if the time has passed,

        ///         False otherwise.
        bool checkElapsed() const;

        /// @brief Checks the correctness of the action's values.
        /// @return True if it has correct values,

        ///         False otherwise.
        virtual bool check() const;

        /// @brief Provides the type of the action.
        /// @return The type of action.
        virtual ActionType getType() const;

        /// @brief Provides the description of the action.
        /// @return The string which describe the current action.
        virtual std::string getDescription() const;

        /// @brief Stops the current action and returns a string which describe the intterruption.
        /// @return The stopping description.
        virtual std::string stop();

        /// @brief Performs the current action.
        /// @return the status after performing the action.
        virtual ActionStatus perform();
};

/// @addtogroup EnumToString
/// @{

/// Return the string describing the type of Action.
std::string GetActionTypeName(ActionType type);

/// @}
<|endoftext|>