def test_random(ctx_factory):
    context = ctx_factory()
    queue = cl.CommandQueue(context)

    from pyopencl.clrandom import RanluxGenerator

    if has_double_support(context.devices[0]):
        dtypes = [np.float32, np.float64]
    else:
        dtypes = [np.float32]

    gen = RanluxGenerator(queue, 5120)

    for ary_size in [300, 301, 302, 303, 10007]:
        for dtype in dtypes:
            ran = cl_array.zeros(queue, ary_size, dtype)
            gen.fill_uniform(ran)
            assert (0 < ran.get()).all()
            assert (ran.get() < 1).all()

            gen.synchronize(queue)

            ran = cl_array.zeros(queue, ary_size, dtype)
            gen.fill_uniform(ran, a=4, b=7)
            assert (4 < ran.get()).all()
            assert (ran.get() < 7).all()

            ran = gen.normal(queue, (10007, ), dtype, mu=4, sigma=3)

    dtypes = [np.int32]
    for dtype in dtypes:
        ran = gen.uniform(queue, (10000007, ), dtype, a=200, b=300)
        assert (200 <= ran.get()).all()
        assert (ran.get() < 300).all()
Beispiel #2
0
def test_random(ctx_factory):
    context = ctx_factory()
    queue = cl.CommandQueue(context)

    from pyopencl.clrandom import RanluxGenerator

    if has_double_support(context.devices[0]):
        dtypes = [np.float32, np.float64]
    else:
        dtypes = [np.float32]

    gen = RanluxGenerator(queue, 5120)

    for ary_size in [300, 301, 302, 303, 10007]:
        for dtype in dtypes:
            ran = cl_array.zeros(queue, ary_size, dtype)
            gen.fill_uniform(ran)
            assert (0 < ran.get()).all()
            assert (ran.get() < 1).all()

            gen.synchronize(queue)

            ran = cl_array.zeros(queue, ary_size, dtype)
            gen.fill_uniform(ran, a=4, b=7)
            assert (4 < ran.get()).all()
            assert (ran.get() < 7).all()

            ran = gen.normal(queue, (10007,), dtype, mu=4, sigma=3)

    dtypes = [np.int32]
    for dtype in dtypes:
        ran = gen.uniform(queue, (10000007,), dtype, a=200, b=300)
        assert (200 <= ran.get()).all()
        assert (ran.get() < 300).all()
