<commit_before>#include <gtest/gtest.h>

#include <sstream>
#include <pficommon/lang/cast.h>
#include "recommender.hpp"
#include "../classifier/classifier_test_util.hpp"

namespace jubatus {
namespace recommender {

using namespace std;
using namespace pfi::lang;

sfv_diff_t make_vec(float v1, float v2, float v3) {
  sfv_diff_t v;
  v.push_back(make_pair("c1", v1));
  v.push_back(make_pair("c2", v2));
  v.push_back(make_pair("c3", v3));
  return v;
}

sfv_diff_t make_vec(const string& c1, const string& c2, const string& c3) {
  sfv_diff_t v;
  v.push_back(make_pair(c1, 1.0));
  v.push_back(make_pair(c2, 1.0));
  v.push_back(make_pair(c3, 1.0));
  return v;
}

template <typename T>
class recommender_random_test : public testing::Test {};

TYPED_TEST_CASE_P(recommender_random_test);

TYPED_TEST_P(recommender_random_test, trivial) {
  TypeParam r;

  r.update_row("r1", make_vec("c1", "c2", "c3"));
  r.update_row("r2", make_vec("c4", "c5", "c6"));

  vector<pair<string, float> > ids;
  r.similar_row(make_vec("c1", "c2", "c3"), ids, 1);
  ASSERT_EQ(1u, ids.size());
  EXPECT_EQ("r1", ids[0].first);
}

TYPED_TEST_P(recommender_random_test, random) {
  TypeParam r;

  // Generate random data from two norma distributions, N1 and N2.
  vector<float> mu1;
  mu1.push_back(1.0);
  mu1.push_back(1.0);
  mu1.push_back(1.0);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu1, 1.0, 3, v);
    string row_name = "r1_" + lexical_cast<string>(i);
    r.update_row(row_name, make_vec(v[0], v[1], v[2]));
  }

  vector<float> mu2;
  mu2.push_back(-1.0);
  mu2.push_back(-1.0);
  mu2.push_back(-1.0);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu2, 1.0, 3, v);
    string row_name = "r2_" + lexical_cast<string>(i);
    r.update_row(row_name, make_vec(v[0], v[1], v[2]));
  }

  // Then, recommend to mean of N1
  vector<pair<string, float> > ids;
  r.similar_row(make_vec(1.0, 1.0, 1.0), ids, 10);
  ASSERT_EQ(10u, ids.size());
  size_t correct = 0;
  for (size_t i = 0; i < ids.size(); ++i) {
    if (ids[i].first[1] == '1')
      ++correct;
  }
  EXPECT_GT(correct, 5u);

  // save the recommender
  stringstream oss;
  r.save(oss);
  TypeParam r2;
  r2.load(oss);

  // Run the same test
  ids.clear();
  r2.similar_row(make_vec(1.0, 1.0, 1.0), ids, 10);
  ASSERT_EQ(10u, ids.size());
  correct = 0;
  for (size_t i = 0; i < ids.size(); ++i) {
    if (ids[i].first[1] == '1')
      ++correct;
  }
  EXPECT_GT(correct, 5u);
}

void update_random(recommender_base& r) {
  vector<float> mu(3);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu, 1.0, 3, v);
    string row_name = "r1_" + lexical_cast<string>(i);
    r.update_row(row_name, make_vec(v[0], v[1], v[2]));
  }
}

void compare_recommenders(recommender_base& r1,
                          recommender_base& r2,
                          bool compare_complete_row = true) {
  // make a query vector
  sfv_t q = make_vec(0.5, 0.3, 1.0);

  // Get result before saving
  vector<pair<string, float> > ids1;
  r1.similar_row(q, ids1, 10);
  sfv_t comp1;
  r1.complete_row("r1_0", comp1);

  // Get result from loaded data
  vector<pair<string, float> > ids2;
  r2.similar_row(q, ids2, 10);
  sfv_t comp2;
  r2.complete_row("r1_0", comp2);

  // Compare two results
  // ID order could not be same if there are score ties.
  // EXPECT_TRUE(ids1 == ids2);
  ASSERT_EQ(ids1.size(), ids2.size());
  for (size_t i = 0; i < ids1.size(); ++i){
    EXPECT_FLOAT_EQ(ids1[i].second, ids2[i].second);
  }

  if (compare_complete_row)
    EXPECT_TRUE(comp1 == comp2);
}

TYPED_TEST_P(recommender_random_test, save_load) {
  TypeParam r;

  // Generate random data
  update_random(r);

  // save and load
  stringstream ss;
  r.save(ss);
  TypeParam r2;
  r2.load(ss);

  vector<string> row_ids;
  r2.get_all_row_ids(row_ids);
  EXPECT_EQ(100u, row_ids.size());

  compare_recommenders(r, r2);
}

TYPED_TEST_P(recommender_random_test, get_all_row_ids) {
  TypeParam r;
  vector<string> expect_ids;
  for (size_t i = 0; i < 100; ++i) {
    string row_name = "r1_" + lexical_cast<string>(i);
    expect_ids.push_back(row_name);
  }
  update_random(r);

  // Get all ids
  vector<string> ids;
  r.get_all_row_ids(ids);

  // Compare
  sort(expect_ids.begin(), expect_ids.end());
  sort(ids.begin(), ids.end());
  ASSERT_EQ(100u, ids.size());
  ASSERT_TRUE(expect_ids == ids);

  /* TODO this test cannot be passed with current implementation
  // Remove half rows
  for (size_t i = 0; i < 50; ++i) {
    string row_name = "r1_" + lexical_cast<string>(i);
    r.clear_row(row_name);
  }

  // Get rest of ids
  ids.clear();
  r.get_all_row_ids(ids);
  ASSERT_EQ(50u, ids.size());
  expect_ids.erase(expect_ids.begin(), expect_ids.begin() + 50);
  ASSERT_TRUE(expect_ids == ids);
  */
}

TYPED_TEST_P(recommender_random_test, diff) {
  TypeParam r;
  update_random(r);

  string diff;
  r.get_storage()->get_diff(diff);

  TypeParam r2;
  r2.get_storage()->set_mixed_and_clear_diff(diff);

  compare_recommenders(r, r2, false);
}

TYPED_TEST_P(recommender_random_test, mix) {
  TypeParam r1, r2, expect;
  vector<float> mu(10);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu, 1.0, 3, v);
    sfv_t vec = make_vec(v[0], v[1], v[2]);

    string row = "r_" + lexical_cast<string>(i);
    (i < 50 ? r1 : r2).update_row(row, vec);
    expect.update_row(row, vec);
  }

  string diff1, diff2;
  r1.get_storage()->get_diff(diff1);
  r2.get_storage()->get_diff(diff2);

  r1.get_storage()->mix(diff1, diff2);

  TypeParam mixed;
  mixed.get_storage()->set_mixed_and_clear_diff(diff2);

  compare_recommenders(expect, mixed, false);
}

REGISTER_TYPED_TEST_CASE_P(recommender_random_test,
                           trivial, random, save_load, get_all_row_ids,
                           diff, mix);

typedef testing::Types<inverted_index, lsh, minhash> recommender_types;

INSTANTIATE_TYPED_TEST_CASE_P(rt, recommender_random_test, recommender_types);

}
}
<commit_msg>Add euclid_lsh to recommender_random_test<commit_after>#include <gtest/gtest.h>

#include <sstream>
#include <pficommon/lang/cast.h>
#include "recommender.hpp"
#include "../classifier/classifier_test_util.hpp"

namespace jubatus {
namespace recommender {

using namespace std;
using namespace pfi::lang;

sfv_diff_t make_vec(float v1, float v2, float v3) {
  sfv_diff_t v;
  v.push_back(make_pair("c1", v1));
  v.push_back(make_pair("c2", v2));
  v.push_back(make_pair("c3", v3));
  return v;
}

sfv_diff_t make_vec(const string& c1, const string& c2, const string& c3) {
  sfv_diff_t v;
  v.push_back(make_pair(c1, 1.0));
  v.push_back(make_pair(c2, 1.0));
  v.push_back(make_pair(c3, 1.0));
  return v;
}

template <typename T>
class recommender_random_test : public testing::Test {};

TYPED_TEST_CASE_P(recommender_random_test);

TYPED_TEST_P(recommender_random_test, trivial) {
  TypeParam r;

  r.update_row("r1", make_vec("c1", "c2", "c3"));
  r.update_row("r2", make_vec("c4", "c5", "c6"));

  vector<pair<string, float> > ids;
  r.similar_row(make_vec("c1", "c2", "c3"), ids, 1);
  ASSERT_EQ(1u, ids.size());
  EXPECT_EQ("r1", ids[0].first);
}

TYPED_TEST_P(recommender_random_test, random) {
  TypeParam r;

  // Generate random data from two norma distributions, N1 and N2.
  vector<float> mu1;
  mu1.push_back(1.0);
  mu1.push_back(1.0);
  mu1.push_back(1.0);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu1, 1.0, 3, v);
    string row_name = "r1_" + lexical_cast<string>(i);
    r.update_row(row_name, make_vec(v[0], v[1], v[2]));
  }

  vector<float> mu2;
  mu2.push_back(-1.0);
  mu2.push_back(-1.0);
  mu2.push_back(-1.0);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu2, 1.0, 3, v);
    string row_name = "r2_" + lexical_cast<string>(i);
    r.update_row(row_name, make_vec(v[0], v[1], v[2]));
  }

  // Then, recommend to mean of N1
  vector<pair<string, float> > ids;
  r.similar_row(make_vec(1.0, 1.0, 1.0), ids, 10);
  ASSERT_EQ(10u, ids.size());
  size_t correct = 0;
  for (size_t i = 0; i < ids.size(); ++i) {
    if (ids[i].first[1] == '1')
      ++correct;
  }
  EXPECT_GT(correct, 5u);

  // save the recommender
  stringstream oss;
  r.save(oss);
  TypeParam r2;
  r2.load(oss);

  // Run the same test
  ids.clear();
  r2.similar_row(make_vec(1.0, 1.0, 1.0), ids, 10);
  ASSERT_EQ(10u, ids.size());
  correct = 0;
  for (size_t i = 0; i < ids.size(); ++i) {
    if (ids[i].first[1] == '1')
      ++correct;
  }
  EXPECT_GT(correct, 5u);
}

void update_random(recommender_base& r) {
  vector<float> mu(3);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu, 1.0, 3, v);
    string row_name = "r1_" + lexical_cast<string>(i);
    r.update_row(row_name, make_vec(v[0], v[1], v[2]));
  }
}

void compare_recommenders(recommender_base& r1,
                          recommender_base& r2,
                          bool compare_complete_row = true) {
  // make a query vector
  sfv_t q = make_vec(0.5, 0.3, 1.0);

  // Get result before saving
  vector<pair<string, float> > ids1;
  r1.similar_row(q, ids1, 10);
  sfv_t comp1;
  r1.complete_row("r1_0", comp1);

  // Get result from loaded data
  vector<pair<string, float> > ids2;
  r2.similar_row(q, ids2, 10);
  sfv_t comp2;
  r2.complete_row("r1_0", comp2);

  // Compare two results
  // ID order could not be same if there are score ties.
  // EXPECT_TRUE(ids1 == ids2);
  ASSERT_EQ(ids1.size(), ids2.size());
  for (size_t i = 0; i < ids1.size(); ++i){
    EXPECT_FLOAT_EQ(ids1[i].second, ids2[i].second);
  }

  if (compare_complete_row)
    EXPECT_TRUE(comp1 == comp2);
}

