GraphLab: Distributed Graph-Parallel API  2.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
stl_util.hpp
1 /**
2  * Copyright (c) 2009 Carnegie Mellon University.
3  * All rights reserved.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing,
12  * software distributed under the License is distributed on an "AS
13  * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
14  * express or implied. See the License for the specific language
15  * governing permissions and limitations under the License.
16  *
17  * For more about this software visit:
18  *
19  * http://www.graphlab.ml.cmu.edu
20  *
21  */
22 
23 
24 // Probabilistic Reasoning Library (PRL)
25 // Copyright 2009 (see AUTHORS.txt for a list of contributors)
26 //
27 // This library is free software; you can redistribute it and/or
28 // modify it under the terms of the GNU Lesser General Public
29 // License as published by the Free Software Foundation; either
30 // version 2.1 of the License, or (at your option) any later version.
31 //
32 // This library is distributed in the hope that it will be useful,
33 // but WITHOUT ANY WARRANTY; without even the implied warranty of
34 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35 // Lesser General Public License for more details.
36 //
37 // You should have received a copy of the GNU Lesser General Public
38 // License along with this library; if not, write to the Free Software
39 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
40 
41 #ifndef GRAPHLAB_STL_UTIL_HPP
42 #define GRAPHLAB_STL_UTIL_HPP
43 
44 
45 #include <set>
46 #include <map>
47 #include <vector>
48 #include <algorithm>
49 #include <iterator>
50 #include <sstream>
51 #include <iostream>
52 #include <iomanip>
53 #include <graphlab/logger/assertions.hpp>
54 
55 // #include <graphlab/serialization/serialize.hpp>
56 // #include <graphlab/serialization/set.hpp>
57 // #include <graphlab/serialization/map.hpp>
58 
59 #include <graphlab/macros_def.hpp>
60 
61 namespace graphlab {
62 
63  // Functions on sets
64  //============================================================================
65 
66  /**
67  * computes the union of two sets.
68  */
69  template <typename T>
70  std::set<T> set_union(const std::set<T>& a, const std::set<T>& b) {
71  std::set<T> output;
72  std::set_union(a.begin(), a.end(),
73  b.begin(), b.end(),
74  std::inserter(output, output.begin()));
75  return output;
76  }
77 
78  template <typename T>
79  std::set<T> set_union(const std::set<T>& a, const T& b) {
80  std::set<T> output = a;
81  output.insert(b);
82  return output;
83  }
84 
85  template <typename T>
86  std::set<T> set_intersect(const std::set<T>& a, const std::set<T>& b) {
87  std::set<T> output;
88  std::set_intersection(a.begin(), a.end(),
89  b.begin(), b.end(),
90  std::inserter(output, output.begin()));
91  return output;
92  }
93 
94  template <typename T>
95  std::set<T> set_difference(const std::set<T>& a, const std::set<T>& b) {
96  std::set<T> output;
97  std::set_difference(a.begin(), a.end(),
98  b.begin(), b.end(),
99  std::inserter(output, output.begin()));
100  return output;
101  }
102 
103 
104  template <typename T>
105  std::set<T> set_difference(const std::set<T>& a, const T& b) {
106  std::set<T> output = a;
107  output.erase(b);
108  return output;
109  }
110 
111  //! @return 2 sets: <s in partition, s not in partition>
112  template <typename T>
113  std::pair<std::set<T>,std::set<T> >
114  set_partition(const std::set<T>& s, const std::set<T>& partition) {
115  std::set<T> a, b;
116  a = set_intersect(s, partition);
117  b = set_difference(s, partition);
118  return std::make_pair(a, b);
119  }
120 
121  template <typename T>
122  bool set_disjoint(const std::set<T>& a, const std::set<T>& b) {
123  return (intersection_size(a,b) == 0);
124  }
125 
126  template <typename T>
127  bool set_equal(const std::set<T>& a, const std::set<T>& b) {
128  if (a.size() != b.size()) return false;
129  return a == b; // defined in <set>
130  }
131 
132  template <typename T>
133  bool includes(const std::set<T>& a, const std::set<T>& b) {
134  return std::includes(a.begin(), a.end(), b.begin(), b.end());
135  }
136 
137  /**
138  * Returns true if $a \subseteq b$
139  */
140  template <typename T>
141  bool is_subset(const std::set<T>& a, const std::set<T>& b) {
142  return includes(b, a);
143  }
144 
145  template <typename T>
146  bool is_superset(const std::set<T>& a,const std::set<T>& b) {
147  return includes(a, b);
148  }
149 
150  //! Writes a human representation of the set to the supplied stream.
151  template <typename T>
152  std::ostream& operator<<(std::ostream& out, const std::set<T>& s) {
153  return print_range(out, s, '{', ' ', '}');
154  }
155 
156  // Functions on maps
157  //============================================================================
158 
159  /**
160  * constant lookup in a map. assertion failure of key not found in map
161  */
162  template <typename Key, typename T>
163  const T& safe_get(const std::map<Key, T>& map,
164  const Key& key) {
165  typedef typename std::map<Key, T>::const_iterator iterator;
166  iterator iter = map.find(key);
167  ASSERT_TRUE(iter != map.end());
168  return iter->second;
169  } // end of safe_get
170 
171  /**
172  * constant lookup in a map. If key is not found in map,
173  * 'default_value' is returned. Note that this can't return a reference
174  * and must return a copy
175  */
176  template <typename Key, typename T>
177  const T safe_get(const std::map<Key, T>& map,
178  const Key& key, const T default_value) {
179  typedef typename std::map<Key, T>::const_iterator iterator;
180  iterator iter = map.find(key);
181  if (iter == map.end()) return default_value;
182  else return iter->second;
183  } // end of safe_get
184 
185  /**
186  * Transform each key in the map using the key_map
187  * transformation. The resulting map will have the form
188  * output[key_map[i]] = map[i]
189  */
190  template <typename OldKey, typename NewKey, typename T>
191  std::map<NewKey, T>
192  rekey(const std::map<OldKey, T>& map,
193  const std::map<OldKey, NewKey>& key_map) {
194  std::map<NewKey, T> output;
195  typedef std::pair<OldKey, T> pair_type;
196  foreach(const pair_type& pair, map) {
197  output[safe_get(key_map, pair.first)] = pair.second;
198  }
199  return output;
200  }
201 
202  /**
203  * Transform each key in the map using the key_map
204  * transformation. The resulting map will have the form
205  output[i] = remap[map[i]]
206  */
207  template <typename Key, typename OldT, typename NewT>
208  std::map<Key, NewT>
209  remap(const std::map<Key, OldT>& map,
210  const std::map<OldT, NewT>& val_map) {
211  std::map<Key, NewT> output;
212  typedef std::pair<Key, OldT> pair_type;
213  foreach(const pair_type& pair, map) {
214  output[pair.first] = safe_get(val_map, pair.second);
215  }
216  return output;
217  }
218 
219  /**
220  * Inplace version of remap
221  */
222  template <typename Key, typename T>
223  void remap(std::map<Key, T>& map,
224  const std::map<T, T>& val_map) {
225  typedef std::pair<Key, T> pair_type;
226  foreach(pair_type& pair, map) {
227  pair.second = safe_get(val_map, pair.second);
228  }
229  }
230 
231  /**
232  * Computes the union of two maps
233  */
234  template <typename Key, typename T>
235  std::map<Key, T>
236  map_union(const std::map<Key, T>& a,
237  const std::map<Key, T>& b) {
238  // Initialize the output map
239  std::map<Key, T> output;
240  std::set_union(a.begin(), a.end(),
241  b.begin(), b.end(),
242  std::inserter(output, output.begin()),
243  output.value_comp());
244  return output;
245  }
246 
247  /**
248  * Computes the intersection of two maps
249  */
250  template <typename Key, typename T>
251  std::map<Key, T>
252  map_intersect(const std::map<Key, T>& a,
253  const std::map<Key, T>& b) {
254  // Initialize the output map
255  std::map<Key, T> output;
256  // compute the intersection
257  std::set_intersection(a.begin(), a.end(),
258  b.begin(), b.end(),
259  std::inserter(output, output.begin()),
260  output.value_comp());
261  return output;
262  }
263 
264  /**
265  * Returns the entries of a map whose keys show up in the set keys
266  */
267  template <typename Key, typename T>
268  std::map<Key, T>
269  map_intersect(const std::map<Key, T>& m,
270  const std::set<Key>& keys) {
271  std::map<Key, T> output;
272  foreach(const Key& key, keys) {
273  typename std::map<Key,T>::const_iterator it = m.find(key);
274  if (it != m.end())
275  output[key] = it->second;
276  }
277  return output;
278  }
279 
280  /**
281  * Computes the difference between two maps
282  */
283  template <typename Key, typename T>
284  std::map<Key, T>
285  map_difference(const std::map<Key, T>& a,
286  const std::map<Key, T>& b) {
287  // Initialize the output map
288  std::map<Key, T> output;
289  // compute the intersection
290  std::set_difference(a.begin(), a.end(),
291  b.begin(), b.end(),
292  std::inserter(output, output.begin()),
293  output.value_comp());
294  return output;
295  }
296 
297 
298  /**
299  * Returns the set of keys in a map
300  */
301  template <typename Key, typename T>
302  std::set<Key> keys(const std::map<Key, T>& map) {
303  std::set<Key> output;
304  typedef std::pair<Key, T> pair_type;
305  foreach(const pair_type& pair, map) {
306  output.insert(pair.first);
307  }
308  return output;
309  }
310 
311  /**
312  * Get teh set of keys in a map as a vector
313  */
314  template <typename Key, typename T>
315  std::vector<Key> keys_as_vector(const std::map<Key, T>& map) {
316  std::vector<Key> output(map.size());
317  typedef std::pair<Key, T> pair_type;
318  size_t i = 0;
319  foreach(const pair_type& pair, map) {
320  output[i++] = pair.first;
321  }
322  return output;
323  }
324 
325 
326  /**
327  * Gets the values from a map
328  */
329  template <typename Key, typename T>
330  std::set<T> values(const std::map<Key, T>& map) {
331  std::set<T> output;
332  typedef std::pair<Key, T> pair_type;
333  foreach(const pair_type& pair, map) {
334  output.insert(pair.second);
335  }
336  return output;
337  }
338 
339  template <typename Key, typename T>
340  std::vector<T> values(const std::map<Key, T>& m,
341  const std::set<Key>& keys) {
342  std::vector<T> output;
343 
344  foreach(const Key &i, keys) {
345  output.push_back(safe_get(m, i));
346  }
347  return output;
348  }
349 
350  template <typename Key, typename T>
351  std::vector<T> values(const std::map<Key, T>& m,
352  const std::vector<Key>& keys) {
353  std::vector<T> output;
354  foreach(const Key &i, keys) {
355  output.push_back(safe_get(m, i));
356  }
357  return output;
358  }
359 
360  //! Creates an identity map (a map from elements to themselves)
361  template <typename Key>
362  std::map<Key, Key> make_identity_map(const std::set<Key>& keys) {
363  std::map<Key, Key> m;
364  foreach(const Key& key, keys)
365  m[key] = key;
366  return m;
367  }
368 
369  //! Writes a map to the supplied stream.
370  template <typename Key, typename T>
371  std::ostream& operator<<(std::ostream& out, const std::map<Key, T>& m) {
372  out << "{";
373  for (typename std::map<Key, T>::const_iterator it = m.begin();
374  it != m.end();) {
375  out << it->first << "-->" << it->second;
376  if (++it != m.end()) out << " ";
377  }
378  out << "}";
379  return out;
380  }
381 
382  /** Removes white space (space and tabs) from the beginning and end of str,
383  returning the resultant string
384  */
385  inline std::string trim(const std::string& str) {
386  std::string::size_type pos1 = str.find_first_not_of(" \t");
387  std::string::size_type pos2 = str.find_last_not_of(" \t");
388  return str.substr(pos1 == std::string::npos ? 0 : pos1,
389  pos2 == std::string::npos ? str.size()-1 : pos2-pos1+1);
390  }
391 
392  /**
393  * Convenience function for using std streams to convert anything to a string
394  */
395  template<typename T>
396  std::string tostr(const T& t) {
397  std::stringstream strm;
398  strm << t;
399  return strm.str();
400  }
401 
402  /**
403  * Convenience function for using std streams to convert a string to anything
404  */
405  template<typename T>
406  T fromstr(const std::string& str) {
407  std::stringstream strm(str);
408  T elem;
409  strm >> elem;
410  ASSERT_FALSE(strm.fail());
411  return elem;
412  }
413 
414  /**
415  Returns a string representation of the number,
416  padded to 'npad' characters using the pad_value character
417  */
418  inline std::string pad_number(const size_t number,
419  const size_t npad,
420  const char pad_value = '0') {
421  std::stringstream strm;
422  strm << std::setw((int)npad) << std::setfill(pad_value)
423  << number;
424  return strm.str();
425  }
426 
427 
428  // inline std::string change_suffix(const std::string& fname,
429  // const std::string& new_suffix) {
430  // size_t pos = fname.rfind('.');
431  // assert(pos != std::string::npos);
432  // const std::string new_base(fname.substr(0, pos));
433  // return new_base + new_suffix;
434  // } // end of change_suffix
435 
436 
437  /**
438  Using splitchars as delimiters, splits the string into a vector of strings.
439  if auto_trim is true, trim() is called on all the extracted strings
440  before returning.
441  */
442  inline std::vector<std::string> strsplit(const std::string& str,
443  const std::string& splitchars,
444  const bool auto_trim = false) {
445  std::vector<std::string> tokens;
446  for(size_t beg = 0, end = 0; end != std::string::npos; beg = end+1) {
447  end = str.find_first_of(splitchars, beg);
448  if(auto_trim) {
449  if(end - beg > 0) {
450  std::string tmp = trim(str.substr(beg, end - beg));
451  if(!tmp.empty()) tokens.push_back(tmp);
452  }
453  } else tokens.push_back(str.substr(beg, end - beg));
454  }
455  return tokens;
456  // size_t pos = 0;
457  // while(1) {
458  // size_t nextpos = s.find_first_of(splitchars, pos);
459  // if (nextpos != std::string::npos) {
460  // ret.push_back(s.substr(pos, nextpos - pos));
461  // pos = nextpos + 1;
462  // } else {
463  // ret.push_back(s.substr(pos));
464  // break;
465  // }
466  // }
467  // return ret;
468  }
469 }; // end of namespace graphlab
470 
471 #include <graphlab/macros_undef.hpp>
472 
473 #endif
474