func start_worker(worker_id int) {
	logger := log.New(os.Stdout, fmt.Sprintf("WORKER(%d): ", worker_id), log.Ldate|log.Ltime)
	gl_min_cost := tsp_types.GlobalCostType{}
	gl_min_cost.Init(tsp_types.POSITIVE_INF)
	curr_task_id := -1
	runtime.GOMAXPROCS(runtime.NumCPU())
	destination := "127.0.0.1:5000"
	logger.Println("worker: connect to ", destination)
	conn, err := net.Dial("tcp", destination)
	if err != nil {
		logger.Printf("dial error: %v", err)
	}
	curr_task_info := CurrTaskInfo{curr_task_id, gl_min_cost}
	go listen_server(&conn, logger, &curr_task_info)
}
func SolveImpl(task tsp_types.TaskType, gl_min_cost *tsp_types.GlobalCostType) (tsp_types.AnswerType, bool) {
	if gl_min_cost.Get() < task.MinCost {
		return tsp_types.ERROR_ANSWER, false
	}
	if (task.Size == 0) || (task.Size == 1) {
		return tsp_types.ERROR_ANSWER, true
	}
	success, additional_cost := calculate_plus_cost(*task.Matrix, task.Size)
	if !success {
		return tsp_types.ERROR_ANSWER, true
	}
	task.CurrCost += additional_cost
	heavier_zero := find_heavier_zero(*task.Matrix, task.Size)
	// if task.Size is 2 end recursion
	if task.Size == 2 {
		next_city := heavier_zero.Col
		previous_city := heavier_zero.Row
		if ((*task.Matrix)[(previous_city^1)*2+(next_city^1)] == 0) &&
			((*task.Matrix)[(previous_city^1)*2+next_city] == tsp_types.POSITIVE_INF) &&
			((*task.Matrix)[previous_city*2+(next_city^1)] == tsp_types.POSITIVE_INF) {
			jumps := make([]tsp_types.JumpType, 2)
			jumps[0] = tsp_types.JumpType{task.RowMapping[heavier_zero.Row], task.ColMapping[heavier_zero.Col]}
			jumps[1] = tsp_types.JumpType{task.RowMapping[heavier_zero.Row^1], task.ColMapping[heavier_zero.Col^1]}
			for j := range task.Jumps {
				jumps = append(jumps, task.Jumps[j])
			}
			return tsp_types.AnswerType{jumps, task.CurrCost}, true
		} else {
			return tsp_types.ERROR_ANSWER, true
		}
	}
	// prepare data for recursive call
	sub_dt := generate_sub_task_data(task.Matrix, task.RowMapping, task.ColMapping, task.Jumps, heavier_zero, task.Size)
	//call this function recursively
	answer, less_global := SolveImpl(tsp_types.TaskType{sub_dt.Matrix, sub_dt.RowMapping, sub_dt.ColMapping, sub_dt.Jumps, task.CurrCost, task.MinCost, task.Size - 1}, gl_min_cost)
	if !less_global {
		return tsp_types.ERROR_ANSWER, false
	}
	//print_answer(answer, "GOT ANSWER")
	final_path := []tsp_types.JumpType{}
	if answer.Cost < task.MinCost {
		final_path = answer.Jumps
		task.MinCost = answer.Cost
	}
	//right_path
	if (task.CurrCost + heavier_zero.Weight) < task.MinCost {
		//correct first one
		(*task.Matrix)[heavier_zero.Row*task.Size+heavier_zero.Col] = tsp_types.POSITIVE_INF
		answer, less_global = SolveImpl(task, gl_min_cost)
		if !less_global {
			return tsp_types.ERROR_ANSWER, false
		}
		if answer.Cost < task.MinCost {
			final_path = answer.Jumps
			task.MinCost = answer.Cost
		}
	}
	// return answer
	if task.MinCost < tsp_types.POSITIVE_INF {
		return tsp_types.AnswerType{final_path, task.MinCost}, true
	} else {
		return tsp_types.ERROR_ANSWER, true
	}
}