TYPED_TEST_P(recommender_random_test, save_load) {
  TypeParam r;

  // Generate random data
  update_random(r);

  // save and load
  stringstream ss;
  r.save(ss);
  TypeParam r2;
  r2.load(ss);

  vector<string> row_ids;
  r2.get_all_row_ids(row_ids);
  EXPECT_EQ(100u, row_ids.size());

  compare_recommenders(r, r2);
}

TYPED_TEST_P(recommender_random_test, get_all_row_ids) {
  TypeParam r;
  vector<string> expect_ids;
  for (size_t i = 0; i < 100; ++i) {
    string row_name = "r1_" + lexical_cast<string>(i);
    expect_ids.push_back(row_name);
  }
  update_random(r);

  // Get all ids
  vector<string> ids;
  r.get_all_row_ids(ids);

  // Compare
  sort(expect_ids.begin(), expect_ids.end());
  sort(ids.begin(), ids.end());
  ASSERT_EQ(100u, ids.size());
  ASSERT_TRUE(expect_ids == ids);

  /* TODO this test cannot be passed with current implementation
  // Remove half rows
  for (size_t i = 0; i < 50; ++i) {
    string row_name = "r1_" + lexical_cast<string>(i);
    r.clear_row(row_name);
  }

  // Get rest of ids
  ids.clear();
  r.get_all_row_ids(ids);
  ASSERT_EQ(50u, ids.size());
  expect_ids.erase(expect_ids.begin(), expect_ids.begin() + 50);
  ASSERT_TRUE(expect_ids == ids);
  */
}

TYPED_TEST_P(recommender_random_test, diff) {
  TypeParam r;
  update_random(r);

  string diff;
  r.get_storage()->get_diff(diff);

  TypeParam r2;
  r2.get_storage()->set_mixed_and_clear_diff(diff);

  compare_recommenders(r, r2, false);
}

TYPED_TEST_P(recommender_random_test, mix) {
  TypeParam r1, r2, expect;
  vector<float> mu(10);
  for (size_t i = 0; i < 100; ++i) {
    vector<double> v;
    make_random(mu, 1.0, 3, v);
    sfv_t vec = make_vec(v[0], v[1], v[2]);

    string row = "r_" + lexical_cast<string>(i);
    (i < 50 ? r1 : r2).update_row(row, vec);
    expect.update_row(row, vec);
  }

  string diff1, diff2;
  r1.get_storage()->get_diff(diff1);
  r2.get_storage()->get_diff(diff2);

  r1.get_storage()->mix(diff1, diff2);

  TypeParam mixed;
  mixed.get_storage()->set_mixed_and_clear_diff(diff2);

  compare_recommenders(expect, mixed, false);
}

REGISTER_TYPED_TEST_CASE_P(recommender_random_test,
                           trivial, random, save_load, get_all_row_ids,
                           diff, mix);

typedef testing::Types<inverted_index, lsh, minhash, euclid_lsh> recommender_types;

INSTANTIATE_TYPED_TEST_CASE_P(rt, recommender_random_test, recommender_types);

}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <algorithm>                    /* for lower_bound */

#include "util/less.h"
#include "zorbaerrors/Assert.h"

#include "wn_types.h"

using namespace std;

namespace zorba {
namespace wordnet {

///////////////////////////////////////////////////////////////////////////////

namespace part_of_speech {
  type find( char pos ) {
    switch ( pos ) {
      case adjective:
      case adverb:
      case noun:
      case verb:
        return static_cast<type>( pos );
      default:
        return unknown;
    }
  }
} // namespace part_of_speech

///////////////////////////////////////////////////////////////////////////////

#define DEF_END(CHAR_ARRAY)                             \
  static char const *const *const end =                 \
    CHAR_ARRAY + sizeof( CHAR_ARRAY ) / sizeof( char* );

#define FIND(what) \
  static_cast<type>( find_index( string_of, end, what ) )

/**
 * A less-verbose way to use std::lower_bound.
 */
inline int find_index( char const *const *begin, char const *const *end,
                       char const *s ) {
  char const *const *const entry =
    ::lower_bound( begin, end, s, less<char const*>() );
  return entry != end && ::strcmp( s, *entry ) == 0 ? entry - begin : 0;
}

namespace pointer {

  char const *const string_of[] = {
    "#UNKNOWN",
    "also see",
    "antonym",
    "attribute",
    "cause",
    "derivationally related form",
    "derived from adjective",
    "domain of synset region",
    "domain of synset topic",
    "domain of synset usage",
    "entailment",
    "hypernym",
    "hyponym",
    "instance hypernym",
    "instance hyponym",
    "member holonym",
    "member meronym",
    "member of domain region",
    "member of domain topic",
    "member of domain usage",
    "part holonym",
    "part meronym",
    "participle of verb",
    "pertainym",
    "similar to",
    "substance holonym",
    "substance meronym",
    "verb group"
  };

  type find( char ptr_symbol ) {
    switch ( ptr_symbol ) {
      case 'A' /* !  */: return antonym;
      case 'a' /* =  */: return attribute;
      case 'C' /* >  */: return cause;
      case 'D' /* \  */: return derived_from_adjective;
      case 'E' /* @  */: return hypernym;
      case 'e' /* @i */: return instance_hypernym;
      case 'F' /* +  */: return derivationally_related_form;
      case 'G' /* $  */: return verb_group;
      case 'H' /* #m */: return member_holonym;
      case 'h' /* #p */: return part_holonym;
      case 'i' /* #s */: return substance_holonym;
      case 'L' /* *  */: return entailment;
      case 'M' /* %m */: return member_meronym;
      case 'm' /* %p */: return part_meronym;
      case 'n' /* %s */: return substance_meronym;
      case 'O' /* ~  */: return hyponym;
      case 'o' /* ~i */: return instance_hyponym;
      case 'P' /* \  */: return pertainym;
      case 'R' /* ;r */: return domain_of_synset_region;
      case 'r' /* -r */: return member_of_domain_region;
      case 'S' /* ^  */: return also_see;
      case 'T' /* ;c */: return domain_of_synset_topic;
      case 't' /* -c */: return member_of_domain_topic;
      case 'U' /* ;u */: return domain_of_synset_usage;
      case 'u' /* -u */: return member_of_domain_usage;
      case 'V' /* <  */: return participle_of_verb;
      case '~' /* &  */: return similar_to;
      default          : return unknown;
    }
  }

  type find( char const *relationship ) {
    DEF_END( string_of );
    return FIND( relationship );
  }

  type map_iso_rel( iso2788::rel_type iso_rel ) {
    using namespace iso2788;
    switch ( iso_rel ) {
      case BT : return hypernym;
      case BTG: return hypernym;
      case BTI: return instance_hypernym;
      case BTP: return part_meronym;
      case NT : return hyponym;
      case NTG: return hyponym;
      case NTI: return instance_hyponym;
      case NTP: return part_holonym;
      case RT : return also_see;
      case SN : return unknown;
      case TT : return hypernym;        // the best we can do
      case UF : return unknown;
      case USE: return unknown;
      // ensures all cases are handled
      default          : ZORBA_ASSERT( false );
    }
  }

} // namespace pointer

///////////////////////////////////////////////////////////////////////////////

} // namespace wordnet
} // namespace zorba

/* vim:set et sw=2 ts=2: */
<commit_msg>Cosmetic change.<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * 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 <algorithm>                    /* for lower_bound */

#include "util/less.h"
#include "zorbaerrors/Assert.h"

#include "wn_types.h"

using namespace std;

namespace zorba {
namespace wordnet {

///////////////////////////////////////////////////////////////////////////////

namespace part_of_speech {
  type find( char pos ) {
    switch ( pos ) {
      case adjective:
      case adverb:
      case noun:
      case verb:
        return static_cast<type>( pos );
      default:
        return unknown;
    }
  }
} // namespace part_of_speech

///////////////////////////////////////////////////////////////////////////////

#define DEF_END(CHAR_ARRAY)                             \
  static char const *const *const end =                 \
    CHAR_ARRAY + sizeof( CHAR_ARRAY ) / sizeof( char* );

#define FIND(what) \
  static_cast<type>( find_index( string_of, end, what ) )

/**
 * A less-verbose way to use std::lower_bound.
 */
inline int find_index( char const *const *begin, char const *const *end,
                       char const *s ) {
  char const *const *const entry =
    ::lower_bound( begin, end, s, less<char const*>() );
  return entry != end && ::strcmp( s, *entry ) == 0 ? entry - begin : 0;
}

namespace pointer {

  char const *const string_of[] = {
    "#UNKNOWN",
    "also see",
    "antonym",
    "attribute",
    "cause",
    "derivationally related form",
    "derived from adjective",
    "domain of synset region",
    "domain of synset topic",
    "domain of synset usage",
    "entailment",
    "hypernym",
    "hyponym",
    "instance hypernym",
    "instance hyponym",
    "member holonym",
    "member meronym",
    "member of domain region",
    "member of domain topic",
    "member of domain usage",
    "part holonym",
    "part meronym",
    "participle of verb",
    "pertainym",
    "similar to",
    "substance holonym",
    "substance meronym",
    "verb group"
  };

  type find( char ptr_symbol ) {
    switch ( ptr_symbol ) {
      case 'A' /* !  */: return antonym;
      case 'a' /* =  */: return attribute;
      case 'C' /* >  */: return cause;
      case 'D' /* \  */: return derived_from_adjective;
      case 'E' /* @  */: return hypernym;
      case 'e' /* @i */: return instance_hypernym;
      case 'F' /* +  */: return derivationally_related_form;
      case 'G' /* $  */: return verb_group;
      case 'H' /* #m */: return member_holonym;
      case 'h' /* #p */: return part_holonym;
      case 'i' /* #s */: return substance_holonym;
      case 'L' /* *  */: return entailment;
      case 'M' /* %m */: return member_meronym;
      case 'm' /* %p */: return part_meronym;
      case 'n' /* %s */: return substance_meronym;
      case 'O' /* ~  */: return hyponym;
      case 'o' /* ~i */: return instance_hyponym;
      case 'P' /* \  */: return pertainym;
      case 'R' /* ;r */: return domain_of_synset_region;
      case 'r' /* -r */: return member_of_domain_region;
      case 'S' /* ^  */: return also_see;
      case 'T' /* ;c */: return domain_of_synset_topic;
      case 't' /* -c */: return member_of_domain_topic;
      case 'U' /* ;u */: return domain_of_synset_usage;
      case 'u' /* -u */: return member_of_domain_usage;
      case 'V' /* <  */: return participle_of_verb;
      case '~' /* &  */: return similar_to;
      default          : return unknown;
    }
  }

  type find( char const *relationship ) {
    DEF_END( string_of );
    return FIND( relationship );
  }

  type map_iso_rel( iso2788::rel_type iso_rel ) {
    using namespace iso2788;
    switch ( iso_rel ) {
      case BT : return hypernym;
      case BTG: return hypernym;
      case BTI: return instance_hypernym;
      case BTP: return part_meronym;
      case NT : return hyponym;
      case NTG: return hyponym;
      case NTI: return instance_hyponym;
      case NTP: return part_holonym;
      case RT : return also_see;
      case SN : return unknown;
      case TT : return hypernym;        // the best we can do
      case UF : return unknown;
      case USE: return unknown;
      // ensures all cases are handled
      default : ZORBA_ASSERT( false );
    }
  }

} // namespace pointer

///////////////////////////////////////////////////////////////////////////////

} // namespace wordnet
} // namespace zorba

