Project: s41467-025-58439-5 | Function: get_reward (python)

system: You are an expert Python programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow Python best practices and maintain consistent code style.
Return **only** the complete Python function code.

user: Complete this Python function:

**DESCRIPTION:** Calculates reward function for reinforcement learning agent in cancer risk gene identification. Evaluates the performance of selected gene sets based on statistical significance, coverage metrics, and biological relevance to guide the DQN agent toward identifying optimal cancer risk gene signatures.

**KEY TERMS:** {
  "reward": "RL optimization signal",
  "gene_sta": "gene statistical significance",
  "coverage": "patient coverage metric",
  "score_alpha": "biological relevance weight"
}

**CONTEXT CODE:**         s = np.expand_dims(s_, 0)
        s_all = np.repeat(s, len(action_sel), axis=0)

        actions_value = self.sess.run(self.q_target_, feed_dict={self.s_: s_all,
                                                                self.a_: action_emb})
        actions_value = np.squeeze(actions_value)
        qt = np.max(actions_value)
        return qt

    def choose_action(self, state,action_sel,action_index):
        """
        Implements epsilon-greedy action selection strategy for deep Q-network in cancer gene identification.

        This function balances exploration and exploitation by either selecting the action with highest Q-value
        or choosing a random action based on epsilon probability, enabling effective learning of optimal gene
        selection policies. The epsilon-greedy strategy is fundamental to RL-GenRisk's exploratory potential
        and performance in discovering meaningful gene combinations.

        Args:
            state: Current state representation
            action_sel: List of available actions for selection
            action_index: Index array for action availability

        Returns:
            action_index: Selected action index for gene selection

        Paper reference: "Throughout the training, we employed the ε-greedy strategy to choose actions
        based on Q values, thus boosting RL-GenRisk's exploratory potential"

        Formula: Action = argmax(Q(s,a)) with probability (1-ε), random otherwise
        Implementation: Epsilon-greedy strategy with Q-value computation, action selection,
                       and exploration-exploitation balance for optimal gene discovery
        """
        # MASKED: Epsilon-greedy action selection for DQN-based gene identification
        raise NotImplementedError("This function is masked for testing purposes. The function implements epsilon-greedy action selection strategy for deep Q-network in cancer gene identification, balancing exploration and exploitation by either selecting the action with highest Q-value or choosing a random action based on epsilon probability, enabling effective learning of optimal gene selection policies.")

    def getQt(self, feature_new, network_new,s_):
        all_embedding = self.getEmbedding(feature_new, network_new)
        action_sel, action_emb = self.getAction(all_embedding, network_new)
        qt = -100
        if len(action_sel)!= 0:
            s = np.expand_dims(s_, 0)
            s_all = np.repeat(s, len(action_sel), axis=0)
            actions_value = self.sess.run(self.q_target_, feed_dict={self.s_: s_all,
                                                                  self.a_: action_emb})
            actions_value = np.squeeze(actions_value)
            qt = np.max(actions_value)
        return qt


    def get_reward(self, gene_num, gene_name):
        """
        Calculates reward function for reinforcement learning agent in cancer risk gene identification.

        This function evaluates the performance of selected gene sets based on statistical significance,
        coverage metrics, and biological relevance to guide the DQN agent toward identifying optimal
        cancer risk gene signatures. The reward function is crucial for RL-GenRisk's performance in
        discovering meaningful gene combinations for cancer risk prediction.

        Args:
            gene_num: Dictionary mapping genes to patient numbers
            gene_name: List of gene names for indexing

        Returns:
            tuple: (statistical_significance_score, coverage_score, biological_relevance_score)

        Paper reference: "In reinforcement learning algorithms, the design of the reward is crucial
        to the performance of the algorithm"

        Formula: Reward = f(statistical_significance, coverage, biological_relevance)
        Implementation: Multi-objective reward calculation combining gene statistics, patient coverage,
                       and biological significance weights for optimal gene set selection
        """
        # MASKED: Reward function calculation for RL-based cancer gene identification
        raise NotImplementedError("This function is masked for testing purposes. The function calculates reward function for reinforcement learning agent in cancer risk gene identification, evaluating the performance of selected gene sets based on statistical significance, coverage metrics, and biological relevance to guide the DQN agent toward identifying optimal cancer risk gene signatures.")

    def getAcc(self, actions, patients, gene_name):
        cover_num = 0
        patients_num = len(patients.keys())
        for patient in patients:
            genes = patients[patient]
            for j in actions:
                if list(gene_name)[j] in genes:
                    cover_num += 1
                    break
        return cover_num / patients_num

    def Normalized_minmax(self,feature):
        X_scaler = preprocessing.MinMaxScaler()
        X_train = copy.deepcopy(feature)
        for i in range(len(feature[0])):
            X_train[:, [i]] = X_scaler.fit_transform(feature[:, [i]])
        return X_train

    def Normalized(self,feature):
        X_scaler = preprocessing.StandardScaler()
        X_train = X_scaler.fit_transform(feature)
        return X_train

    def get_feature(self,net,actions,weights,gene_name,gene_final):
        nodes_size = net.shape[0]
        feature = np.zeros((nodes_size, 3))
        i=0
        for gene in list(gene_name):
            feature[i][0] = np.sum(net[i])
            feature[i][1] = weights[gene]
            if gene in list(gene_final.keys()):
                feature[i][2] = len(gene_final[gene])
            i=i+1
        feature = self.Normalized_minmax(feature)
        return feature

    def step(self,network, action, gene_num, gene_name,weights): 
        actions = self.actions[:]
        node_prop = len(actions)
        weight_sum,patient_num,gene_sta_num = self.get_reward(gene_num, gene_name)
        score_new = self.score_alpha*weight_sum+(1-self.score_alpha)*patient_num*3000

        score = self.score_be-score_new
        score_st = self.score_sta-gene_sta_num
        score_pa = self.score_pat-patient_num
        reward = 0
        if score>0 or (self.score_be==0 and score==0):
            reward=reward+score_pa*50
        if score_st>0 or (self.score_sta==0 and score_st==0):
            reward=reward+2

        self.reward_all = self.reward_all + reward
        self.score_be = score_new
        self.score_sta = gene_sta_num
        self.score_pat = patient_num
        done = 0
        if len(actions) == 999:
            self.embedding=None
            done = 1
            # print(self.actions)
            train_acc = self.getAcc(actions, self.train_patient_data, gene_name)
            self.train_cover.append(train_acc)
            test_acc = self.getAcc(actions, self.test_patient_data, gene_name)
            self.test_cover.append(test_acc)
            # print('train_acc', train_acc, 'test_acc', test_acc)
            self.actions = []
            self.reward_list.append(reward)
            self.reward_all = 0
        return  reward, done, actions
    def remember(self, *args):
        self.memory.store_transition(*args)
        self.memory_counter+=1
    def clear_mem(self):
        self.memory.clear()


Complete the function implementation replacing "raise NotImplementedError".