def generate_parameters(self, parameter_id):
        """Returns a set of trial graph config, as a serializable object.
        An example configuration:
        ```json
        {
            "shared_id": [
                "4a11b2ef9cb7211590dfe81039b27670",
                "370af04de24985e5ea5b3d72b12644c9",
                "11f646e9f650f5f3fedc12b6349ec60f",
                "0604e5350b9c734dd2d770ee877cfb26",
                "6dbeb8b022083396acb721267335f228",
                "ba55380d6c84f5caeb87155d1c5fa654"
            ],
            "graph": {
                "layers": [
                    ...
                    {
                        "hash_id": "ba55380d6c84f5caeb87155d1c5fa654",
                        "is_delete": false,
                        "size": "x",
                        "graph_type": 0,
                        "output": [
                            6
                        ],
                        "output_size": 1,
                        "input": [
                            7,
                            1
                        ],
                        "input_size": 2
                    },
                    ...
                ]
            },
            "restore_dir": "/mnt/nfs/nni/ga_squad/87",
            "save_dir": "/mnt/nfs/nni/ga_squad/95"
        }
        ```
        `restore_dir` means the path in which to load the previous trained model weights. if null, init from stratch.
        `save_dir` means the path to save trained model for current trial.
        `graph` is the configuration of model network.
                Note: each configuration of layers has a `hash_id` property,
                which tells tuner & trial code whether to share trained weights or not.
        `shared_id` is the hash_id of layers that should be shared with previously trained model.
        """
        logger.debug('acquiring lock for param {}'.format(parameter_id))
        self.thread_lock.acquire()
        logger.debug('lock for current thread acquired')
        if not self.population:
            logger.debug("the len of poplution lower than zero.")
            raise Exception('The population is empty')
        pos = -1
        for i in range(len(self.population)):
            if self.population[i].result is None:
                pos = i
                break
        if pos != -1:
            indiv = copy.deepcopy(self.population[pos])
            self.population.pop(pos)
            graph_param = json.loads(graph_dumps(indiv.config))
        else:
            random.shuffle(self.population)
            if self.population[0].result < self.population[1].result:
                self.population[0] = self.population[1]
            indiv = copy.deepcopy(self.population[0])
            self.population.pop(1)
            indiv.mutation(indiv_id = self.generate_new_id())
            graph_param = json.loads(graph_dumps(indiv.config))
        param_json = {
            'graph': graph_param,
            'restore_dir': self.save_dir(indiv.parent_id),
            'save_dir': self.save_dir(indiv.indiv_id),
            'shared_id': list(indiv.shared_ids) if indiv.parent_id is not None else None,
        }
        logger.debug('generate_parameter return value is:')
        logger.debug(param_json)
        logger.debug('releasing lock')
        self.thread_lock.release()
        if indiv.parent_id is not None:
            logger.debug("new trial {} pending on parent experiment {}".format(indiv.indiv_id, indiv.parent_id))
            self.events[indiv.parent_id].wait()
        logger.debug("trial {} ready".format(indiv.indiv_id))
        return param_json