/* vim:set et sw=2 ts=2: */
<|endoftext|>


<commit_before>#include "OSMTileSource.h"

#include "guts/MapGraphicsNetwork.h"

#include <cmath>
#include <QPainter>
#include <QStringBuilder>
#include <QtDebug>
#include <QNetworkReply>

const qreal PI = 3.14159265358979323846;
const qreal deg2rad = PI / 180.0;
const qreal rad2deg = 180.0 / PI;

OSMTileSource::OSMTileSource(OSMTileType tileType) :
    MapTileSource(), _tileType(tileType)
{
}

OSMTileSource::~OSMTileSource()
{
    qDebug() << this << this->name() << "Destructing";
}

QPointF OSMTileSource::ll2qgs(const QPointF &ll, quint8 zoomLevel) const
{
    const qreal tilesOnOneEdge = pow(2.0,zoomLevel);
    const quint16 tileSize = this->tileSize();
    qreal x = (ll.x()+180) * (tilesOnOneEdge*tileSize)/360; // coord to pixel!
    qreal y = (1-(log(tan(PI/4+(ll.y()*deg2rad)/2)) /PI)) /2  * (tilesOnOneEdge*tileSize);

    return QPoint(int(x), int(y));
}

QPointF OSMTileSource::qgs2ll(const QPointF &qgs, quint8 zoomLevel) const
{
    const qreal tilesOnOneEdge = pow(2.0,zoomLevel);
    const quint16 tileSize = this->tileSize();
    qreal longitude = (qgs.x()*(360/(tilesOnOneEdge*tileSize)))-180;
    qreal latitude = rad2deg*(atan(sinh((1-qgs.y()*(2/(tilesOnOneEdge*tileSize)))*PI)));

    return QPointF(longitude, latitude);
}

quint64 OSMTileSource::tilesOnZoomLevel(quint8 zoomLevel) const
{
    return pow(4.0,zoomLevel);
}

quint16 OSMTileSource::tileSize() const
{
    return 256;
}

quint8 OSMTileSource::minZoomLevel(QPointF ll)
{
    Q_UNUSED(ll)
    return 0;
}

quint8 OSMTileSource::maxZoomLevel(QPointF ll)
{
    Q_UNUSED(ll)
    return 18;
}

QString OSMTileSource::name() const
{
    switch(_tileType)
    {
    case OSMTiles:
        return "OpenStreetMap Tiles";
        break;

    case MapQuestOSMTiles:
        return "MapQuestOSM Tiles";
        break;

    case MapQuestAerialTiles:
        return "MapQuest Aerial Tiles";
        break;

    default:
        return "Unknown Tiles";
        break;
    }
}

QString OSMTileSource::tileFileExtension() const
{
    if (_tileType == OSMTiles || _tileType == MapQuestOSMTiles)
        return "png";
    else
        return "jpg";
}

//protected
void OSMTileSource::fetchTile(quint32 x, quint32 y, quint8 z)
{
    MapGraphicsNetwork * network = MapGraphicsNetwork::getInstance();

    QString host;
    QString url;

    //Figure out which server to request from based on our desired tile type
    if (_tileType == OSMTiles)
    {
        host = "http://b.tile.openstreetmap.org";
        url = "/%1/%2/%3.png";
    }
    else if (_tileType == MapQuestOSMTiles)
    {
        host = "http://otile1.mqcdn.com";
        url = "/tiles/1.0.0/osm/%1/%2/%3.jpg";
    }
    else
    {
        host = "http://oatile1.mqcdn.com";
        url = "/tiles/1.0.0/sat/%1/%2/%3.jpg";
    }

    //Use the unique cacheID to see if this tile has already been requested
    const QString cacheID = this->createCacheID(x,y,z);
    if (_pendingRequests.contains(cacheID))
        return;
    _pendingRequests.insert(cacheID);

    //Build the request
    const QString fetchURL = url.arg(QString::number(z),
                                     QString::number(x),
                                     QString::number(y));
    QNetworkRequest request(QUrl(host + fetchURL));

    //Send the request and setupd a signal to ensure we're notified when it finishes
    QNetworkReply * reply = network->get(request);
    _pendingReplies.insert(reply,cacheID);

    connect(reply,
            SIGNAL(finished()),
            this,
            SLOT(handleNetworkRequestFinished()));
}

//private slot
void OSMTileSource::handleNetworkRequestFinished()
{
    QObject * sender = QObject::sender();
    QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender);

    if (reply == 0)
    {
        qWarning() << "QNetworkReply cast failure";
        return;
    }

    /*
      We can do this here and use reply later in the function because the reply
      won't be deleted until execution returns to the event loop.
    */
    reply->deleteLater();

    if (!_pendingReplies.contains(reply))
    {
        qWarning() << "Unknown QNetworkReply";
        return;
    }

    //get the cacheID
    const QString cacheID = _pendingReplies.take(reply);
    _pendingRequests.remove(cacheID);

    //If there was a network error, ignore the reply
    if (reply->error() != QNetworkReply::NoError)
    {
        qDebug() << "Network Error:" << reply->errorString();
        return;
    }

    //Convert the cacheID back into x,y,z tile coordinates
    quint32 x,y,z;
    if (!MapTileSource::cacheID2xyz(cacheID,&x,&y,&z))
    {
        qWarning() << "Failed to convert cacheID" << cacheID << "back to xyz";
        return;
    }

    QByteArray bytes = reply->readAll();
    QImage * image = new QImage();

    if (!image->loadFromData(bytes))
    {
        delete image;
        qWarning() << "Failed to make QImage from network bytes";
        return;
    }

    //Notify client of tile retrieval
    this->prepareRetrievedTile(x,y,z,image);
}
<commit_msg>Updated MapQuest sat URL to new one<commit_after>#include "OSMTileSource.h"

#include "guts/MapGraphicsNetwork.h"

#include <cmath>
#include <QPainter>
#include <QStringBuilder>
#include <QtDebug>
#include <QNetworkReply>

const qreal PI = 3.14159265358979323846;
const qreal deg2rad = PI / 180.0;
const qreal rad2deg = 180.0 / PI;

OSMTileSource::OSMTileSource(OSMTileType tileType) :
    MapTileSource(), _tileType(tileType)
{
}

OSMTileSource::~OSMTileSource()
{
    qDebug() << this << this->name() << "Destructing";
}

QPointF OSMTileSource::ll2qgs(const QPointF &ll, quint8 zoomLevel) const
{
    const qreal tilesOnOneEdge = pow(2.0,zoomLevel);
    const quint16 tileSize = this->tileSize();
    qreal x = (ll.x()+180) * (tilesOnOneEdge*tileSize)/360; // coord to pixel!
    qreal y = (1-(log(tan(PI/4+(ll.y()*deg2rad)/2)) /PI)) /2  * (tilesOnOneEdge*tileSize);

    return QPoint(int(x), int(y));
}

QPointF OSMTileSource::qgs2ll(const QPointF &qgs, quint8 zoomLevel) const
{
    const qreal tilesOnOneEdge = pow(2.0,zoomLevel);
    const quint16 tileSize = this->tileSize();
    qreal longitude = (qgs.x()*(360/(tilesOnOneEdge*tileSize)))-180;
    qreal latitude = rad2deg*(atan(sinh((1-qgs.y()*(2/(tilesOnOneEdge*tileSize)))*PI)));

    return QPointF(longitude, latitude);
}

quint64 OSMTileSource::tilesOnZoomLevel(quint8 zoomLevel) const
{
    return pow(4.0,zoomLevel);
}

quint16 OSMTileSource::tileSize() const
{
    return 256;
}

quint8 OSMTileSource::minZoomLevel(QPointF ll)
{
    Q_UNUSED(ll)
    return 0;
}

quint8 OSMTileSource::maxZoomLevel(QPointF ll)
{
    Q_UNUSED(ll)
    return 18;
}

QString OSMTileSource::name() const
{
    switch(_tileType)
    {
    case OSMTiles:
        return "OpenStreetMap Tiles";
        break;

    case MapQuestOSMTiles:
        return "MapQuestOSM Tiles";
        break;

    case MapQuestAerialTiles:
        return "MapQuest Aerial Tiles";
        break;

    default:
        return "Unknown Tiles";
        break;
    }
}

QString OSMTileSource::tileFileExtension() const
{
    if (_tileType == OSMTiles || _tileType == MapQuestOSMTiles)
        return "png";
    else
        return "jpg";
}

//protected
void OSMTileSource::fetchTile(quint32 x, quint32 y, quint8 z)
{
    MapGraphicsNetwork * network = MapGraphicsNetwork::getInstance();

    QString host;
    QString url;

    //Figure out which server to request from based on our desired tile type
    if (_tileType == OSMTiles)
    {
        host = "http://b.tile.openstreetmap.org";
        url = "/%1/%2/%3.png";
    }
    else if (_tileType == MapQuestOSMTiles)
    {
        host = "http://otile1.mqcdn.com";
        url = "/tiles/1.0.0/osm/%1/%2/%3.jpg";
    }
    else
    {
        host = "http://otile1.mqcdn.com";
        url = "/tiles/1.0.0/sat/%1/%2/%3.jpg";
    }

    //Use the unique cacheID to see if this tile has already been requested
    const QString cacheID = this->createCacheID(x,y,z);
    if (_pendingRequests.contains(cacheID))
        return;
    _pendingRequests.insert(cacheID);

    //Build the request
    const QString fetchURL = url.arg(QString::number(z),
                                     QString::number(x),
                                     QString::number(y));
    QNetworkRequest request(QUrl(host + fetchURL));

    //Send the request and setupd a signal to ensure we're notified when it finishes
    QNetworkReply * reply = network->get(request);
    _pendingReplies.insert(reply,cacheID);

    connect(reply,
            SIGNAL(finished()),
            this,
            SLOT(handleNetworkRequestFinished()));
}