class GeneticAlgorithmOpenCL(GeneticAlgorithm):
    class Population:
        # Crossover modes
        CM_SEPARATE = 0 # Separate probabilities for translation/rotation genes
        CM_COMBINE = 1  # Combined probability for translation/rotation genes

        def __init__(self, size = 0, dna_size = 0, \
                     cl_ctx = None, cl_queue = None, rng = None, cl_prg = None):
            self.size = size
            self.dna_size = dna_size

            # OpenCL
            self.cl_ctx = cl_ctx
            self.cl_queue = cl_queue
            self.rng = rng
            self.cl_prg = cl_prg
            # Matrix of i by j for individuals and genes (DNA) respectively
            self.individuals_np = None
            self.individuals_buf = None
            self.new_individuals_np = None
            self.new_individuals_buf = None
            self.crossover_translation_mode_np = np.array([], dtype = int)
            self.crossover_translation_mode_buf = None
            self.crossover_rotation_mode_np = np.array([], dtype = int)
            self.crossover_rotation_mode_buf = None
            self.crossover_probability_np = np.array([], dtype = float)
            self.crossover_probability_buf = None
            self.mutation_probability_np = np.array([], dtype = float)
            self.mutation_probability_buf = None

        def setup_opencl(self):
            mf = cl.mem_flags
            # Setup device buffers
            self.individuals_buf = cl.array.zeros(self.cl_queue, \
                                                  (self.size, self.dna_size), \
                                                  dtype = float)
            self.new_individuals_buf = cl.array.zeros(self.cl_queue, \
                                                      (self.size, self.dna_size), \
                                                      dtype = float)
            self.crossover_translation_mode_np = np.array([self.crossover_translation_mode], \
                                                          dtype = int)
            self.crossover_translation_mode_buf =  cl.Buffer(self.cl_ctx, \
                                                             mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                                             hostbuf = self.crossover_translation_mode_np)
            self.crossover_rotation_mode_np = np.array([self.crossover_rotation_mode], \
                                                       dtype = int)
            self.crossover_rotation_mode_buf =  cl.Buffer(self.cl_ctx, \
                                                          mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                                          hostbuf = self.crossover_rotation_mode_np)
            self.crossover_probability_np = np.array([self.crossover_probability], \
                                                     dtype = float)
            self.crossover_probability_buf =  cl.Buffer(self.cl_ctx, \
                                                        mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                                        hostbuf = self.crossover_probability_np)
            self.mutation_probability_np = np.array([self.mutation_probability], \
                                                    dtype = float)
            self.mutation_probability_buf =  cl.Buffer(self.cl_ctx, \
                                                       mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                                       hostbuf = self.mutation_probability_np)

        def __repr__(self):
            self.individuals_np = self.individuals_buf.get()

            ret = "Individuals:\n"
            for idx, individual in enumerate(self.individuals_np):
                ret += "[%3d] " % (idx + 1)
                ret += "%6.2f %6.2f %6.2f | " % (individual[0], \
                                                 individual[1], \
                                                 individual[2])
                ret += "%6.2f %6.2fi %6.2fj %6.2fk | " % (individual[3], \
                                                          individual[4], \
                                                          individual[5], \
                                                          individual[6])
                for torsion in individual[7:]:
                    ret += " %5.2f" % torsion
                ret += "\n"
            return ret

        def get_individual(self, idx = 0):
            self.individuals_np = self.individuals_buf.get()
            return self.individuals_np[idx]

        def create(self, dna_size_buf = None, dock = None):
            self.rng.fill_uniform(self.individuals_buf)
            # Construct individuals
            self.cl_prg.construct_individuals(self.cl_queue, \
                                              (self.size,), None, \
                                              dock.lo_grid_buf, \
                                              dock.dist_grid_buf, \
                                              dna_size_buf, \
                                              self.individuals_buf.data)

        def scoring(self, dock = None, \
                    cl_ctx = None, cl_queue = None):
            dock.reset_poses(self.size, self.individuals_buf, \
                             cl_ctx, cl_queue)
            dock.calc_energy()

        def min_score(self, dock = None):
            scores = dock.e_totals_buf.get()
            return scores.min()

        def crossover(self, parents_idx, ttl_torsions, rng):
            return None

        def mutate(self, individual, mutation_chance, \
                   lo_grid, hi_grid, ttl_torsions, rng):
            return None

    class Settler(Population):
        def __init__(self, size = 0, dna_size = 0, \
                     cl_ctx = None, cl_queue = None, rng = None, cl_prg = None):
            GeneticAlgorithmOpenCL.Population.__init__(self, size, dna_size, \
                                                       cl_ctx, cl_queue, \
                                                       rng, cl_prg)
            self.crossover_translation_mode = self.CM_COMBINE
            self.crossover_rotation_mode = self.CM_COMBINE
            self.crossover_probability = 0.5
            self.mutation_probability = 0.25
            # OpenCL
            self.setup_opencl()

    class Nomad(Population):
        def __init__(self, size = 0, dna_size = 0, \
                     cl_ctx = None, cl_queue = None, rng = None, cl_prg = None):
            GeneticAlgorithmOpenCL.Population.__init__(self, size, dna_size, \
                                                       cl_ctx, cl_queue, \
                                                       rng, cl_prg)
            self.crossover_translation_mode = self.CM_SEPARATE
            self.crossover_rotation_mode = self.CM_SEPARATE
            self.crossover_probability = 0.5
            self.mutation_probability = 0.75
            # OpenCL
            self.setup_opencl()

    def __init__(self, dock = None, cl_device_type = None):
        GeneticAlgorithm.__init__(self, dock)
        # OpenCL
        self.cl_device_type = cl_device_type
        if self.cl_device_type == "gpu":
            self.cl_ctx = cl.Context(dev_type = cl.device_type.GPU)
        elif self.cl_device_type == "cpu":
            self.cl_ctx = cl.Context(dev_type = cl.device_type.CPU)
        else: # manual selection
            self.cl_ctx = cl.create_some_context()
        self.cl_queue = cl.CommandQueue(self.cl_ctx)
        self.cl_filename = "./OpenCL/GeneticAlgorithm.cl"
        fh = open(self.cl_filename, 'r')
        cl_code = "".join(fh.readlines())
        self.cl_prg = cl.Program(self.cl_ctx, cl_code).build()
        self.rng = None
        # OpenCL buffer
        self.population_size_np = np.array([], dtype = int)
        self.population_size_buf =  None
        self.dna_size_np = np.array([], dtype = int)
        self.dna_size_buf = None
        self.max_inherited_prob_np = np.array([], dtype = int)
        self.max_inherited_prob_buf = None
        self.normalizer_np = np.array([], dtype = int)
        self.normalizer_buf = None
        self.chances_np = None
        self.chances_buf = None
        self.chances_sum_buf = None
        self.dna1_buf = None
        self.dna2_buf = None
        self.ttl_reproduction_rns_np = np.array([], dtype = int)
        self.ttl_reproduction_rns_buf = None
        self.reproduction_rns_buf = None
        self.mutation_chance_np = np.array([], dtype = float)
        self.mutation_chance_buf = None

    def setup_opencl(self):
        # OpenCL setup
        self.dock.setup_opencl(self.cl_ctx, self.cl_queue)

        # Setup OpenCL device buffer
        mf = cl.mem_flags
        self.population_size_np = np.array([self.population_size], dtype = int)
        self.population_size_buf =  cl.Buffer(self.cl_ctx, \
                                              mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                              hostbuf = self.population_size_np)
        self.dna_size = 3 + 4 + self.dock.get_total_torsions()
        self.dna_size_np = np.array([self.dna_size], dtype = int)
        self.dna_size_buf = cl.Buffer(self.cl_ctx, \
                                      mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                      hostbuf = self.dna_size_np)
        self.max_inherited_prob_np = np.array([self.max_inherited_prob], \
                                              dtype = int)
        self.max_inherited_prob_buf = cl.Buffer(self.cl_ctx, \
                                                mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                                hostbuf = self.max_inherited_prob_np)
        self.normalizer_np = np.array([self.ttl_ligand_atoms], dtype = int)
        self.normalizer_buf = cl.Buffer(self.cl_ctx, \
                                        mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                        hostbuf = self.normalizer_np)
        self.chances_buf = cl.array.zeros(self.cl_queue, (self.population_size), \
                                          dtype = int)
        self.chances_sum_buf = cl.array.zeros(self.cl_queue, (self.population_size), \
                                              dtype = int)
        self.dna1_buf = cl.array.zeros(self.cl_queue, \
                                       (self.population_size, self.dna_size), \
                                       dtype = float)
        self.dna2_buf = cl.array.zeros(self.cl_queue, \
                                       (self.population_size, self.dna_size), \
                                       dtype = float)
        # Reproduction random numbers needed per individual:
        # - Selecting parents:  2
        # - Crossing over:      Use new_individuals_buf
        # - Mutation:           1 + 2 + total torsions
        # - Mutation pose:      3 + 4 + total torsions
        ttl_reproduction_rns = 2 + 1 + 2 + self.ttl_torsions + \
                               3 + 4 + self.ttl_torsions
        self.ttl_reproduction_rns_np = np.array([ttl_reproduction_rns], \
                                                dtype = int)
        self.ttl_reproduction_rns_buf = cl.Buffer(self.cl_ctx, \
                                                  mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                                  hostbuf = self.ttl_reproduction_rns_np)
        self.reproduction_rns_buf = cl.array.zeros(self.cl_queue, \
                                                   (self.population_size, ttl_reproduction_rns), \
                                                   dtype = float)
        self.mutation_chance_np = np.array([self.mutation_chance], dtype = float)
        self.mutation_chance_buf = cl.Buffer(self.cl_ctx, \
                                             mf.READ_ONLY | mf.COPY_HOST_PTR, \
                                             hostbuf = self.mutation_chance_np)
        # Setup OpenCL buffer for docking object
        self.dock.setup_opencl_buffer(self.population_size, \
                                      self.cl_ctx, self.cl_queue)

    def setup_rng(self):
        self.rng = RanluxGenerator(self.cl_queue)

    def setup(self):
        # Call parent setup
        GeneticAlgorithm.setup(self)
        # OpenCL
        self.setup_opencl()

    def select(self, population):
        # Get individual scores
        population.scoring(self.dock, self.cl_ctx, self.cl_queue)
        self.cl_prg.calc_chances(self.cl_queue, (self.population_size,), None, \
                                 self.dock.e_totals_buf.data, \
                                 self.normalizer_buf, \
                                 self.max_inherited_prob_buf, \
                                 self.chances_buf.data)

    def reproduce(self, population):
        self.rng.fill_uniform(population.new_individuals_buf)
        self.rng.fill_uniform(self.reproduction_rns_buf)

        self.cl_prg.reproduce(self.cl_queue, (self.population_size,), None, \
                              self.population_size_buf, \
                              self.chances_buf.data, \
                              self.ttl_reproduction_rns_buf, \
                              self.reproduction_rns_buf.data, \

                              self.dna_size_buf, \
                              population.individuals_buf.data, \

                              population.crossover_translation_mode_buf, \
                              population.crossover_rotation_mode_buf, \
                              population.crossover_probability_buf, \

                              self.mutation_chance_buf, \
                              population.mutation_probability_buf, \
                              self.dock.ttl_torsions_buf, \
                              self.dock.lo_grid_buf, \
                              self.dock.dist_grid_buf, \

                              self.chances_sum_buf.data, \
                              self.dna1_buf.data, \
                              self.dna2_buf.data, \

                              population.new_individuals_buf.data)

        cl.enqueue_copy(self.cl_queue, population.individuals_buf.data, \
                        population.new_individuals_buf.data)

    def run(self):
        self.setup()
        # Define multiple population
        self.nomad = self.Nomad(self.population_size, self.dna_size, \
                                self.cl_ctx, self.cl_queue, \
                                self.rng, self.cl_prg)
        self.settler = self.Settler(self.population_size, self.dna_size, \
                                    self.cl_ctx, self.cl_queue, \
                                    self.rng, self.cl_prg)
        population_min_scores = []
        for community_idx in xrange(self.community_size):
            tic = time()
            # Nomad portion
            nomad_min_score = float("inf")
            self.nomad.create(self.dna_size_buf, self.dock)
            if VERBOSE: print self.nomad
            for gen_idx in xrange(self.num_gen):
                self.select(self.nomad)
                self.reproduce(self.nomad)
            nomad_min_score = self.nomad.min_score(self.dock)

            # Settler portion
            settler_min_score = float("inf")
            cl.enqueue_copy(self.cl_queue, self.settler.individuals_buf.data, \
                            self.nomad.individuals_buf.data)
            if VERBOSE: print self.settler
            for gen_idx in xrange(self.num_gen):
                self.select(self.settler)
                self.reproduce(self.settler)
            if VERBOSE: print self.settler
            settler_min_score = self.settler.min_score(self.dock)

            population_min_scores.append([nomad_min_score, settler_min_score])
            toc = time()
            print "Elapsed time community %4d: %10.2f - Minimum Scores: %12.3f, %12.3f" \
                  % (community_idx + 1, toc - tic, \
                     nomad_min_score, settler_min_score)

        print "Community Minimum Scores: %s" % population_min_scores