"""Compute score for Divergent Association Task,
a quick and simple measure of creativity
(Copyright 2021 Jay Olson; see LICENSE)"""

import re
import itertools
import numpy
import scipy.spatial.distance


class Model:
    """Create model to compute DAT"""

    def __init__(self, model="glove.840B.300d.txt", dictionary="words.txt", pattern="^[a-z][a-z-]*[a-z]$"):
        """Join model and words matching pattern in dictionary"""

        # Keep unique words matching pattern from file
        words = set()
        with open(dictionary, "r", encoding="utf8") as f:
            for line in f:
                if re.match(pattern, line):
                    words.add(line.rstrip("\n"))

        # Join words with model
        vectors = {}
        with open(model, "r", encoding="utf8") as f:
            for line in f:
                tokens = line.split(" ")
                word = tokens[0]
                if word in words:
                    vector = numpy.asarray(tokens[1:], "float32")
                    vectors[word] = vector
        self.vectors = vectors


    def validate(self, word):
        """Clean up word and find best candidate to use"""

        # Strip unwanted characters
        clean = re.sub(r"[^a-zA-Z- ]+", "", word).strip().lower()
        if len(clean) <= 1:
            return None # Word too short

        # Generate candidates for possible compound words
        # "valid" -> ["valid"]
        # "cul de sac" -> ["cul-de-sac", "culdesac"]
        # "top-hat" -> ["top-hat", "tophat"]
        candidates = []
        if " " in clean:
            candidates.append(re.sub(r" +", "-", clean))
            candidates.append(re.sub(r" +", "", clean))
        else:
            candidates.append(clean)
            if "-" in clean:
                candidates.append(re.sub(r"-+", "", clean))
        for cand in candidates:
            if cand in self.vectors:
                return cand # Return first word that is in model
        return None # Could not find valid word


    def distance(self, word1, word2):
        """Compute cosine distance (0 to 2) between two words"""

        return scipy.spatial.distance.cosine(self.vectors.get(word1), self.vectors.get(word2))


    def dat(self, words, minimum=7):
        """Compute DAT score"""
        # Keep only valid unique words
        uniques = []
        for word in words:
            valid = self.validate(word)
            if valid and valid not in uniques:
                uniques.append(valid)

        # Keep subset of words
        if len(uniques) >= minimum:
            subset = uniques[:minimum]
        else:
            return None # Not enough valid words

        # Compute distances between each pair of words
        distances = []
        for word1, word2 in itertools.combinations(subset, 2):
            dist = self.distance(word1, word2)
            distances.append(dist)

        # Compute the DAT score (average semantic distance multiplied by 100)
        return (sum(distances) / len(distances)) * 100

324b6d13a40343285d171153b87448902b7494bf
<mask token>


class Model:
    <mask token>

    def __init__(self, model='glove.840B.300d.txt', dictionary='words.txt',
        pattern='^[a-z][a-z-]*[a-z]$'):
        """Join model and words matching pattern in dictionary"""
        words = set()
        with open(dictionary, 'r', encoding='utf8') as f:
            for line in f:
                if re.match(pattern, line):
                    words.add(line.rstrip('\n'))
        vectors = {}
        with open(model, 'r', encoding='utf8') as f:
            for line in f:
                tokens = line.split(' ')
                word = tokens[0]
                if word in words:
                    vector = numpy.asarray(tokens[1:], 'float32')
                    vectors[word] = vector
        self.vectors = vectors

    def validate(self, word):
        """Clean up word and find best candidate to use"""
        clean = re.sub('[^a-zA-Z- ]+', '', word).strip().lower()
        if len(clean) <= 1:
            return None
        candidates = []
        if ' ' in clean:
            candidates.append(re.sub(' +', '-', clean))
            candidates.append(re.sub(' +', '', clean))
        else:
            candidates.append(clean)
            if '-' in clean:
                candidates.append(re.sub('-+', '', clean))
        for cand in candidates:
            if cand in self.vectors:
                return cand
        return None

    def distance(self, word1, word2):
        """Compute cosine distance (0 to 2) between two words"""
        return scipy.spatial.distance.cosine(self.vectors.get(word1), self.
            vectors.get(word2))
    <mask token>

<mask token>


