-
Notifications
You must be signed in to change notification settings - Fork 1
/
MissingMPInstanceGenerator.py
121 lines (107 loc) · 4.13 KB
/
MissingMPInstanceGenerator.py
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
import random
import copy
import csv
'''
This class creates exports a csv of shuffled missing n-bit multiplexer instances. A missing multiplexer instance is a
multiclass multiplexer (i.e. register bits are multiclass) whose attributes appear in order. The csv writes a blank row
for spaces between instances
'''
class MissingMPInstanceGenerator:
def __init__(self,bits=6,classCount=4):
#Check if bits is valid from 6 bit to 135 bit MP
isValid = False
addressBitCount = 0
registerBitCount = 0
for i in range(2,8):
if bits == i+pow(2,i):
isValid = True
addressBitCount = i
registerBitCount = bits - addressBitCount
if not isValid:
raise Exception("# of bits is invalid. Must be n+2^n, 2 <= n <= 7")
#Check if classCount is valid
if classCount < 2:
raise Exception("# of classes must be at least 2")
#Populate list of possible MP conditions and actions
mps = []
for i in range(pow(2,addressBitCount)):
address = str(self.baseTenToBase(i,2))
for j in range(pow(classCount,registerBitCount)):
register = str(self.baseTenToBase(j,classCount))
while len(register) < registerBitCount:
register = "0"+register
while len(address) < addressBitCount:
address = "0"+address
nAddress = []
nRegister = []
for z in address:
nAddress.append(int(z))
for z in register:
nRegister.append(int(z))
r = self.binaryToDecimal(int(address))
phenotype = register[r]
mps.append(nAddress+nRegister+[int(phenotype)])
#Sort mps by class
splitMPs = []
for i in range(classCount):
splitMPs.append([])
for i in mps:
splitMPs[i[len(i)-1]].append(i)
#Determine appearance order for each class
shuffleIndices = []
indices = []
for i in range(bits):
indices.append(i)
for i in range(classCount):
t = random.sample(indices,len(indices))
while t in shuffleIndices:
t = random.sample(indices, len(indices))
shuffleIndices.append(t)
#Create instances
self.instances = []
for classIndex in range(classCount):
for inst in splitMPs[classIndex]:
newInst = [""]*(bits+1)
newInst[bits] = inst[bits] #Phenotype
singleInst = []
for appearIndex in shuffleIndices[classIndex]:
newInst[appearIndex] = inst[appearIndex]
singleInst.append(copy.deepcopy(newInst))
self.instances.append(singleInst)
self.bits = bits
self.classCount = classCount
#Returns num in base endBase
def baseTenToBase(self,num, endBase):
s = ""
while int(num / endBase) != 0:
r = num % endBase
num = int(num / endBase)
s = str(r) + s
r = num % endBase
s = str(r) + s
return int(s)
def binaryToDecimal(self,binary):
binary1 = binary
decimal, i, n = 0, 0, 0
while (binary != 0):
dec = binary % 10
decimal = decimal + dec * pow(2, i)
binary = binary // 10
i += 1
return decimal
def exportInstances(self,filename="mp.csv"):
headerNames = []
for i in range(self.bits+1):
if i != self.bits:
headerNames.append("N"+str(i))
else:
headerNames.append("class")
with open(filename,mode='w') as file:
writer = csv.writer(file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
writer.writerow(headerNames)
for inst in self.instances:
for snapshot in inst:
writer.writerow(snapshot)
writer.writerow([""]*(self.bits+1))
m = MissingMPInstanceGenerator(bits=6,classCount=4)
m.exportInstances()