//private slot
void OSMTileSource::handleNetworkRequestFinished()
{
    QObject * sender = QObject::sender();
    QNetworkReply * reply = qobject_cast<QNetworkReply *>(sender);

    if (reply == 0)
    {
        qWarning() << "QNetworkReply cast failure";
        return;
    }

    /*
      We can do this here and use reply later in the function because the reply
      won't be deleted until execution returns to the event loop.
    */
    reply->deleteLater();

    if (!_pendingReplies.contains(reply))
    {
        qWarning() << "Unknown QNetworkReply";
        return;
    }

    //get the cacheID
    const QString cacheID = _pendingReplies.take(reply);
    _pendingRequests.remove(cacheID);

    //If there was a network error, ignore the reply
    if (reply->error() != QNetworkReply::NoError)
    {
        qDebug() << "Network Error:" << reply->errorString();
        return;
    }

    //Convert the cacheID back into x,y,z tile coordinates
    quint32 x,y,z;
    if (!MapTileSource::cacheID2xyz(cacheID,&x,&y,&z))
    {
        qWarning() << "Failed to convert cacheID" << cacheID << "back to xyz";
        return;
    }

    QByteArray bytes = reply->readAll();
    QImage * image = new QImage();

    if (!image->loadFromData(bytes))
    {
        delete image;
        qWarning() << "Failed to make QImage from network bytes";
        return;
    }

    //Notify client of tile retrieval
    this->prepareRetrievedTile(x,y,z,image);
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    MetaImageReadWrite.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <iostream>

#include <itkImage.h>
#include <itkImageFileWriter.h>
#include <itkImageFileReader.h>
#include <itkMetaImageIO.h>

#include <itkImageRegionIterator.h>

int main(int argc, char **argv)
  {
  // Declare the image
  typedef itk::Image<short, 3> ImageType;

  ImageType::SizeType imSize = {{256, 256, 10}};
  ImageType::Pointer im = ImageType::New();
  im->SetRegions(imSize);
  im->Allocate();

  // Set some values in the image
  itk::ImageRegionIterator< ImageType > it(im,
        im->GetLargestPossibleRegion());

  it.GoToBegin();
  int c = 0;
  while(!it.IsAtEnd())
    {
    it.Set( c++/1000 );
    ++it;
    }

  // Declare a Writer
  typedef itk::ImageFileWriter< ImageType > VolumeWriterType;
  VolumeWriterType::Pointer writer = VolumeWriterType::New();

  // Add the MetaImage format to the writer
  itk::MetaImageIO::Pointer metaWriter = itk::MetaImageIO::New();
  writer->SetImageIO( metaWriter );

  // Uncomment the next line to write the data to one file.
  // metaWriter->SetDataFileName( "LOCAL" );

  // Set the filename
  writer->SetFileName( "test.mhd" );

  // Set the image to write
  writer->SetInput( im );

  //   Update function.   Writers are the exception to that rule
  writer->Update();

  // Make sure the image in memory hasn't been corrupted by writing
  it.GoToBegin();
  c = 0;
  while(!it.IsAtEnd())
    {
    if(it.Get() != c++/1000)
      {
      std::cout << "Memory is " << it.Get()
                << " expected " << c++/1000 << std::endl;
      }
    ++it;
    }

  // Declare a reader
  typedef itk::ImageFileReader< ImageType > VolumeReaderType;
  VolumeReaderType::Pointer reader = VolumeReaderType::New();

  // Set the name of the file to read
  reader->SetFileName( "test.mhd" );

  // Set the image into which the results should be stored
  ImageType::Pointer imOut;
  imOut = reader->GetOutput();

  // See if the file can be read - "try" otherwise program will
  //   mysteriously exit on failure in the Object factory
  try
    {
    reader->Update();
    }
  catch( ... )
    {
    std::cout << "Problems reading file format" << std::endl;
    return 1;
    }

  // See if the data read is valid
  itk::ImageRegionIterator< ImageType > itOut(imOut,
        imOut->GetLargestPossibleRegion());

  it.GoToBegin();
  itOut.GoToBegin();
  while(!it.IsAtEnd())
    {
    if(it.Get() != itOut.Get())
      {
      std::cout << "Read " << itOut.Get()
                << " expected " << it.Get() << std::endl;
      }
    ++it;
    ++itOut;
    }

  return 1;
  }
<commit_msg>ENH: Fixed a warning - argc/v never used<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    MetaImageReadWrite.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include <iostream>

#include <itkImage.h>
#include <itkImageFileWriter.h>
#include <itkImageFileReader.h>
#include <itkMetaImageIO.h>

#include <itkImageRegionIterator.h>

int main()
  {
  // Declare the image
  typedef itk::Image<short, 3> ImageType;

  ImageType::SizeType imSize = {{256, 256, 10}};
  ImageType::Pointer im = ImageType::New();
  im->SetRegions(imSize);
  im->Allocate();

  // Set some values in the image
  itk::ImageRegionIterator< ImageType > it(im,
        im->GetLargestPossibleRegion());

  it.GoToBegin();
  int c = 0;
  while(!it.IsAtEnd())
    {
    it.Set( c++/1000 );
    ++it;
    }

  // Declare a Writer
  typedef itk::ImageFileWriter< ImageType > VolumeWriterType;
  VolumeWriterType::Pointer writer = VolumeWriterType::New();

  // Add the MetaImage format to the writer
  itk::MetaImageIO::Pointer metaWriter = itk::MetaImageIO::New();
  writer->SetImageIO( metaWriter );

  // Uncomment the next line to write the data to one file.
  // metaWriter->SetDataFileName( "LOCAL" );

  // Set the filename
  writer->SetFileName( "test.mhd" );

  // Set the image to write
  writer->SetInput( im );

  //   Update function.   Writers are the exception to that rule
  writer->Update();

  // Make sure the image in memory hasn't been corrupted by writing
  it.GoToBegin();
  c = 0;
  while(!it.IsAtEnd())
    {
    if(it.Get() != c++/1000)
      {
      std::cout << "Memory is " << it.Get()
                << " expected " << c++/1000 << std::endl;
      }
    ++it;
    }

  // Declare a reader
  typedef itk::ImageFileReader< ImageType > VolumeReaderType;
  VolumeReaderType::Pointer reader = VolumeReaderType::New();

  // Set the name of the file to read
  reader->SetFileName( "test.mhd" );

  // Set the image into which the results should be stored
  ImageType::Pointer imOut;
  imOut = reader->GetOutput();

  // See if the file can be read - "try" otherwise program will
  //   mysteriously exit on failure in the Object factory
  try
    {
    reader->Update();
    }
  catch( ... )
    {
    std::cout << "Problems reading file format" << std::endl;
    return 1;
    }

  // See if the data read is valid
  itk::ImageRegionIterator< ImageType > itOut(imOut,
        imOut->GetLargestPossibleRegion());

  it.GoToBegin();
  itOut.GoToBegin();
  while(!it.IsAtEnd())
    {
    if(it.Get() != itOut.Get())
      {
      std::cout << "Read " << itOut.Get()
                << " expected " << it.Get() << std::endl;
      }
    ++it;
    ++itOut;
    }

  return 1;
  }
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads

// <mutex>

// class mutex;

// void lock();

#include <mutex>
#include <thread>
#include <cstdlib>
#include <cassert>

#include <iostream>

std::mutex m;

typedef std::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
typedef std::chrono::milliseconds ms;
typedef std::chrono::nanoseconds ns;

void f()
{
    time_point t0 = Clock::now();
    m.lock();
    time_point t1 = Clock::now();
    m.unlock();
    ns d = t1 - t0 - ms(250);
    assert(d < ms(50));  // within 50ms
}

int main()
{
    m.lock();
    std::thread t(f);
    std::this_thread::sleep_for(ms(250));
    m.unlock();
    t.join();
}
<commit_msg>Mark another test as flaky<commit_after>//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: libcpp-has-no-threads

// FLAKY_TEST.

// <mutex>

// class mutex;

// void lock();

#include <mutex>
#include <thread>
#include <cstdlib>
#include <cassert>

#include <iostream>

std::mutex m;

typedef std::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
typedef std::chrono::milliseconds ms;
typedef std::chrono::nanoseconds ns;

void f()
{
    time_point t0 = Clock::now();
    m.lock();
    time_point t1 = Clock::now();
    m.unlock();
    ns d = t1 - t0 - ms(250);
    assert(d < ms(50));  // within 50ms
}

int main()
{
    m.lock();
    std::thread t(f);
    std::this_thread::sleep_for(ms(250));
    m.unlock();
    t.join();
}
<|endoftext|>


<commit_before>/**
 * \file Library.cpp
 * \author Matt Hammerly
 */

#include <string>
#include <iostream>
#include "Library.h"

/**
 * \brief Default constructor
 *
 * Todo: sanitize the db credentials I guess lol
 */
CLibrary::CLibrary()
{
    char connectionString[512];
    snprintf(connectionString, 512, "dbname=%s host=%s user=%s password=%s",
             DBNAME, DBHOST, DBUSER, DBPW);

    mConnection = PQconnectdb(connectionString);

    if (PQstatus(mConnection) == CONNECTION_BAD)
    {
        std::cout << "Failed to connect to the database" << std::endl;
        exit(0);
    }
}

/**
 * \brief Destructor
 *
 * Will close the database connection before exiting
 */
CLibrary::~CLibrary()
{
    PQfinish(mConnection);
}

/**
 * \brief Create the database tables for this application
 *
 * \returns -1 if something goes wrong
 *
 * Todo: Write database schema in this comment
 *       `create trigger IF NOT EXISTS` or similar
 */
int CLibrary::PrepareDatabase()
{
    PGresult *res;
    res = PQexec(mConnection,
            "CREATE TABLE IF NOT EXISTS tracks (\
                id SERIAL NOT NULL PRIMARY KEY,\
                filepath TEXT NOT NULL,\
                date_added TIMESTAMPTZ NOT NULL DEFAULT NOW()\
          )");
    PQclear(res);

    res = PQexec(mConnection,
            "CREATE TABLE IF NOT EXISTS playlists (\
                id SERIAL NOT NULL PRIMARY KEY,\
                title TEXT NOT NULL,\
                length INTEGER NOT NULL DEFAULT 0\
          )");
    PQclear(res);

    res = PQexec(mConnection,
            "CREATE TABLE IF NOT EXISTS tracks_playlists (\
                id SERIAL NOT NULL PRIMARY KEY,\
                track_id INTEGER NOT NULL,\
                playlist_id INTEGER NOT NULL,\
                position FLOAT NOT NULL\
          )");
    PQclear(res);

    // Create a function to adjust the length of a playlist
    res = PQexec(mConnection,
            "CREATE OR REPLACE FUNCTION tracks_playlists_insert_func() RETURNS TRIGGER\
            LANGUAGE plpgsql\
            AS $tracks_playlists_insert_func$\
            DECLARE\
                pid INTEGER;\
            BEGIN\
                pid=0;\
                IF (TG_OP = 'INSERT') THEN pid = NEW.playlist_id;\
                ELSIF (TG_OP = 'DELETE') THEN pid = OLD.playlist_id;\
                END IF;\
                WITH Sub AS (SELECT COUNT(id) AS c FROM tracks_playlists WHERE playlist_id = pid)\
                    UPDATE playlists AS Main SET length = Sub.c FROM Sub WHERE Main.id = pid AND 1=1;\
                RETURN NULL;\
            END;\
            $tracks_playlists_insert_func$;");
    PQclear(res);

    // Create a trigger to adjust the length of a playlist on each insert or delete
    res = PQexec(mConnection,
            "CREATE TRIGGER tracks_playlists_insert_trg\
            AFTER INSERT OR DELETE ON tracks_playlists\
            FOR EACH ROW EXECUTE PROCEDURE tracks_playlists_insert_func();");
    PQclear(res);

    return 0;
}

/**
 * \brief Destroy all database objects used in this application
 *
 * \returns -1 if something goes wrong? I don't know what or why, frankly.
 */
int CLibrary::DestroyDatabase()
{
    PGresult *res;
    res = PQexec(mConnection, "DROP TRIGGER IF EXISTS tracks_playlists_insert_trg ON tracks_playlists;");
    PQclear(res);

    res = PQexec(mConnection, "DROP FUNCTION IF EXISTS tracks_playlists_insert_func() CASCADE;");
    PQclear(res);

    res = PQexec(mConnection, "DROP TABLE IF EXISTS tracks;");
    PQclear(res);

    res = PQexec(mConnection, "DROP TABLE IF EXISTS playlists;");
    PQclear(res);

    res = PQexec(mConnection, "DROP TABLE IF EXISTS tracks_playlists;");
    PQclear(res);

    return 0;
}

/**
 * \brief Exposes the database connection status
 * \returns PostgreSQL connection status object
 *
 * Just in case.
 */
ConnStatusType CLibrary::GetStatus()
{
    return PQstatus(mConnection);
}

/**
 * \brief Returns a pointer to the connection object
 *
 * It makes tests easier. Might make this protected and
 * require a testing subclass to use this later, whatever.
 */
PGconn* CLibrary::GetConnection()
{
    return mConnection;
}

/**
 * \brief Add a track to the database
 * \param filepath The filepath of the file to be added
 * \returns The ID of the new track (as a string)
 */
std::string CLibrary::AddTrack(std::string filepath)
{
    std::string query = "INSERT INTO tracks (filepath) VALUES (";

    // Safety first
    char *escaped_filepath = PQescapeLiteral(mConnection, filepath.c_str(), filepath.length());
    query.append(escaped_filepath);
    PQfreemem(escaped_filepath);

    query.append(") RETURNING id");

    PGresult *res = PQexec(mConnection, query.c_str());
    char *id = PQgetvalue(res, 0, 0);

    // Create an std::string to return so we can appropriately free the PGresult
    std::string std_id(id);
    PQclear(res);

    return std_id;
}

/**
 * \brief Add a playlist to the database
 * \param title The title of the playlist to be added
 * \returns The ID of the new playlist (as a string)
 */
std::string CLibrary::AddPlaylist(std::string title)
{
    std::string query = "INSERT INTO playlists (title) VALUES (";

    // Safety first
    char *escaped_title = PQescapeLiteral(mConnection, title.c_str(), title.length());
    query.append(escaped_title);
    PQfreemem(escaped_title);

    query.append(") RETURNING id");

    PGresult *res = PQexec(mConnection, query.c_str());
    char *id = PQgetvalue(res, 0, 0);

    // Create an std::string to return so we can appropriately free the PGresult
    std::string std_id(id);
    PQclear(res);

    return std_id;
}

/**
 * \brief Removes a track from the database, and all records of the track's playlist membership
 * \param id ID of the track to be deleted
 * \returns ID of the deleted track
 */
std::string CLibrary::RemoveTrack(std::string id)
{
    std::string query = "DELETE FROM tracks WHERE id=";

    char escaped_id[30];
    PQescapeStringConn(mConnection, escaped_id, id.c_str(), 30, 0);
    query.append(escaped_id);
    query.append("; DELETE FROM tracks_playlists WHERE track_id=");
    query.append(escaped_id);

    PGresult *res = PQexec(mConnection, query.c_str());
    PQclear(res);

    return id;
}

/**
 * \brief Removes a playlist from the database, and all records of membership in the playlist
 * \param id ID of the playlist to be deleted
 * \returns ID of the deleted playlist
 */
std::string CLibrary::RemovePlaylist(std::string id)
{
    std::string query = "DELETE FROM tracks WHERE id=";

    char escaped_id[30];
    PQescapeStringConn(mConnection, escaped_id, id.c_str(), 30, 0);
    query.append(escaped_id);
    query.append("; DELETE FROM tracks_playlists WHERE playlist_id=");
    query.append(escaped_id);

    PGresult *res = PQexec(mConnection, query.c_str());
    PQclear(res);

    return id;
}
<commit_msg>create a default library playlist<commit_after>/**
 * \file Library.cpp
 * \author Matt Hammerly
 */

#include <string>
#include <iostream>
#include "Library.h"

/**
 * \brief Default constructor
 *
 * Todo: sanitize the db credentials I guess lol
 */
CLibrary::CLibrary()
{
    char connectionString[512];
    snprintf(connectionString, 512, "dbname=%s host=%s user=%s password=%s",
             DBNAME, DBHOST, DBUSER, DBPW);

    mConnection = PQconnectdb(connectionString);

    if (PQstatus(mConnection) == CONNECTION_BAD)
    {
        std::cout << "Failed to connect to the database" << std::endl;
        exit(0);
    }
}

/**
 * \brief Destructor
 *
 * Will close the database connection before exiting
 */
CLibrary::~CLibrary()
{
    PQfinish(mConnection);
}

/**
 * \brief Create the database tables for this application
 *
 * \returns -1 if something goes wrong
 *
 * Todo: Write database schema in this comment
 *       `create trigger IF NOT EXISTS` or similar
 */
int CLibrary::PrepareDatabase()
{
    PGresult *res;
    res = PQexec(mConnection,
            "CREATE TABLE IF NOT EXISTS tracks (\
                id SERIAL NOT NULL PRIMARY KEY,\
                filepath TEXT NOT NULL,\
                date_added TIMESTAMPTZ NOT NULL DEFAULT NOW()\
          )");
    PQclear(res);

    res = PQexec(mConnection,
            "CREATE TABLE IF NOT EXISTS playlists (\
                id SERIAL NOT NULL PRIMARY KEY,\
                title TEXT NOT NULL,\
                length INTEGER NOT NULL DEFAULT 0\
          )");
    PQclear(res);

    res = PQexec(mConnection,
            "CREATE TABLE IF NOT EXISTS tracks_playlists (\
                id SERIAL NOT NULL PRIMARY KEY,\
                track_id INTEGER NOT NULL,\
                playlist_id INTEGER NOT NULL,\
                position FLOAT NOT NULL\
          )");
    PQclear(res);

    // Create a function to adjust the length of a playlist
    res = PQexec(mConnection,
            "CREATE OR REPLACE FUNCTION tracks_playlists_insert_func() RETURNS TRIGGER\
            LANGUAGE plpgsql\
            AS $tracks_playlists_insert_func$\
            DECLARE\
                pid INTEGER;\
            BEGIN\
                pid=0;\
                IF (TG_OP = 'INSERT') THEN pid = NEW.playlist_id;\
                ELSIF (TG_OP = 'DELETE') THEN pid = OLD.playlist_id;\
                END IF;\
                WITH Sub AS (SELECT COUNT(id) AS c FROM tracks_playlists WHERE playlist_id = pid)\
                    UPDATE playlists AS Main SET length = Sub.c FROM Sub WHERE Main.id = pid AND 1=1;\
                RETURN NULL;\
            END;\
            $tracks_playlists_insert_func$;");
    PQclear(res);

    // Create a trigger to adjust the length of a playlist on each insert or delete
    res = PQexec(mConnection,
            "CREATE TRIGGER tracks_playlists_insert_trg\
            AFTER INSERT OR DELETE ON tracks_playlists\
            FOR EACH ROW EXECUTE PROCEDURE tracks_playlists_insert_func();");
    PQclear(res);

    // Create a default playlist for all songs to be added to
    res = PQexec(mConnection, "INSERT INTO playlists (title) VALUES ('library')");
    PQclear(res);

    return 0;
}

/**
 * \brief Destroy all database objects used in this application
 *
 * \returns -1 if something goes wrong? I don't know what or why, frankly.
 */
int CLibrary::DestroyDatabase()
{
    PGresult *res;
    res = PQexec(mConnection, "DROP TRIGGER IF EXISTS tracks_playlists_insert_trg ON tracks_playlists;");
    PQclear(res);

    res = PQexec(mConnection, "DROP FUNCTION IF EXISTS tracks_playlists_insert_func() CASCADE;");
    PQclear(res);

    res = PQexec(mConnection, "DROP TABLE IF EXISTS tracks;");
    PQclear(res);

    res = PQexec(mConnection, "DROP TABLE IF EXISTS playlists;");
    PQclear(res);

    res = PQexec(mConnection, "DROP TABLE IF EXISTS tracks_playlists;");
    PQclear(res);

    return 0;
}

/**
 * \brief Exposes the database connection status
 * \returns PostgreSQL connection status object
 *
 * Just in case.
 */
ConnStatusType CLibrary::GetStatus()
{
    return PQstatus(mConnection);
}

/**
 * \brief Returns a pointer to the connection object
 *
 * It makes tests easier. Might make this protected and
 * require a testing subclass to use this later, whatever.
 */
PGconn* CLibrary::GetConnection()
{
    return mConnection;
}

/**
 * \brief Add a track to the database
 * \param filepath The filepath of the file to be added
 * \returns The ID of the new track (as a string)
 */
std::string CLibrary::AddTrack(std::string filepath)
{
    std::string query = "INSERT INTO tracks (filepath) VALUES (";

    // Safety first
    char *escaped_filepath = PQescapeLiteral(mConnection, filepath.c_str(), filepath.length());
    query.append(escaped_filepath);
    PQfreemem(escaped_filepath);

    query.append(") RETURNING id");

    PGresult *res = PQexec(mConnection, query.c_str());
    char *id = PQgetvalue(res, 0, 0);

    // Create an std::string to return so we can appropriately free the PGresult
    std::string std_id(id);
    PQclear(res);

    return std_id;
}

/**
 * \brief Add a playlist to the database
 * \param title The title of the playlist to be added
 * \returns The ID of the new playlist (as a string)
 */
std::string CLibrary::AddPlaylist(std::string title)
{
    std::string query = "INSERT INTO playlists (title) VALUES (";

    // Safety first
    char *escaped_title = PQescapeLiteral(mConnection, title.c_str(), title.length());
    query.append(escaped_title);
    PQfreemem(escaped_title);

    query.append(") RETURNING id");

    PGresult *res = PQexec(mConnection, query.c_str());
    char *id = PQgetvalue(res, 0, 0);

    // Create an std::string to return so we can appropriately free the PGresult
    std::string std_id(id);
    PQclear(res);

    return std_id;
}

/**
 * \brief Removes a track from the database, and all records of the track's playlist membership
 * \param id ID of the track to be deleted
 * \returns ID of the deleted track
 */
std::string CLibrary::RemoveTrack(std::string id)
{
    std::string query = "DELETE FROM tracks WHERE id=";

    char escaped_id[30];
    PQescapeStringConn(mConnection, escaped_id, id.c_str(), 30, 0);
    query.append(escaped_id);
    query.append("; DELETE FROM tracks_playlists WHERE track_id=");
    query.append(escaped_id);

    PGresult *res = PQexec(mConnection, query.c_str());
    PQclear(res);

    return id;
}

/**
 * \brief Removes a playlist from the database, and all records of membership in the playlist
 * \param id ID of the playlist to be deleted
 * \returns ID of the deleted playlist
 */
std::string CLibrary::RemovePlaylist(std::string id)
{
    std::string query = "DELETE FROM tracks WHERE id=";

    char escaped_id[30];
    PQescapeStringConn(mConnection, escaped_id, id.c_str(), 30, 0);
    query.append(escaped_id);
    query.append("; DELETE FROM tracks_playlists WHERE playlist_id=");
    query.append(escaped_id);

    PGresult *res = PQexec(mConnection, query.c_str());
    PQclear(res);

    return id;
}
<|endoftext|>


<commit_before>/*
 * Manager.cpp
 *
 *  Created on: Mar 25, 2014
 *      Author: user
 */

#include "Manager.h"

Manager::Manager(Robot* robot, Plan* plan)
{
	_robot = robot;
	_plan = plan;
	_currentBehavior = plan->startBehavior();
	_running = false;
}

void Manager::run()
{
	_running = true;
	_robot->refresh();

	if (_currentBehavior->startCondition() == false)
	{
		_currentBehavior = _currentBehavior->getNextBehavior();

		// If there are no more behaviors
		if (!_currentBehavior)
		{
			return;
		}
	}

	double previewsX = 0;
	double previewsY = 0;
	double previewsYaw = 0;

	int runNum=0;
	while (_running)
	{
		_robot->refresh();

		// ------------
		// Calculate deltas

		double deltaX = _robot->getX() - previewsX;
		double deltaY = _robot->getY() - previewsY;
		double deltaYaw = _robot->getYaw() - previewsYaw;

		if (_currentBehavior->stopCondition())
		{
			_currentBehavior = _currentBehavior->getNextBehavior();

			// If there are no more behaviors
			if (!_currentBehavior)
			{
				return;
			}
		}

		_currentBehavior->action();

		Laser& laser = _robot->getLaser();
		Map& map = _slamManager.update(deltaX, deltaY, deltaYaw, laser);
		// ------------
		// Save this iteration x, y ,yaw

		previewsX = _robot->getX();
		previewsY = _robot->getY();
		previewsYaw = _robot->getYaw();

		// -----------
		// Print the map
		if (runNum % 3 == 0)
		{
			cout << map << endl;
		}
		runNum++;
	}

}

Manager::~Manager()
{
}
<commit_msg>fail to commit from the trunk :(<commit_after>/*
 * Manager.cpp
 *
 *  Created on: Mar 25, 2014
 *      Author: user
 */

#include "Manager.h"

Manager::Manager(Robot* robot, Plan* plan)
{
	_robot = robot;
	_plan = plan;
	_currentBehavior = plan->startBehavior();
	_running = false;
}

void Manager::run()
{
	_running = true;
	_robot->refresh();

	if (_currentBehavior->startCondition() == false)
	{
		_currentBehavior = _currentBehavior->getNextBehavior();

		// If there are no more behaviors
		if (!_currentBehavior)
		{
			std::cout << "The robot fail to start! there isn't any legal step! Please take the robot to other position" << std::endl;
			return;
		}
	}

	double previewsX = 0;
	double previewsY = 0;
	double previewsYaw = 0;

	int runNum=0;
	while (_running)
	{
		_robot->refresh();

		// ------------
		// Calculate deltas

		double deltaX = _robot->getX() - previewsX;
		double deltaY = _robot->getY() - previewsY;
		double deltaYaw = _robot->getYaw() - previewsYaw;

		if (_currentBehavior->stopCondition())
		{
			_currentBehavior = _currentBehavior->getNextBehavior();

			// If there are no more behaviors
			if (!_currentBehavior)
			{
				std::cout << "Can't move! there isn't any legal step!" << std::endl;
				return;
			}
		}

		// ------------
		// Save this iteration x, y ,yaw
		previewsX = _robot->getX();
		previewsY = _robot->getY();
		previewsYaw = _robot->getYaw();

		_currentBehavior->action();

		Laser& laser = _robot->getLaser();
		Map& map = _slamManager.update(deltaX, deltaY, deltaYaw, laser);

		// -----------
		// Print the map
		if (runNum % 3 == 0)
		{
			cout << map << endl;

		}

		runNum++;
	}

}

Manager::~Manager()
{
}
<|endoftext|>


<commit_before>#include <iostream>
#include "localSearch.h"

using namespace std;

int main(int argc, char* argv[])
{
	char filename[1024];
	sscanf(argv[1], "%s", filename);

	int seed;
	sscanf(argv[2], "%d", &seed);
	srand(seed);

	int time_limit;
	sscanf(argv[3], "%d", &time_limit);

	StochasticLocalSearch mySLS(filename, time_limit);

	mySLS.clique_sls();

	mySLS.show_results();

	return 0;
}
<commit_msg>Delete LMY-GRS.cpp<commit_after><|endoftext|>


<commit_before>#include "LPD8806.h"
#include "SPI.h"
#include "pins_arduino.h"
#include "wiring_private.h"

//Example to control LPD8806-based RGB LED Strips
// (c) Adafruit industries
// MIT license

/*****************************************************************************/

// Test code for using hardware SPI
LPD8806::LPD8806(uint16_t n) {
  // use hardware SPI!
  dataPin = clockPin = 0;
  hardwareSPI = true;

  numLEDs = n;
  // malloc 3 bytes per pixel so we dont have to hardcode the length
  pixels = (uint8_t *)malloc(numLEDs * 3); // 3 bytes per pixel
  memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state
}

LPD8806::LPD8806(uint16_t n, uint8_t dpin, uint8_t cpin) {
  dataPin = dpin;
  clockPin = cpin;

  numLEDs = n;

  clkportreg = portOutputRegister(digitalPinToPort(cpin));
  clkpin = digitalPinToBitMask(cpin);
  mosiportreg = portOutputRegister(digitalPinToPort(dpin));
  mosipin = digitalPinToBitMask(dpin);

  // malloc 3 bytes per pixel so we dont have to hardcode the length
  pixels = (uint8_t *)malloc(numLEDs * 3); // 3 bytes per pixel
  memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state
}

void LPD8806::begin(void) {
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

  if (hardwareSPI) {
    // using hardware SPI
    SPI.begin();
    // run the SPI bus as fast as possible
    // this has been tested on a 16MHz Arduino Uno
    SPI.setClockDivider(SPI_CLOCK_DIV2);
  }

  // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs)
  writezeros(3 * ((numLEDs + 63) / 64));
}

uint16_t LPD8806::numPixels(void) {
  return numLEDs;
}

uint32_t LPD8806::Color(byte r, byte g, byte b)
{
  //Take the lowest 7 bits of each value and append them end to end
  // We have the top bit set high (its a 'parity-like' bit in the protocol
  // and must be set!)

  uint32_t x;
  x = g | 0x80;
  x <<= 8;
  x |= r | 0x80;
  x <<= 8;
  x |= b | 0x80;

  return(x);
}

// Basic, push SPI data out
inline void LPD8806::write8(uint8_t d) {

  // this is the 'least efficient' way (28ms per 32-LED write)
  // shiftOut(dataPin, clockPin, MSBFIRST, d);

  // this is the faster pin-flexible way! the pins are precomputed once only
  for (uint8_t bit=0x80; bit; bit >>= 1) {
    *clkportreg &= ~clkpin;
    if (d & bit) {
      *mosiportreg |= mosipin;
    } else {
      *mosiportreg &= ~mosipin;
    }
    *clkportreg |= clkpin;
  }

  *clkportreg &= ~clkpin;
}

// Basic, push SPI data out
void LPD8806::writezeros(uint16_t n) {
  // this is the 'least efficient' way (28ms per 32-LED write)
  /*
  digitalWrite(dataPin, LOW);
  for(uint16_t i = 8 * n; i>0; i--) {
     digitalWrite(clockPin, HIGH);
     digitalWrite(clockPin, LOW);
  }
  */

  if (hardwareSPI) {
    // hardware SPI!
    while(n--)
      SPI.transfer(0);
    return;
  }

  // this is the faster pin-flexible way! 7.4ms to write 32 LEDs
  *mosiportreg &= ~mosipin;
  for(uint16_t i = 8 * n; i>0; i--) {
    *clkportreg |= clkpin;
    *clkportreg &= ~clkpin;
  }
}

// This is how data is pushed to the strip.
// Unfortunately, the company that makes the chip didnt release the
// protocol document or you need to sign an NDA or something stupid
// like that, but we reverse engineered this from a strip
// controller and it seems to work very nicely!
void LPD8806::show(void) {
  uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED

  // get the strip's attention
  //writezeros(4);
  // This initial latch should only be required once,
  // moved to begin() method.

  // write 24 bits per pixel
  if (hardwareSPI) {
    // sped up!
    for (i=0; i<nl3; i++ ) {
      SPDR = pixels[i];
      while (!(SPSR & (1<<SPIF))) {};
    }
  } else {
    for (i=0; i<nl3; i++ ) {
      write8(pixels[i]);
    }
  }

  // to 'latch' the data, we send just zeros
  //writezeros(3*numLEDs*2);
  //writezeros(4);
  // 20111028 pburgess: correct latch length varies --
  // three bytes per 64 LEDs.
  writezeros(3 * ((numLEDs + 63) / 64));

  // we need to have a delay here, a few ms seems to do the job
  // shorter may be OK as well - need to experiment :(
  delay(3);
}

// store the rgb component in our array
void LPD8806::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
  uint32_t data;

  if (n > numLEDs) return;

  pixels[n*3] = g | 0x80;
  pixels[n*3+1] = r | 0x80;
  pixels[n*3+2] = b | 0x80;
}

void LPD8806::setPixelColor(uint16_t n, uint32_t c) {
  if (n > numLEDs) return;

  pixels[n*3] = (c >> 16) | 0x80;
  pixels[n*3+1] = (c >> 8) | 0x80;
  pixels[n*3+2] = c | 0x80;
}

<commit_msg>Fixed bounds checking in setPixelColor()<commit_after>#include "LPD8806.h"
#include "SPI.h"
#include "pins_arduino.h"
#include "wiring_private.h"

//Example to control LPD8806-based RGB LED Strips
// (c) Adafruit industries
// MIT license

/*****************************************************************************/

// Test code for using hardware SPI
LPD8806::LPD8806(uint16_t n) {
  // use hardware SPI!
  dataPin = clockPin = 0;
  hardwareSPI = true;

  numLEDs = n;
  // malloc 3 bytes per pixel so we dont have to hardcode the length
  pixels = (uint8_t *)malloc(numLEDs * 3); // 3 bytes per pixel
  memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state
}

LPD8806::LPD8806(uint16_t n, uint8_t dpin, uint8_t cpin) {
  dataPin = dpin;
  clockPin = cpin;

  numLEDs = n;

  clkportreg = portOutputRegister(digitalPinToPort(cpin));
  clkpin = digitalPinToBitMask(cpin);
  mosiportreg = portOutputRegister(digitalPinToPort(dpin));
  mosipin = digitalPinToBitMask(dpin);

  // malloc 3 bytes per pixel so we dont have to hardcode the length
  pixels = (uint8_t *)malloc(numLEDs * 3); // 3 bytes per pixel
  memset(pixels, 0x80, numLEDs * 3); // Init to RGB 'off' state
}

void LPD8806::begin(void) {
  pinMode(dataPin, OUTPUT);
  pinMode(clockPin, OUTPUT);

  if (hardwareSPI) {
    // using hardware SPI
    SPI.begin();
    // run the SPI bus as fast as possible
    // this has been tested on a 16MHz Arduino Uno
    SPI.setClockDivider(SPI_CLOCK_DIV2);
  }

  // Issue initial latch to 'wake up' strip (latch length varies w/numLEDs)
  writezeros(3 * ((numLEDs + 63) / 64));
}

uint16_t LPD8806::numPixels(void) {
  return numLEDs;
}

uint32_t LPD8806::Color(byte r, byte g, byte b)
{
  // Take the lowest 7 bits of each value and append them end to end
  // We have the top bit set high (its a 'parity-like' bit in the protocol
  // and must be set!)

  return 0x808080 | (g << 16) | (r << 8) | b;
}

// Basic, push SPI data out
inline void LPD8806::write8(uint8_t d) {

  // this is the 'least efficient' way (28ms per 32-LED write)
  // shiftOut(dataPin, clockPin, MSBFIRST, d);

  // this is the faster pin-flexible way! the pins are precomputed once only
  for (uint8_t bit=0x80; bit; bit >>= 1) {
    *clkportreg &= ~clkpin;
    if (d & bit) {
      *mosiportreg |= mosipin;
    } else {
      *mosiportreg &= ~mosipin;
    }
    *clkportreg |= clkpin;
  }

  *clkportreg &= ~clkpin;
}

// Basic, push SPI data out
void LPD8806::writezeros(uint16_t n) {
  // this is the 'least efficient' way (28ms per 32-LED write)
  /*
  digitalWrite(dataPin, LOW);
  for(uint16_t i = 8 * n; i>0; i--) {
     digitalWrite(clockPin, HIGH);
     digitalWrite(clockPin, LOW);
  }
  */

  if (hardwareSPI) {
    // hardware SPI!
    while(n--)
      SPI.transfer(0);
    return;
  }

  // this is the faster pin-flexible way! 7.4ms to write 32 LEDs
  *mosiportreg &= ~mosipin;
  for(uint16_t i = 8 * n; i>0; i--) {
    *clkportreg |= clkpin;
    *clkportreg &= ~clkpin;
  }
}

// This is how data is pushed to the strip.
// Unfortunately, the company that makes the chip didnt release the
// protocol document or you need to sign an NDA or something stupid
// like that, but we reverse engineered this from a strip
// controller and it seems to work very nicely!
void LPD8806::show(void) {
  uint16_t i, nl3 = numLEDs * 3; // 3 bytes per LED

  // get the strip's attention
  //writezeros(4);
  // This initial latch should only be required once,
  // moved to begin() method.

  // write 24 bits per pixel
  if (hardwareSPI) {
    // sped up!
    for (i=0; i<nl3; i++ ) {
      SPDR = pixels[i];
      while (!(SPSR & (1<<SPIF))) {};
    }
  } else {
    for (i=0; i<nl3; i++ ) {
      write8(pixels[i]);
    }
  }

  // to 'latch' the data, we send just zeros
  //writezeros(3*numLEDs*2);
  //writezeros(4);
  // 20111028 pburgess: correct latch length varies --
  // three bytes per 64 LEDs.
  writezeros(3 * ((numLEDs + 63) / 64));

  // we need to have a delay here, a few ms seems to do the job
  // shorter may be OK as well - need to experiment :(
  delay(3);
}

// store the rgb component in our array
void LPD8806::setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b) {
  uint32_t data;

  if (n >= numLEDs) return; // '>=' because arrays are 0-indexed

  pixels[n*3] = g | 0x80;
  pixels[n*3+1] = r | 0x80;
  pixels[n*3+2] = b | 0x80;
}

