func SolveTask(client ClientInfo, task_data []byte, task_id int) {
	fmt.Println("SolveTask: Start")
	task := tsp_types.TaskType{}
	task.FromXml(task_data)

	new_task := &TaskQueueItem{}
	new_task.Init(task_id)
	task_queue.PushBack(new_task)

	go TaskHandler(new_task)
	go AnswerCombiner(new_task)

	//split
	enabled, task1, task2 := tsp_solver.CrusherImpl(&task)
	for enabled {
		new_task.SubTasks <- task1
		new_task.SentTasksCount.Inc()
		new_task.PreparedTasks <- true
		task2.MinCost = new_task.CurrMinCost.Get()
		enabled, task1, task2 = tsp_solver.CrusherImpl(task2)
	}
	new_task.PrepareFinished = true
	new_task.PreparedTasks <- false
	final_answer := <-new_task.FinalAnswer

	msg := []byte(final_answer.ToXml())
	err := binary.Write(*client.Conn, binary.LittleEndian, int64(len(msg)))
	if err != nil {
		fmt.Printf("[SolveTask] Write data error: %v", err)
		return
	}
	(*client.Conn).Write(msg)
	task_queue.Remove(new_task.ID)
	fmt.Println("[SolveTask] Finish")
}
func CrusherImpl(task *tsp_types.TaskType) (bool, *tsp_types.TaskType, *tsp_types.TaskType) {
	success, additional_cost := calculate_plus_cost(*task.Matrix, task.Size)
	if success != true {
		return false, nil, nil
	}
	task.CurrCost += additional_cost
	heavier_zero := find_heavier_zero(*task.Matrix, task.Size)
	//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
	task1 := tsp_types.TaskType{sub_dt.Matrix, sub_dt.RowMapping, sub_dt.ColMapping, sub_dt.Jumps, task.CurrCost, task.MinCost, task.Size - 1}
	(*task.Matrix)[heavier_zero.Row*task.Size+heavier_zero.Col] = tsp_types.POSITIVE_INF
	return true, &task1, task
}
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
	}
}