idol
A C++ Framework for Optimization
Loading...
Searching...
No Matches
sort.h
1//
2// Created by henri on 24.10.24.
3//
4
5#ifndef IDOL_SORT_H
6#define IDOL_SORT_H
7
8#include <vector>
9#include <numeric>
10#include <functional>
11#include <iostream>
12#include "idol/general/utils/Pair.h"
13
14namespace idol {
15 template<class T> struct get_id;
16
17 template<class Key1, class Key2>
18 struct get_id<std::pair<Key1, Key2>> {
19 auto operator()(const std::pair<Key1, Key2>& t) const { return std::make_pair(get_id<Key1>()(t.first), get_id<Key2>()(t.second)); }
20 };
21
22 template<class T>
23 struct get_id {
24 unsigned int operator()(const T& t) const { return t.id(); }
25 };
26
27 template<class Key1, class Key2>
28 struct get_id<idol::Pair<Key1, Key2>> {
29 auto operator()(const idol::Pair<Key1, Key2>& t) const { return std::make_pair(get_id<Key1>()(t.first), get_id<Key2>()(t.second)); }
30 };
31
32 template<class T>
33 struct identity {
34 const T& operator()(const T& t) const { return t; }
35 };
36
37 template<class T>
38 void apply_permutation(const std::vector<unsigned int>& t_permutation, std::vector<T>& t_arg) {
39
40 std::vector<bool> visited(t_arg.size(), false); // To track visited elements
41
42 for (size_t i = 0; i < t_arg.size(); ++i) {
43
44 if (visited[i]) {
45 continue; // Skip if already processed
46 }
47
48 // Apply permutation cycle starting at index i
49 size_t current = i;
50 T temp = std::move(t_arg[i]); // Store the element to be moved
51
52 while (true) {
53 size_t next = t_permutation[current]; // Find the target index
54 if (next == i) {
55 break; // End of cycle
56 }
57
58 t_arg[current] = std::move(t_arg[next]); // Move the element
59 visited[current] = true; // Mark as visited
60 current = next; // Move to the next index
61 }
62
63 t_arg[current] = std::move(temp); // Place the stored element in its final position
64 visited[current] = true; // Mark the last element as visited
65 }
66 }
67
68 template<class FirstT, class ...T>
69 void apply_permutation(const std::vector<unsigned int>& t_permutation, std::vector<FirstT>& t_first, std::vector<T>& ...t_args) {
70 apply_permutation(t_permutation, t_first);
71 apply_permutation(t_permutation, t_args...);
72 }
73
74 template<class IndexT, class IndexExtractor = identity<IndexT>, class ...T>
75 void sort(std::vector<IndexT>& t_index,
76 std::vector<T>& ... t_args) {
77
78 std::vector<unsigned int> permutation(t_index.size());
79 std::iota(permutation.begin(), permutation.end(), 0);
80 std::sort(
81 permutation.begin(),
82 permutation.end(),
83 [&t_index, extractor = IndexExtractor()](unsigned int i, unsigned int j) {
84 return extractor(t_index[i]) < extractor(t_index[j]);
85 }
86 );
87
88 apply_permutation(permutation, t_index, t_args...);
89
90 }
91}
92
93#endif //IDOL_SORT_H