【问题标题】:How to optimize scoring in a match如何在比赛中优化得分
【发布时间】:2016-12-21 04:44:43
【问题描述】:

我正在为比赛设计一个决策系统,要求玩家瞄准不同的目标。在不同目标上得分的概率各不相同,每个目标得分的球员越多,在那个目标上得分的概率就会降低。玩家的尝试机会有限。

我想到的只有马尔可夫链和博弈论,但我不知道如何实现它们,我想知道是否有任何其他数学技术可以最大化我的分数。

我将非常感谢任何指导。

【问题讨论】:

  • 您能描述一下您要解决的实际问题吗?当前的描述不够详细,无法以任何有用的方式回答问题。
  • 只需将球射到空间有限的目标上,一个人越多,剩余的空间就越小。即使我使用相同的参数,碰撞和其他因素也无法保证我可以在目标上得分,因此在目标上得分的可能性会随着已经在上面的球数量而降低。

标签: algorithm optimization mathematical-optimization markov-chains game-theory


【解决方案1】:

马尔可夫过程:非解决方案

我认为马尔可夫过程在这里行不通。马尔可夫性质要求过程未来状态的概率分布仅取决于其当前状态(或有限数量的过去 st

如果过程的未来状态的条件概率分布(以过去和现在状态为条件)仅取决于当前状态,而不取决于之前的事件序列,则随机过程具有马尔可夫性质。由于每次成功命中目标的概率都会降低,因此您的流程的未来取决于其过去,因此您的流程不是马尔可夫。

递归蛮力搜索:一个适当的解决方案

解决此问题的一种方法是探索搜索树。以下 C++ 代码描述了该操作:

#include <limits>
#include <iostream>
#include <cstdio>
#include <vector>

std::vector<float> ScoreOn(const std::vector<float> &probs, int target){
  std::vector<float> temp = probs; //Copy original array to avoid corrupting it
  temp[target]          *= 0.9;    //Decrease the probability
  return temp;                     //Return the new array
}

std::pair<float,int> Choice(
  const std::vector<float> &probs,
  const std::vector<float> &values,
  int depth
){
  if(depth==0)                      //We gotta cut this off somewhere
    return std::make_pair(0.0,-1);  //Return 0 value at the end of time

  //Any real choice will have a value greater than this
  float valmax = -std::numeric_limits<float>::infinity();
  //Will shortly be filled with a real choice value
  int choice = -1;

  //Loop through all targets
  for(int t=0;t<probs.size();t++){
    float hit_value  = values[t]+Choice(ScoreOn(probs,t),values,depth-1).first;
    float miss_value = 0        +Choice(probs           ,values,depth-1).first;
    float val        = probs[t]*hit_value+(1-probs[t])*miss_value;
    if(val>valmax){ //Is current target a better choice?
      valmax = val;
      choice = t;
    }
  }
  return std::make_pair(valmax,choice);
}

int main(){
  //Generate sample data and print the current best answer
  int target_count = 8; //Number of targets
  std::vector<float> probs,values;
  for(int t=0;t<target_count;t++){
    probs.push_back(rand()/(float)RAND_MAX);
    values.push_back(80.0*(rand()/(float)RAND_MAX));
  }

  std::cout<<Choice(probs,values,6).first<<std::endl;
}

现在,考虑尝试击中目标。如果我们击中它,我们行动的价值(称为H)是目标的价值加上我们所有未来行动的价值。如果我们错过了 (M),那么价值为零加上我们所有未来行动的价值。我们通过每次发生的概率p对这些值加权,得到等式:

值 = pH+(1-p)M

我们以相同的方式计算未来值,从而生成递归函数。由于这可能永远持续下去,我们将递归的深度限制在一定数量的级别上。因为在每个级别,决策树针对每个t 目标沿着两条路径拆分,因此树中有(2t)**(Depth+1)-1 节点。因此,明智地选择你的深度以避免永远思考。

上面的代码,在我的 Intel i5 M480 cpu(现在大约五年前)上,深度 = 5 的优化运行时间为 0.044 秒,深度 = 6 的优化运行时间为 0.557 秒。对于深度=6,树中有 268,435,455 个节点,每个叶子的可能性只有 16,777,216 分之一的可能性被实现。除非你的价值函数是奇怪的,否则没有必要考虑更远的未来。

Branch and Bound:改进的解决方案

但是,如果您确实需要探索更大的空间或走得更快,您可以考虑使用Branch and Bound methods。这以相同的方式工作,除了我们选择不扩展任何可证明小于我们已经找到的解决方案的子树。证明严格的上限成为主要挑战。

【讨论】:

  • 这样的蛮力方法可能不适合实时决策,比如我有8个目标,40次尝试的机会,一台小电脑不会在短时间内解决所有情况。至少我需要一些方法来砍掉某些树枝。
  • @Newb:我觉得还是可以的。我用一些时间值和更正的状态空间大小覆盖率编辑了我的答案。
  • 可能我误解了马尔可夫链,我认为每个目标上的得分是一个状态空间(S_t-1),得分的概率是转移矩阵(P_t-1)。下一轮状态(S_t)的可能性仅由上一轮决定。 S_t = P_t-1 + S_t-1。可以转换为 P( S_t = A | S_t-1 = B) , P( S_t-1 = B | S_t-2 = C), P( S_t-2 = C|S_t-3 = D)...
  • 但是从一种状态转换到另一种状态的概率并不仅仅是目标大小的函数:我们基于某种最大化原则进行转换。因此,这种转变并不类似于掷骰子,而是做出明确的选择。我不认为你可以让马尔可夫模型在这种情况下工作。
【解决方案2】:

为什么不使用贪心算法?

你不能在每个时间点做得比选择期望值最高的目标(命中概率乘以目标值)更好。

【讨论】:

  • 每次选择最高期望值是否有可能导致局部最大值而不是全局最大值?
  • 我认为如果击中一个目标导致其他个目标缩小,那将是一个真正的风险,但在这种情况下,击中一个目标只会影响该目标。如果有一个最佳目标可以击中,选择现在或稍后尝试击中它不会影响任何其他选择,也不会受到任何其他选择的影响。因此,选择首先击中最佳目标可以最大限度地提高成功击中它们的机会。
猜你喜欢
  • 1970-01-01
  • 2012-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 2022-11-30
  • 1970-01-01
相关资源
最近更新 更多