class_docstr: Allocate the time resources when tuning multiple tasks together.
  This implements two strategies: "round-robin" and "gradient".
  
  Parameters
  ----------
  tasks: List[SearchTask]
      All tasks to tune
  task_weights: Optional[List[float]]
      The weights of tasks.
      If provided, the task scheduler will set the objective function to
      sum(weight[t] * latency[t]), where weight[t] is the weight of a task
      and the lantecy[t] is the lantecy of the task.
      If not provided, the task scheduer will assign equal weights to all
      tasks (i.e., the objective function is sum(latency[t])).
  objective_func: Optional[Callable[List[float] -> float]]
      The objective function to be minimized.
      The objective function accepts the current latencies of all tasks and returns the
      objective.
      If not provided, the objective is the weighted sum of the latencies of all tasks.
  strategy: str = "gradient"
      The scheduling strategy.
      "round-robin": Tune tasks in round robin order.
      "gradient" : Tune tasks with gradient descent.
  load_model_file: Optional[str]
      Load pre-trained model from this file. If this is None, the cost model will
      be trained from scratch.
  load_log_file: Optional[str]
      Load measurement records from this file. If it is not None, the status of the
      task scheduler, search policies and cost models will be restored according to this file.
  verbose: int = 1
      The level of verbosity. 0 means silent.
  alpha: float = 0.2
      The parameter used for 'gradient' strategy
  beta: float = 2
      The parameter used for 'gradient' strategy
  backward_window_size: int = 3
      The parameter used for 'gradient' strategy
  callbacks: Optional[List[TaskSchedulerCallback]]
      The task scheduler callbacks that will be called before and after tuning a task.
      If None, PrintTableInfo and LogEstimatedLatency callback will be used.
class_docstr_tok: ["Allocate","the","time","resources","when","tuning","multiple","tasks","together",".","This","implements","two","strategies",":","``","round-robin","''","and","``","gradient","''",".","Parameters","--","--","--","--","--","tasks",":","List","[","SearchTask","]","All","tasks","to","tune","task_weights",":","Optional","[","List","[","float","]","]","The","weights","of","tasks",".","If","provided",",","the","task","scheduler","will","set","the","objective","function","to","sum","(","weight","[","t","]","*","latency","[","t","]",")",",","where","weight","[","t","]","is","the","weight","of","a","task","and","the","lantecy","[","t","]","is","the","lantecy","of","the","task",".","If","not","provided",",","the","task","scheduer","will","assign","equal","weights","to","all","tasks","(","i.e.",",","the","objective","function","is","sum","(","latency","[","t","]",")",")",".","objective_func",":","Optional","[","Callable","[","List","[","float","]","-",">","float","]","]","The","objective","function","to","be","minimized",".","The","objective","function","accepts","the","current","latencies","of","all","tasks","and","returns","the","objective",".","If","not","provided",",","the","objective","is","the","weighted","sum","of","the","latencies","of","all","tasks",".","strategy",":","str","=","``","gradient","''","The","scheduling","strategy",".","``","round-robin","''",":","Tune","tasks","in","round","robin","order",".","``","gradient","''",":","Tune","tasks","with","gradient","descent",".","load_model_file",":","Optional","[","str","]","Load","pre-trained","model","from","this","file",".","If","this","is","None",",","the","cost","model","will","be","trained","from","scratch",".","load_log_file",":","Optional","[","str","]","Load","measurement","records","from","this","file",".","If","it","is","not","None",",","the","status","of","the","task","scheduler",",","search","policies","and","cost","models","will","be","restored","according","to","this","file",".","verbose",":","int","=","1","The","level","of","verbosity",".","0","means","silent",".","alpha",":","float","=","0.2","The","parameter","used","for","'gradient","'","strategy","beta",":","float","=","2","The","parameter","used","for","'gradient","'","strategy","backward_window_size",":","int","=","3","The","parameter","used","for","'gradient","'","strategy","callbacks",":","Optional","[","List","[","TaskSchedulerCallback","]","]","The","task","scheduler","callbacks","that","will","be","called","before","and","after","tuning","a","task",".","If","None",",","PrintTableInfo","and","LogEstimatedLatency","callback","will","be","used","."]
code: def __init__(
      self,
      tasks,
      task_weights=None,
      objective_func=None,
      strategy="gradient",
      load_model_file: str = None,
      load_log_file: str = None,
      alpha: float = 0.2,
      beta: float = 2,
      gamma: float = 0.5,
      backward_window_size: int = 3,
      callbacks=None,
  ):
      self.tasks = tasks
      if objective_func:  # use custom objective function
          self.objective_func = objective_func
      else:  # use weighted sum
          if task_weights:
              self.objective_func = lambda costs: sum(
                  c * w for c, w in zip(costs, task_weights)
              )
          else:
              self.objective_func = sum
  
      self.strategy = strategy
      self.load_log_file = load_log_file
      self.load_model_file = load_model_file
      self.alpha = alpha
      self.beta = beta
      self.gamma = gamma
      self.backward_window_size = backward_window_size
      self.callbacks = (
          callbacks
          if callbacks is not None
          else [
              PrintTableInfo(),
              LogEstimatedLatency("total_latency.tsv"),
          ]
      )
  
      assert len(self.tasks) != 0, "No tasks"
      assert self.strategy in ["round-robin", "gradient"]
  
      # task_cts[i] saves how many times task i is tuned
      self.task_cts = [0 for _ in range(len(self.tasks))]
  
      # task_best_cts[i] saves the round task i found the best latency
      self.task_best_cts = [0 for _ in range(len(self.tasks))]
  
      # task_costs_history[i] saves the latency history of task i
      self.task_costs_history = [[] for _ in range(len(self.tasks))]
  
      # best_costs[i] saves the best latency of task i
      self.best_costs = 1e10 * np.ones(len(self.tasks))
      self.cur_score = self._compute_score(self.best_costs)
  
      self.tune_option = self.measurer = self.search_policies = None
      self.ct = self.best_ct = self.best_score = self.tic = None
      self.num_measures_per_round = None
      self.dead_tasks = set()
  
      # Build similarity groups
      self.task_tags = []  # task_id -> tag
      self.tag_to_group_id = {}  # tag -> group_id
      self.group_task_ids = []  # group_id -> all task ids in this group
      self.flop_cts = []  # task_id -> the number of floating ops
      for i, task in enumerate(self.tasks):
          tag = derive_similarity_tag(task.compute_dag)
          self.task_tags.append(tag)
          self.flop_cts.append(task.compute_dag.flop_ct)
          if not tag:
              continue
  
          if tag not in self.tag_to_group_id:
              self.tag_to_group_id[tag] = len(self.tag_to_group_id)
              self.group_task_ids.append([])
          self.group_task_ids[self.tag_to_group_id[tag]].append(i)
  
imports: import os
  import time
  import math
  import logging
  import numpy
  from .search_policy import SearchPolicy, SketchPolicy, PreloadMeasuredStates
  from .cost_model import RandomModel, XGBModel
  from .utils import array_mean
  from .measure import ProgramMeasurer
  from .measure_record import RecordReader
  from .None import _ffi_api
label_desc: Use image node_id 1 to create a new TaskScheduler object  with example: obj = TaskScheduler(tasks, task_weights, objective_func, strategy, load_model_file, load_log_file, alpha, beta, gamma, backward_window_size, callbacks)