-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAMUBeef.php
249 lines (188 loc) · 7.53 KB
/
AMUBeef.php
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
<?php
// Code to randomly generate conjoint profiles to send to a Qualtrics instance
// Terminology clarification:
// Task = Set of choices presented to respondent in a single screen (i.e. pair of candidates)
// Profile = Single list of attributes in a given task (i.e. candidate)
// Attribute = Category characterized by a set of levels (i.e. education level)
// Level = Value that an attribute can take in a particular choice task (i.e. "no formal education")
// Attributes and Levels stored in a 2-dimensional Array
// Function to generate weighted random numbers
function weighted_randomize($prob_array, $at_key)
{
$prob_list = $prob_array[$at_key];
// Create an array containing cutpoints for randomization
$cumul_prob = array();
$cumulative = 0.0;
for ($i=0; $i<count($prob_list); $i++){
$cumul_prob[$i] = $cumulative;
$cumulative = $cumulative + floatval($prob_list[$i]);
}
// Generate a uniform random floating point value between 0.0 and 1.0
$unif_rand = mt_rand() / mt_getrandmax();
// Figure out which integer should be returned
$outInt = 0;
for ($k = 0; $k < count($cumul_prob); $k++){
if ($cumul_prob[$k] <= $unif_rand){
$outInt = $k + 1;
}
}
return($outInt);
}
$featurearray = array("Antibiotic Use" => array("Raised without antibiotics","Fed no antibiotics","Raised without medically important antibiotics","Fed no medically important antibiotics","Raised with responsible antibiotic use","Conventional antibiotic use"),"Production" => array("Grassfed","Conventional"),"Certified Organic" => array("Yes","No"),"Animal Welfare Certified " => array("Yes","No"),"Add Hormone" => array("Yes","No"),"Price" => array("8","10","12","14"));
$restrictionarray = array();
// Indicator for whether weighted randomization should be enabled or not
$weighted = 0;
// K = Number of tasks displayed to the respondent
$K = 5;
// N = Number of profiles displayed in each task
$N = 2;
// num_attributes = Number of Attributes in the Array
$num_attributes = count($featurearray);
// Should duplicate profiles be rejected?
$noDuplicateProfiles = False;
$attrconstraintarray = array();
// Re-randomize the $featurearray
// Place the $featurearray keys into a new array
$featureArrayKeys = array();
$incr = 0;
foreach($featurearray as $attribute => $levels){
$featureArrayKeys[$incr] = $attribute;
$incr = $incr + 1;
}
// Backup $featureArrayKeys
$featureArrayKeysBackup = $featureArrayKeys;
// If order randomization constraints exist, drop all of the non-free attributes
if (count($attrconstraintarray) != 0){
foreach ($attrconstraintarray as $constraints){
if (count($constraints) > 1){
for ($p = 1; $p < count($constraints); $p++){
if (in_array($constraints[$p], $featureArrayKeys)){
$remkey = array_search($constraints[$p],$featureArrayKeys);
unset($featureArrayKeys[$remkey]);
}
}
}
}
}
// Re-set the array key indices
$featureArrayKeys = array_values($featureArrayKeys);
// Re-randomize the $featurearray keys
shuffle($featureArrayKeys);
// Re-insert the non-free attributes constrained by $attrconstraintarray
if (count($attrconstraintarray) != 0){
foreach ($attrconstraintarray as $constraints){
if (count($constraints) > 1){
$insertloc = $constraints[0];
if (in_array($insertloc, $featureArrayKeys)){
$insert_block = array($insertloc);
for ($p = 1; $p < count($constraints); $p++){
if (in_array($constraints[$p], $featureArrayKeysBackup)){
array_push($insert_block, $constraints[$p]);
}
}
$begin_index = array_search($insertloc, $featureArrayKeys);
array_splice($featureArrayKeys, $begin_index, 1, $insert_block);
}
}
}
}
// Re-generate the new $featurearray - label it $featureArrayNew
$featureArrayNew = array();
foreach($featureArrayKeys as $key){
$featureArrayNew[$key] = $featurearray[$key];
}
// Initialize the array returned to the user
// Naming Convention
// Level Name: F-[task number]-[profile number]-[attribute number]
// Attribute Name: F-[task number]-[attribute number]
// Example: F-1-3-2, Returns the level corresponding to Task 1, Profile 3, Attribute 2
// F-3-3, Returns the attribute name corresponding to Task 3, Attribute 3
$returnarray = array();
// For each task $p
for($p = 1; $p <= $K; $p++){
// For each profile $i
for($i = 1; $i <= $N; $i++){
// Repeat until non-restricted profile generated
$complete = False;
while ($complete == False){
// Create a count for $attributes to be incremented in the next loop
$attr = 0;
// Create a dictionary to hold profile's attributes
$profile_dict = array();
// For each attribute $attribute and level array $levels in task $p
foreach($featureArrayNew as $attribute => $levels){
// Increment attribute count
$attr = $attr + 1;
// Create key for attribute name
$attr_key = "F-" . (string)$p . "-" . (string)$attr;
// Store attribute name in $returnarray
$returnarray[$attr_key] = $attribute;
// Get length of $levels array
$num_levels = count($levels);
// Randomly select one of the level indices
if ($weighted == 1){
$level_index = weighted_randomize($probabilityarray, $attribute) - 1;
}else{
$level_index = mt_rand(1,$num_levels) - 1;
}
// Pull out the selected level
$chosen_level = $levels[$level_index];
// Store selected level in $profileDict
$profile_dict[$attribute] = $chosen_level;
// Create key for level in $returnarray
$level_key = "F-" . (string)$p . "-" . (string)$i . "-" . (string)$attr;
// Store selected level in $returnarray
$returnarray[$level_key] = $chosen_level;
}
$clear = True;
// Cycle through restrictions to confirm/reject profile
if(count($restrictionarray) != 0){
foreach($restrictionarray as $restriction){
$false = 1;
foreach($restriction as $pair){
if ($profile_dict[$pair[0]] == $pair[1]){
$false = $false*1;
}else{
$false = $false*0;
}
}
if ($false == 1){
$clear = False;
}
}
}
// Cycle through all previous profiles to confirm no identical profiles
if ($noDuplicateProfiles == True){
if ($i > 1){
// For each previous profile
for($z = 1; $z < $i; $z++){
// Start by assuming it's the same
$identical = True;
// Create a count for $attributes to be incremented in the next loop
$attrTemp = 0;
// For each attribute $attribute and level array $levels in task $p
foreach($featureArrayNew as $attribute => $levels){
// Increment attribute count
$attrTemp = $attrTemp + 1;
// Create keys
$level_key_profile = "F-" . (string)$p . "-" . (string)$i . "-" . (string)$attrTemp;
$level_key_check = "F-" . (string)$p . "-" . (string)$z . "-" . (string)$attrTemp;
// If attributes are different, declare not identical
if ($returnarray[$level_key_profile] != $returnarray[$level_key_check]){
$identical = False;
}
}
// If we detect an identical profile, reject
if ($identical == True){
$clear = False;
}
}
}
}
$complete = $clear;
}
}
}
// Return the array back to Qualtrics
print json_encode($returnarray);
?>