File: Permutations.hh

package info (click to toggle)
cadabra2 2.4.3.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 78,732 kB
  • sloc: ansic: 133,450; cpp: 92,064; python: 1,530; javascript: 203; sh: 184; xml: 182; objc: 53; makefile: 51
file content (119 lines) | stat: -rw-r--r-- 2,480 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

#pragma once

#include <stdexcept>
#include <vector>

/// \ingroup core
///
/// Generic permutation group material. Largely follows the notation of xperm to avoid
/// confusion.
///
/// Example: 1->4, 4->3, 3->1, 5->6, 6->5
///
///    Perm(   3, 2, 4, 1, 6, 5 )
///    Images( 4, 2, 1, 3, 6, 5 )

class PermutationException : std::logic_error {
	public:
		PermutationException(const std::string& ex) : std::logic_error(ex) {};
	};

class Perm {
	public:
		std::vector<int> perm;

		/// Find the permutation that takes [start1, end1> to [start2, end2>.
		/// This will be available in 'perm' afterwards.
		template<class iterator>
		void find(iterator start1, iterator end1, iterator start2, iterator end2);

		/// Apply the permutation 'perm' on the given range.
		template<class iterator>
		void apply(iterator start1, iterator end1);

	};

class Images {
	public:
		std::vector<int> images;

		/// Find the permutation that takes [start1, end1> to [start2, end2>.
		template<class iterator>
		void find(iterator start1, iterator end1, iterator start2, iterator end2);
	};




template<class iterator>
void Perm::find(iterator start1, iterator end1, iterator start2, iterator end2)
	{
	perm.clear();

	while(start2!=end2) {
		auto it=start1;
		int num=0;
		while(it!=end1) {
			if(*start2==*it) {
				perm.push_back(num);
				break;
				}
			++num;
			++it;
			}
		if(it==end1)
			throw PermutationException("Sets do not contain the same elements.");

		++start2;
		}
	}

template<class iterator>
void Perm::apply(iterator start, iterator end)
	{
	typedef typename std::remove_reference<decltype(*start)>::type value_type;

	std::vector<value_type> orig;
	auto it=start;
	while(it!=end) {
		orig.push_back(*it);
		++it;
		}

	// std::cerr << orig.size() << ", " << perm.size() << std::endl;
	if(orig.size()!=perm.size()) {
		std::cerr << "Perm::apply: orig.size()=" << orig.size() << ", "
		          << "perm.size()=" << perm.size() << std::endl;
		assert(orig.size()==perm.size());
		}

	for(unsigned int i=0; i<orig.size(); ++i) {
		*start=orig[perm[i]];
		++start;
		}
	}


template<class iterator>
void Images::find(iterator start1, iterator end1, iterator start2, iterator end2)
	{
	images.clear();

	while(start1!=end1) {
		auto it=start2;
		int num=0;
		while(it!=end2) {
			if(*start1==*it) {
				images.push_back(num);
				break;
				}
			++num;
			++it;
			}
		if(it==end2)
			throw PermutationException("Sets do not contain the same elements.");

		++start1;
		}
	}