void LPD8806::setPixelColor(uint16_t n, uint32_t c) {
  if (n >= numLEDs) return; // '>=' because arrays are 0-indexed

  pixels[n*3] = (c >> 16) | 0x80;
  pixels[n*3+1] = (c >> 8) | 0x80;
  pixels[n*3+2] = c | 0x80;
}

<|endoftext|>


<commit_before>#include "NQueens.h"
#include <cilk/cilk.h>
#include <cilk/reducer_opadd.h>
#include <vector>
#include <iostream>
#include "Tree.h"

// global solution count for parallel calls
cilk::reducer_opadd<double> nqueens_solutions(0);

bool place_queen(Board &board, int row, int column) {
  board.add_queen(row, column);
  if (!board.validate_queen(row, column)) {
    board.remove_queen(row, column);
    return false;
  }
  return true;
}

int solve_serial(Board &board, int column) {
  int i;
  int num_solutions = 0;

  // for each possible queen placement
  for (i = 0; i < board.size; i++) {
    if (place_queen(board, i, column)) { // if it is a valid move, we place it

      num_solutions =
          column == board.size - 1
              // if we are at the end, mark as solution
              ? num_solutions + 1
              // if more columns, recursively add next columns solution
              : num_solutions + solve_serial(board, column + 1);

      // and remove the queen for next check
      board.remove_queen(i, column);
    }
  }

  return num_solutions;
}

