-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathget_ocubo.m
149 lines (133 loc) · 3.93 KB
/
get_ocubo.m
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
function o = get_ocubo(n,method,sidelength,seed)
arguments
n {mustBeNonNegIntegerOrEmpty} = 1
method char {mustBeMember(method,{'random','uniform'})} = 'random'
sidelength {mustBeNonNegIntegerOrEmpty} = []
seed = []
end
% GET_OCUBO get octonions formed by pairs of quaternions from randomly or uniformly sampled cubochoric points.
% In general, for random, no two quaternions will be the same.
%--------------------------------------------------------------------------
% Author: Sterling Baird
%
% Date: 2020-07-25
%
% Inputs:
% n - # of octonions to output (re-calculated if using 'uniform' method
% and sidelength is specified
%
% method - sampling method, 'random', 'uniform'
%
% sidelength - # of points along edge of cube used in cubochoric
% sampling (automatically calculated if n is given and sidelength is
% not specified)
%
% Outputs:
%
% o - list of octonions
%
% Usage:
% o = get_ocubo(); %generate a single octonion formed by two
% quaternions sampled randomly from cubochoric space
%
% o = get_ocubo(5) %generate 5 octonions from pairs of quaternions
% randomly sampled from cubochoric space
%
% o = get_ocubo(5,'random') %generate 5 octonions from pairs of
% quaternions randomly sampled from cubochoric space
%
% o = get_ocubo(100,'uniform') %generate 100 octonions randomly sampled
% from list of pairs of quaternions generated via uniform cubochoric
% sampling with automatically calculated sidelength (ceil(100^(1/3))
%
% o = get_ocubo([],'uniform',5) %generate all combinations of
% quaternion pairs (i.e. octonions) using 5^3 == 125 uniformly sampled
% quaternions (15625 octonions)
%
% o = get_ocubo(100,'random',[],10) %generate 100 random octonions
% using a random number generator seed of 10
%
% Dependencies:
% allcomb.m (optional if nboQ == false)
%
% ocubo.m
% --cu2qu.m (De Graef group)
%
% Note: specifying 'random' and a non-empty sidelength will error, as these
% are two contradictory options.
%
%--------------------------------------------------------------------------
%set random number generator (only if custom seed is specified)
if ~isempty(seed)
startseed = rng; %to be used at end to set rng to initial state (i.e. before calling this function)
rng(seed)
end
% argument validation (cont.)
if strcmp(method,'random') && ~isempty(sidelength)
error('sidelength should not be specified for random sampling')
end
%--------------------------------------------------------------------------
%setup
if strcmp(method,'uniform') && isempty(sidelength)
sidelength = ceil(n^(1/3)); % auto-calculate sidelength
nq = [];
else
if isempty(sidelength)
nq = n;
else
nq = sidelength^3; %auto-calculate # of quaternions
end
end
%--------------------------------------------------------------------------
switch method
case 'random'
% get 2*n cubochoric points
q = get_cubo(2*nq,method,sidelength);
%unpack
qA = q(1:n,:);
qB = q(n+1:2*n,:);
case 'uniform'
%get n cubochoric points
q = get_cubo(nq,method,sidelength);
%convert to cell array of quaternions
q = num2cell(q,2);
%form pairs
nboQ = true; %whether to include no-boundary octonions
if nboQ
qpairs = allcomb(q,q);
else
qpairs = nchoosek(q,2);
end
% unpack
qA = vertcat(qpairs{:,1});
qB = vertcat(qpairs{:,2});
if ~isempty(n)
if (n < length(q)) && ~isempty(sidelength)
% get a random list of the quaternions
randlist = randi(size(qA,1),n,1);
qA = qA(randlist,:);
qB = qB(randlist,:);
end
end
end
%catenate
o = [qA qB];
%get unique list
[~,ia] = uniquetol(round(o,12),'ByRows',true);
o = o(ia,:);
if ~isempty(seed)
%reset rng back to what it was before calling the function
rng(startseed);
end
end %get_ocube.m
%----------------------CUSTOM VALIDATION FUNCTIONS-------------------------
function mustBeNonNegIntegerOrEmpty(arg)
errmsg = 'must be non-neg integer or empty []';
if ~isempty(arg)
if floor(arg) ~= arg
error(errmsg)
elseif arg < 0
error(errmsg)
end
end
end