class Model:
    <mask token>

    def __init__(self, model='glove.840B.300d.txt', dictionary='words.txt',
        pattern='^[a-z][a-z-]*[a-z]$'):
        """Join model and words matching pattern in dictionary"""
        words = set()
        with open(dictionary, 'r', encoding='utf8') as f:
            for line in f:
                if re.match(pattern, line):
                    words.add(line.rstrip('\n'))
        vectors = {}
        with open(model, 'r', encoding='utf8') as f:
            for line in f:
                tokens = line.split(' ')
                word = tokens[0]
                if word in words:
                    vector = numpy.asarray(tokens[1:], 'float32')
                    vectors[word] = vector
        self.vectors = vectors

    def validate(self, word):
        """Clean up word and find best candidate to use"""
        clean = re.sub('[^a-zA-Z- ]+', '', word).strip().lower()
        if len(clean) <= 1:
            return None
        candidates = []
        if ' ' in clean:
            candidates.append(re.sub(' +', '-', clean))
            candidates.append(re.sub(' +', '', clean))
        else:
            candidates.append(clean)
            if '-' in clean:
                candidates.append(re.sub('-+', '', clean))
        for cand in candidates:
            if cand in self.vectors:
                return cand
        return None

    def distance(self, word1, word2):
        """Compute cosine distance (0 to 2) between two words"""
        return scipy.spatial.distance.cosine(self.vectors.get(word1), self.
            vectors.get(word2))

    def dat(self, words, minimum=7):
        """Compute DAT score"""
        uniques = []
        for word in words:
            valid = self.validate(word)
            if valid and valid not in uniques:
                uniques.append(valid)
        if len(uniques) >= minimum:
            subset = uniques[:minimum]
        else:
            return None
        distances = []
        for word1, word2 in itertools.combinations(subset, 2):
            dist = self.distance(word1, word2)
            distances.append(dist)
        return sum(distances) / len(distances) * 100

<mask token>


class Model:
    """Create model to compute DAT"""

    def __init__(self, model='glove.840B.300d.txt', dictionary='words.txt',
        pattern='^[a-z][a-z-]*[a-z]$'):
        """Join model and words matching pattern in dictionary"""
        words = set()
        with open(dictionary, 'r', encoding='utf8') as f:
            for line in f:
                if re.match(pattern, line):
                    words.add(line.rstrip('\n'))
        vectors = {}
        with open(model, 'r', encoding='utf8') as f:
            for line in f:
                tokens = line.split(' ')
                word = tokens[0]
                if word in words:
                    vector = numpy.asarray(tokens[1:], 'float32')
                    vectors[word] = vector
        self.vectors = vectors

    def validate(self, word):
        """Clean up word and find best candidate to use"""
        clean = re.sub('[^a-zA-Z- ]+', '', word).strip().lower()
        if len(clean) <= 1:
            return None
        candidates = []
        if ' ' in clean:
            candidates.append(re.sub(' +', '-', clean))
            candidates.append(re.sub(' +', '', clean))
        else:
            candidates.append(clean)
            if '-' in clean:
                candidates.append(re.sub('-+', '', clean))
        for cand in candidates:
            if cand in self.vectors:
                return cand
        return None

    def distance(self, word1, word2):
        """Compute cosine distance (0 to 2) between two words"""
        return scipy.spatial.distance.cosine(self.vectors.get(word1), self.
            vectors.get(word2))

    def dat(self, words, minimum=7):
        """Compute DAT score"""
        uniques = []
        for word in words:
            valid = self.validate(word)
            if valid and valid not in uniques:
                uniques.append(valid)
        if len(uniques) >= minimum:
            subset = uniques[:minimum]
        else:
            return None
        distances = []
        for word1, word2 in itertools.combinations(subset, 2):
            dist = self.distance(word1, word2)
            distances.append(dist)
        return sum(distances) / len(distances) * 100

<mask token>
import re
import itertools
import numpy
import scipy.spatial.distance