int solve_parallel(Board board, int column) {
  int i;

  // if we got a solution
  if (column >= board.size) {
    *nqueens_solutions += 1;
    return nqueens_solutions.get_value();
  }

  // for each possible queen placement
  for (i = 0; i < board.size; i++) {
    if (place_queen(board, i, column)) { // if it is a valid move, we place it
      // check the rest of the board in parallel
      cilk_spawn solve_parallel(board, column+1);
      // and remove the queen for next check
      board.remove_queen(i, column);
    }
  }

  cilk_sync;
  return nqueens_solutions.get_value();
}

int solve_opt1(const size_t size) {
	int array[size];
	std::vector<bool> visited = std::vector<bool>(size, false);
	for (int i = 0; i < size; ++i) {
		array[i] = i;
	}
	Tree root = Tree(NULL, 19999);
	dfs_permute(array, size, &tree, 0, visited);

  return nqueens_solutions.get_value();
}

void dfs_permute(int *numbers, int size, const Tree *parent, int length, std::vector<bool> visited) {
	int *next_branch = new int[size];

	// Copy and init board layout for this path
	const Tree *tmp = parent;
	for (int i = 0; i < length; ++i) {
		next_branch[i] = tmp->value;
		tmp = tmp->parent;
	}
	for (int i = length; i < size; ++i) {
		next_branch[i] = -1;
	}

	{
		Board board = Board(next_branch, size);

		// Don't continue down this path of permutations if there's a conflict
		// This can hugely reduce the problem search space
		if (!board.validate_nqueens()) {
			return;
		}
	}

	if (length == size) {
		*nqueens_solutions += 1;
		delete parent;
		return;
	}

	for (int i = 0; i < size; i++) {
		// For all elements that haven't been used in permutation
		if (!visited[i]) {
			// Add to permutation
			const Tree *node = new Tree(parent, numbers[i]);
			visited[i] = true;
			// Permute remaining elements
			if (size - length <=2) {
				// don't create new workers if only two items remain
				dfs_permute(numbers, size, node, length+ 1, visited);
			} else {
				cilk_spawn dfs_permute(numbers, size, node, length+ 1, visited);
			}
			visited[i] = false;
		}
	}
	cilk_sync;
}

