from constraint import *
import itertools as it
import Numberjack as nj
class EvenRandomGenerator:
"""Generate even random sequences according to a predefined TL ration (Ralph, 2014)"""
def __init__(self, choices, trials=64, tl=1):
self.tl, self.trials, self.choices = tl, trials, choices
def generate(self):
seqs = self._generate_initial_sequences()
return self._find_optimal_sequence(seqs, 0.2)
def _generate_initial_sequences(self):
"""
Generates initial sequence of items based on choices and number of desired trials.
In EvenRandom sequences, all stimuli have same number of appearances.
"""
pool = it.product(self.choices, repeat=self.trials)
return pool
def _find_optimal_sequence_numberjack(self,tl_ratio):
"""Optimize with Numberjack"""
cost = nj.Variable(0, 100, 'cost')
seqs = nj.Variable([]) # all sequences
model = nj.Model(
seqs.,
cost == self.calculate_tl_ratio(seq) - tl_ratio,
nj.Minimise(cost)
)
solver = model.load('Mistral')
if solver.solve():
solver.printStatistics()
else:
print("No solution with Numberjack")
def _find_optimal_sequence(self, sequences, tl_ratio):
"""Optimize a sequence to match a desired tl ratio with python-constraints"""
p = Problem()
# TODO add all possible values for seq (its domain)
p.addVariable("seq", list(sequences))
p.addConstraint(lambda s: self.calculate_tl_ratio(s) - tl_ratio < 0.05)
return p.getSolution()
@staticmethod
def calculate_tl_ratio(seq):
"""Calculates the T:L ratio of a sequence."""
targets = 0
lures = 0
for index, item in seq:
if item == seq[index-2]:
targets += 1
elif item == seq[index-1] or item == seq[index-3]:
lures += 1
# avoid division by zero
if lures == 0:
lures = 1
return targets/lures
if __name__ == '__main__':
generator = EvenRandomGenerator(['a', 'b', 'c'], trials = 4)
generated_seq = generator.generate()
print('Even Random Sequence: %s' % ''.join(generated_seq))