class Model:
    """Create model to compute DAT"""

    def __init__(self, model='glove.840B.300d.txt', dictionary='words.txt',
        pattern='^[a-z][a-z-]*[a-z]$'):
        """Join model and words matching pattern in dictionary"""
        words = set()
        with open(dictionary, 'r', encoding='utf8') as f:
            for line in f:
                if re.match(pattern, line):
                    words.add(line.rstrip('\n'))
        vectors = {}
        with open(model, 'r', encoding='utf8') as f:
            for line in f:
                tokens = line.split(' ')
                word = tokens[0]
                if word in words:
                    vector = numpy.asarray(tokens[1:], 'float32')
                    vectors[word] = vector
        self.vectors = vectors

    def validate(self, word):
        """Clean up word and find best candidate to use"""
        clean = re.sub('[^a-zA-Z- ]+', '', word).strip().lower()
        if len(clean) <= 1:
            return None
        candidates = []
        if ' ' in clean:
            candidates.append(re.sub(' +', '-', clean))
            candidates.append(re.sub(' +', '', clean))
        else:
            candidates.append(clean)
            if '-' in clean:
                candidates.append(re.sub('-+', '', clean))
        for cand in candidates:
            if cand in self.vectors:
                return cand
        return None

    def distance(self, word1, word2):
        """Compute cosine distance (0 to 2) between two words"""
        return scipy.spatial.distance.cosine(self.vectors.get(word1), self.
            vectors.get(word2))

    def dat(self, words, minimum=7):
        """Compute DAT score"""
        uniques = []
        for word in words:
            valid = self.validate(word)
            if valid and valid not in uniques:
                uniques.append(valid)
        if len(uniques) >= minimum:
            subset = uniques[:minimum]
        else:
            return None
        distances = []
        for word1, word2 in itertools.combinations(subset, 2):
            dist = self.distance(word1, word2)
            distances.append(dist)
        return sum(distances) / len(distances) * 100

"""Compute score for Divergent Association Task,
a quick and simple measure of creativity
(Copyright 2021 Jay Olson; see LICENSE)"""

import re
import itertools
import numpy
import scipy.spatial.distance


class Model:
    """Create model to compute DAT"""

    def __init__(self, model="glove.840B.300d.txt", dictionary="words.txt", pattern="^[a-z][a-z-]*[a-z]$"):
        """Join model and words matching pattern in dictionary"""

        # Keep unique words matching pattern from file
        words = set()
        with open(dictionary, "r", encoding="utf8") as f:
            for line in f:
                if re.match(pattern, line):
                    words.add(line.rstrip("\n"))

        # Join words with model
        vectors = {}
        with open(model, "r", encoding="utf8") as f:
            for line in f:
                tokens = line.split(" ")
                word = tokens[0]
                if word in words:
                    vector = numpy.asarray(tokens[1:], "float32")
                    vectors[word] = vector
        self.vectors = vectors


    def validate(self, word):
        """Clean up word and find best candidate to use"""

        # Strip unwanted characters
        clean = re.sub(r"[^a-zA-Z- ]+", "", word).strip().lower()
        if len(clean) <= 1:
            return None # Word too short

        # Generate candidates for possible compound words
        # "valid" -> ["valid"]
        # "cul de sac" -> ["cul-de-sac", "culdesac"]
        # "top-hat" -> ["top-hat", "tophat"]
        candidates = []
        if " " in clean:
            candidates.append(re.sub(r" +", "-", clean))
            candidates.append(re.sub(r" +", "", clean))
        else:
            candidates.append(clean)
            if "-" in clean:
                candidates.append(re.sub(r"-+", "", clean))
        for cand in candidates:
            if cand in self.vectors:
                return cand # Return first word that is in model
        return None # Could not find valid word


    def distance(self, word1, word2):
        """Compute cosine distance (0 to 2) between two words"""

        return scipy.spatial.distance.cosine(self.vectors.get(word1), self.vectors.get(word2))


    def dat(self, words, minimum=7):
        """Compute DAT score"""
        # Keep only valid unique words
        uniques = []
        for word in words:
            valid = self.validate(word)
            if valid and valid not in uniques:
                uniques.append(valid)

        # Keep subset of words
        if len(uniques) >= minimum:
            subset = uniques[:minimum]
        else:
            return None # Not enough valid words

        # Compute distances between each pair of words
        distances = []
        for word1, word2 in itertools.combinations(subset, 2):
            dist = self.distance(word1, word2)
            distances.append(dist)

        # Compute the DAT score (average semantic distance multiplied by 100)
        return (sum(distances) / len(distances)) * 100