int solve_opt2(Column *last, int column, size_t size) {
    int i, back_n;
    bool valid;
    Column *tmp;

    // if we got a solution
    if (column == size) {
        delete last;
        *nqueens_solutions += 1;
        return 0; // only first call needs access to nqueens_solutions
    }

    // for each possible queen placement
    for (i = 0; i < size; i++) {
        tmp = last;
        back_n = 1;
        valid = true;
        while (tmp != NULL) {
            if (tmp->value == i || // if in same row
                tmp->value - back_n == i || // if in left diag
                tmp->value + back_n == i )  { // if in right diag
                valid = false; // invalid queen
                break;
            }
            tmp = tmp->prev;
            back_n += 1;
        }
        if (valid) {
            // check the rest of the board in parallel
            cilk_spawn solve_opt2(new Column(last, i), column + 1, size);
        }
    }

    cilk_sync;
    if (last != NULL) {
        delete last;
        return 0; // only first call needs access to nqueens_solutions
    }
    return nqueens_solutions.get_value();
}

int solve(Board &board, int flag) {
  switch(flag) {
    case PARALLEL:
      return solve_parallel(board, 0);
    case OPT1:
      return solve_opt1(board.size);
    case OPT2:
      return solve_opt2(NULL, 0, board.size);
    case SERIAL: default:
      return solve_serial(board, 0);
  }
}
<commit_msg>Reduced amount of unecessary board checks for opt1<commit_after>#include "NQueens.h"
#include <cilk/cilk.h>
#include <cilk/reducer_opadd.h>
#include <vector>
#include <iostream>
#include "Tree.h"

// global solution count for parallel calls
cilk::reducer_opadd<double> nqueens_solutions(0);

bool place_queen(Board &board, int row, int column) {
  board.add_queen(row, column);
  if (!board.validate_queen(row, column)) {
    board.remove_queen(row, column);
    return false;
  }
  return true;
}

int solve_serial(Board &board, int column) {
  int i;
  int num_solutions = 0;

  // for each possible queen placement
  for (i = 0; i < board.size; i++) {
    if (place_queen(board, i, column)) { // if it is a valid move, we place it

      num_solutions =
          column == board.size - 1
              // if we are at the end, mark as solution
              ? num_solutions + 1
              // if more columns, recursively add next columns solution
              : num_solutions + solve_serial(board, column + 1);

      // and remove the queen for next check
      board.remove_queen(i, column);
    }
  }

  return num_solutions;
}

int solve_parallel(Board board, int column) {
  int i;

  // if we got a solution
  if (column >= board.size) {
    *nqueens_solutions += 1;
    return nqueens_solutions.get_value();
  }

  // for each possible queen placement
  for (i = 0; i < board.size; i++) {
    if (place_queen(board, i, column)) { // if it is a valid move, we place it
      // check the rest of the board in parallel
      cilk_spawn solve_parallel(board, column+1);
      // and remove the queen for next check
      board.remove_queen(i, column);
    }
  }

  cilk_sync;
  return nqueens_solutions.get_value();
}

int solve_opt1(const size_t size) {
	int array[size];
	std::vector<bool> visited = std::vector<bool>(size, false);
	for (int i = 0; i < size; ++i) {
		array[i] = i;
	}
	Tree root = Tree(NULL, 19999);
	dfs_permute(array, size, &root, 0, visited);

  return nqueens_solutions.get_value();
}

void dfs_permute(int *numbers, int size, const Tree *parent, int length, std::vector<bool> visited) {
	int *next_branch = new int[size];

	// Copy and init board layout for this path
	const Tree *tmp = parent;
	for (int i = length - 1; i >= 0; --i) {
		next_branch[i] = tmp->value;
		tmp = tmp->parent;
	}
	for (int i = length; i < size; ++i) {
		next_branch[i] = -1;
	}

	{
		Board board = Board(next_branch, size);

		// Don't continue down this path of permutations if there's a conflict
		// This can hugely reduce the problem search space
		if (length > 0) {
			const size_t index = length - 1;
			const int lcount = board.queens_in_ldiagonal(parent->value, index);
			const int rcount = board.queens_in_rdiagonal(parent->value, index);
			if ( lcount > 1 || rcount > 1) {
				return;
			}
		}
	}

	if (length == size) {
		*nqueens_solutions += 1;
		delete parent;
		return;
	}

	for (int i = 0; i < size; i++) {
		// For all elements that haven't been used in permutation
		if (!visited[i]) {
			// Add to permutation
			const Tree *node = new Tree(parent, numbers[i]);
			visited[i] = true;
			// Permute remaining elements
			if (size - length <=5) {
				// don't create new workers if only two items remain
				dfs_permute(numbers, size, node, length+ 1, visited);
			} else {
				cilk_spawn dfs_permute(numbers, size, node, length+ 1, visited);
			}
			visited[i] = false;
		}
	}
	cilk_sync;
}

int solve_opt2(Column *last, int column, size_t size) {
    int i, back_n;
    bool valid;
    Column *tmp;

    // if we got a solution
    if (column == size) {
        delete last;
        *nqueens_solutions += 1;
        return 0; // only first call needs access to nqueens_solutions
    }

    // for each possible queen placement
    for (i = 0; i < size; i++) {
        tmp = last;
        back_n = 1;
        valid = true;
        while (tmp != NULL) {
            if (tmp->value == i || // if in same row
                tmp->value - back_n == i || // if in left diag
                tmp->value + back_n == i )  { // if in right diag
                valid = false; // invalid queen
                break;
            }
            tmp = tmp->prev;
            back_n += 1;
        }
        if (valid) {
            // check the rest of the board in parallel
            cilk_spawn solve_opt2(new Column(last, i), column + 1, size);
        }
    }

    cilk_sync;
    if (last != NULL) {
        delete last;
        return 0; // only first call needs access to nqueens_solutions
    }
    return nqueens_solutions.get_value();
}

int solve(Board &board, int flag) {
  switch(flag) {
    case PARALLEL:
      return solve_parallel(board, 0);
    case OPT1:
      return solve_opt1(board.size);
    case OPT2:
      return solve_opt2(NULL, 0, board.size);
    case SERIAL: default:
      return solve_serial(board, 0);
  }
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Message.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "Message.h"

using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::shh;

Message::Message(Envelope const& _e, FullTopic const& _fk, Secret const& _s)
{
	try
	{
		bytes b;
		if (_s)
			if (!decrypt(_s, &(_e.data()), b))
				return;
			else{}
		else
		{
			// public - need to get the key through combining with the topic/topicIndex we know.
			unsigned topicIndex = 0;
			Secret topicSecret;

			// determine topicSecret/topicIndex from knowledge of the collapsed topics (which give the order) and our full-size filter topic.
			CollapsedTopic knownTopic = collapse(_fk);
			for (unsigned ti = 0; ti < _fk.size() && !topicSecret; ++ti)
				for (unsigned i = 0; i < _e.topic().size(); ++i)
					if (_e.topic()[i] == knownTopic[ti])
					{
						topicSecret = _fk[ti];
						topicIndex = i;
						break;
					}

			if (_e.data().size() < _e.topic().size() * 32)
				return;

			// get key from decrypted topic key: just xor
			h256 tk = h256(bytesConstRef(&(_e.data())).cropped(32 * topicIndex, 32));
			bytesConstRef cipherText = bytesConstRef(&(_e.data())).cropped(32 * _e.topic().size());
			cnote << "Decrypting(" << topicIndex << "): " << topicSecret << tk << (topicSecret ^ tk) << toHex(cipherText);
			if (!decryptSym(topicSecret ^ tk, cipherText, b))
				return;
			cnote << "Got: " << toHex(b);
		}

		if (populate(b))
			if (_s)
				m_to = KeyPair(_s).pub();
	}
	catch (...)	// Invalid secret? TODO: replace ... with InvalidSecret
	{
	}
}

bool Message::populate(bytes const& _data)
{
	if (!_data.size())
		return false;

	byte flags = _data[0];
	if (!!(flags & ContainsSignature) && _data.size() >= sizeof(Signature) + 1)	// has a signature
	{
		bytesConstRef payload = bytesConstRef(&_data).cropped(1, _data.size() - sizeof(Signature) - 1);
		h256 h = sha3(payload);
		Signature const& sig = *(Signature const*)&(_data[1 + payload.size()]);
		m_from = recover(sig, h);
		if (!m_from)
			return false;
		m_payload = payload.toBytes();
	}
	else
		m_payload = bytesConstRef(&_data).cropped(1).toBytes();
	return true;
}

Envelope Message::seal(Secret _from, FullTopic const& _fullTopic, unsigned _ttl, unsigned _workToProve) const
{
	CollapsedTopic topic = collapse(_fullTopic);
	Envelope ret(time(0) + _ttl, _ttl, topic);

	bytes input(1 + m_payload.size());
	input[0] = 0;
	memcpy(input.data() + 1, m_payload.data(), m_payload.size());

	if (_from)		// needs a sig
	{
		input.resize(1 + m_payload.size() + sizeof(Signature));
		input[0] |= ContainsSignature;
		*(Signature*)&(input[1 + m_payload.size()]) = sign(_from, sha3(m_payload));
		// If this fails, the something is wrong with the sign-recover round-trip.
		assert(recover(*(Signature*)&(input[1 + m_payload.size()]), sha3(m_payload)) == KeyPair(_from).pub());
	}

	if (m_to)
		encrypt(m_to, &input, ret.m_data);
	else
	{
		// create the shared secret and encrypt
		Secret s = Secret::random();
		for (h256 const& t: _fullTopic)
			ret.m_data += (t ^ s).asBytes();
		bytes d;
		encryptSym(s, &input, d);
		ret.m_data += d;

		for (unsigned i = 0; i < _fullTopic.size(); ++i)
		{
			bytes b;
			h256 tk = h256(bytesConstRef(&(ret.m_data)).cropped(32 * i, 32));
			bytesConstRef cipherText = bytesConstRef(&(ret.m_data)).cropped(32 * ret.topic().size());
			cnote << "Test decrypting(" << i << "): " << _fullTopic[i] << tk << (_fullTopic[i] ^ tk) << toHex(cipherText);
			assert(decryptSym(_fullTopic[i] ^ tk, cipherText, b));
			cnote << "Got: " << toHex(b);
		}
	}

	ret.proveWork(_workToProve);
	return ret;
}

Envelope::Envelope(RLP const& _m)
{
	m_expiry = _m[0].toInt<unsigned>();
	m_ttl = _m[1].toInt<unsigned>();
	m_topic = _m[2].toVector<FixedHash<4>>();
	m_data = _m[3].toBytes();
	m_nonce = _m[4].toInt<u256>();
}

Message Envelope::open(FullTopic const& _ft, Secret const& _s) const
{
	return Message(*this, _ft, _s);
}

unsigned Envelope::workProved() const
{
	h256 d[2];
	d[0] = sha3(WithoutNonce);
	d[1] = m_nonce;
	return dev::sha3(bytesConstRef(d[0].data(), 64)).firstBitSet();
}

void Envelope::proveWork(unsigned _ms)
{
	// PoW
	h256 d[2];
	d[0] = sha3(WithoutNonce);
	uint32_t& n = *(uint32_t*)&(d[1][28]);
	unsigned bestBitSet = 0;
	bytesConstRef chuck(d[0].data(), 64);

	chrono::high_resolution_clock::time_point then = chrono::high_resolution_clock::now() + chrono::milliseconds(_ms);
	for (n = 0; chrono::high_resolution_clock::now() < then; )
		// do it rounds of 1024 for efficiency
		for (unsigned i = 0; i < 1024; ++i, ++n)
		{
			auto fbs = dev::sha3(chuck).firstBitSet();
			if (fbs > bestBitSet)
			{
				bestBitSet = fbs;
				m_nonce = n;
			}
		}
}
<commit_msg>Fixes #1470<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

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

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Message.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 */

#include "Message.h"

using namespace std;
using namespace dev;
using namespace dev::p2p;
using namespace dev::shh;

Message::Message(Envelope const& _e, FullTopic const& _fk, Secret const& _s)
{
	try
	{
		bytes b;
		if (_s)
			if (!decrypt(_s, &(_e.data()), b))
				return;
			else{}
		else
		{
			// public - need to get the key through combining with the topic/topicIndex we know.
			unsigned topicIndex = 0;
			Secret topicSecret;

			// determine topicSecret/topicIndex from knowledge of the collapsed topics (which give the order) and our full-size filter topic.
			CollapsedTopic knownTopic = collapse(_fk);
			for (unsigned ti = 0; ti < _fk.size() && !topicSecret; ++ti)
				for (unsigned i = 0; i < _e.topic().size(); ++i)
					if (_e.topic()[i] == knownTopic[ti])
					{
						topicSecret = _fk[ti];
						topicIndex = i;
						break;
					}

			if (_e.data().size() < _e.topic().size() * 32)
				return;

			// get key from decrypted topic key: just xor
			h256 tk = h256(bytesConstRef(&(_e.data())).cropped(32 * topicIndex, 32));
			bytesConstRef cipherText = bytesConstRef(&(_e.data())).cropped(32 * _e.topic().size());
//			cdebug << "Decrypting(" << topicIndex << "): " << topicSecret << tk << (topicSecret ^ tk) << toHex(cipherText);
			if (!decryptSym(topicSecret ^ tk, cipherText, b))
				return;
//			cdebug << "Got: " << toHex(b);
		}

		if (populate(b))
			if (_s)
				m_to = KeyPair(_s).pub();
	}
	catch (...)	// Invalid secret? TODO: replace ... with InvalidSecret
	{
	}
}

bool Message::populate(bytes const& _data)
{
	if (!_data.size())
		return false;

	byte flags = _data[0];
	if (!!(flags & ContainsSignature) && _data.size() >= sizeof(Signature) + 1)	// has a signature
	{
		bytesConstRef payload = bytesConstRef(&_data).cropped(1, _data.size() - sizeof(Signature) - 1);
		h256 h = sha3(payload);
		Signature const& sig = *(Signature const*)&(_data[1 + payload.size()]);
		m_from = recover(sig, h);
		if (!m_from)
			return false;
		m_payload = payload.toBytes();
	}
	else
		m_payload = bytesConstRef(&_data).cropped(1).toBytes();
	return true;
}

Envelope Message::seal(Secret _from, FullTopic const& _fullTopic, unsigned _ttl, unsigned _workToProve) const
{
	CollapsedTopic topic = collapse(_fullTopic);
	Envelope ret(time(0) + _ttl, _ttl, topic);

	bytes input(1 + m_payload.size());
	input[0] = 0;
	memcpy(input.data() + 1, m_payload.data(), m_payload.size());

	if (_from)		// needs a sig
	{
		input.resize(1 + m_payload.size() + sizeof(Signature));
		input[0] |= ContainsSignature;
		*(Signature*)&(input[1 + m_payload.size()]) = sign(_from, sha3(m_payload));
		// If this fails, the something is wrong with the sign-recover round-trip.
		assert(recover(*(Signature*)&(input[1 + m_payload.size()]), sha3(m_payload)) == KeyPair(_from).pub());
	}

	if (m_to)
		encrypt(m_to, &input, ret.m_data);
	else
	{
		// create the shared secret and encrypt
		Secret s = Secret::random();
		for (h256 const& t: _fullTopic)
			ret.m_data += (t ^ s).asBytes();
		bytes d;
		encryptSym(s, &input, d);
		ret.m_data += d;

		for (unsigned i = 0; i < _fullTopic.size(); ++i)
		{
			bytes b;
			h256 tk = h256(bytesConstRef(&(ret.m_data)).cropped(32 * i, 32));
			bytesConstRef cipherText = bytesConstRef(&(ret.m_data)).cropped(32 * ret.topic().size());
			cnote << "Test decrypting(" << i << "): " << _fullTopic[i] << tk << (_fullTopic[i] ^ tk) << toHex(cipherText);
			assert(decryptSym(_fullTopic[i] ^ tk, cipherText, b));
			cnote << "Got: " << toHex(b);
		}
	}

	ret.proveWork(_workToProve);
	return ret;
}

Envelope::Envelope(RLP const& _m)
{
	m_expiry = _m[0].toInt<unsigned>();
	m_ttl = _m[1].toInt<unsigned>();
	m_topic = _m[2].toVector<FixedHash<4>>();
	m_data = _m[3].toBytes();
	m_nonce = _m[4].toInt<u256>();
}

Message Envelope::open(FullTopic const& _ft, Secret const& _s) const
{
	return Message(*this, _ft, _s);
}

unsigned Envelope::workProved() const
{
	h256 d[2];
	d[0] = sha3(WithoutNonce);
	d[1] = m_nonce;
	return dev::sha3(bytesConstRef(d[0].data(), 64)).firstBitSet();
}

void Envelope::proveWork(unsigned _ms)
{
	// PoW
	h256 d[2];
	d[0] = sha3(WithoutNonce);
	uint32_t& n = *(uint32_t*)&(d[1][28]);
	unsigned bestBitSet = 0;
	bytesConstRef chuck(d[0].data(), 64);

	chrono::high_resolution_clock::time_point then = chrono::high_resolution_clock::now() + chrono::milliseconds(_ms);
	for (n = 0; chrono::high_resolution_clock::now() < then; )
		// do it rounds of 1024 for efficiency
		for (unsigned i = 0; i < 1024; ++i, ++n)
		{
			auto fbs = dev::sha3(chuck).firstBitSet();
			if (fbs > bestBitSet)
			{
				bestBitSet = fbs;
				m_nonce = n;
			}
		}
}
<|endoftext|>