【Gurobi学习笔记】翻转游戏(Flip Game):数学模型与Python调用Gurobi实现


前言

翻转游戏(Flip Game), 是20世纪90年代开始流行的一款电子游戏。该游戏由一个5*5的网格组成,每格里有一个圈。 游戏的初始状态是,25个圈中的颜色相同。点击任意一个圈将使得它和相邻格子的圈改变颜色。游戏的目标是用尽可能少的点击数让所有圈都变色。

举一个Flip Game的例子,来帮助理解游戏规则:
初始状态:
图1 初始状态
点击(3,3):
图2 第一次点击
点击(3,1):
图2 第二次点击
本文来介绍如何使用数学规划的方法来解决Flip Game。本文的主要内容如下:

  1. Flip Game的问题描述;
  2. Flip Game的数学规划模型;
  3. Python调用Gurobi求解Flip Game的模型。

问题描述

Flap Game的问题描述如下:

给定一个5*5的方格矩阵,其中格子中的圈两面颜色不同,比如要么绿色朝上,要么红色朝上,初始的圈颜色都相同。点击圈可以进行翻转,改变颜色,同时也会改变所有邻格的颜色。游戏的目的是:

  1. 使所有圈与初始颜色不同;
  2. 尽可能少的点击数。

数学模型

Flip Game可以被构建为整数规划,并使用求解器求解。本节就来介绍Flip Game的数学规划模型。

1.整理数据和参数

  • 5 ∗ 5 网格

图3 数据和参数

2.定义决策变量

  • 决策:点击哪一个格子
  • 变量: x i , j ( i , j = 1 , 2 , … , 5 ) x_{i, j}(i, j = 1,2,\ldots,5) xi,j(i,j=1,2,,5)
  • =1 如果 ( i , j ) (i,j) (i,j)被点,否则为0
  • 类型:0-1

3.构建目标函数

  • 最小化点击数
  • min ∑ i , j = 1 , … , 5 x i , j \sum_{i,j=1,\ldots,5}x_{i,j} i,j=1,,5xi,j

4.设置约束条件

  • 用逻辑约束来表达更简单
  • x i , j + x i − 1 , j + x i + 1 , j + x i , j − 1 + x i , j + 1 x_{i, j}+x_{i-1, j}+x_{i+1, j}+x_{i, j-1}+x_{i, j+1} xi,j+xi1,j+xi+1,j+xi,j1+xi,j+1为奇数, ∀ i , j = 1 , … , 5 \forall i, j=1, \ldots, 5 i,j=1,,5
  • x i , j = 0 , ∀ i , j < 1 x_{i, j}=0, \forall i, j<1 xi,j=0,i,j<1 i , j > 5 i, j>5 i,j>5

如何将上述约束转化为数学形式呢?

  • 引入辅助变量 y i , j y_{i, j} yi,j
  • 0 ≤ y i , j ≤ 2 , y i , j 0 \leq y_{i, j} \leq 2, y_{i, j} 0yi,j2,yi,j 为整数, ∀ i , j = 1 , … , 5 \forall i, j=1, \ldots, 5 i,j=1,,5
  • x i , j + x i − 1 , j + x i + 1 , j + x i , j − 1 + x i , j + 1 = 2 y i , j + 1 , ∀ i , j = 1 , … , 5 x_{i, j}+x_{i-1, j}+x_{i+1, j}+x_{i, j-1}+x_{i, j+1}=2 y_{i, j}+1,\forall i, j=1, \ldots, 5 xi,j+xi1,j+xi+1,j+xi,j1+xi,j+1=2yi,j+1,i,j=1,,5

5.模型建立

基于上述过程,我们给出Flip Game的数学规划模型。
min ⁡ ∑ i , j = 1 , … , 5 x i , j  s.t.  x i , j + x i − 1 , j + x i + 1 , j + x i , j − 1 + x i , j + 1 = 2 y i , j + 1 , ∀ i , j = 1 , … , 5 0 ≤ y i , j ≤ 2 , y i , j 为整数,  ∀ i , j = 1 , … , 5 x i , j = 0 ,否则 \begin{aligned} & \min \sum_{i,j=1,\ldots,5}x_{i,j} \\ & \text { s.t. } x_{i, j}+x_{i-1, j}+x_{i+1, j}+x_{i, j-1}+x_{i, j+1}=2 y_{i, j}+1,\forall i, j=1, \ldots, 5\\ & \quad\quad0 \leq y_{i, j} \leq 2, y_{i, j} \text {为整数, }\forall i, j=1, \ldots, 5 \\ & \quad \quad x_{i, j}=0\text{,否则} \\ & \end{aligned} mini,j=1,,5xi,j s.t. xi,j+xi1,j+xi+1,j+xi,j1+xi,j+1=2yi,j+1,i,j=1,,50yi,j2,yi,j为整数i,j=1,,5xi,j=0,否则

Python调用Gurobi求解

我们给出使用Python调用Gurobi求解上述整数规划模型的代码:

import gurobipy as gp
from gurobipy import GRB

# create the model object
model = gp.Model("Flap Game")

# define decision variables
x = {
    
    }
y = {
    
    }
for i in range(0, 7):
    for j in range(0, 7):
        if i < 1 or i > 5 or j < 1 or j > 5:
            x[i, j] = model.addVar(vtype=GRB.BINARY, ub=0, name=f"x_{
      
      i}_{
      
      j}")
        else:
            x[i, j] = model.addVar(vtype=GRB.BINARY, name=f"x_{
      
      i}_{
      
      j}")
            y[i, j] = model.addVar(lb=0, ub=2, vtype=GRB.INTEGER, name=f"y_{
      
      i}_{
      
      j}")

# set the objective function
model.setObjective(gp.quicksum(x[i, j] for i in range(1, 6) for j in range(1, 6)), GRB.MINIMIZE)

# add the constraint x[i, j] + x[i-1, j] + x[i+1, j] + x[i, j-1] + x[i, j+1] = 2*y[i, j] + 1
for i in range(1, 6):
    for j in range(1, 6):
        model.addConstr(x[i, j] + x[i-1, j] + x[i+1, j] + x[i, j-1] + x[i, j+1] == 2*y[i, j] + 1)

# optimize the model
model.Params.outputFlag = 0
model.optimize()

# print the results
if model.status == GRB.OPTIMAL:
    print("Optimal objective value:", model.objVal)
    print("Optimal solution:")
    for i in range(1, 6):
        for j in range(1, 6):
            print(f"x_{
      
      i}_{
      
      j} = {
      
      x[i, j].x}, y_{
      
      i}_{
      
      j} = {
      
      y[i, j].x}")
else:
    print("No optimal solution found.")

求解结果如下:

Optimal objective value: 15.0
Optimal solution:
x_1_1 = -0.0, y_1_1 = 0.0
x_1_2 = 1.0, y_1_2 = 1.0
x_1_3 = 1.0, y_1_3 = 1.0
x_1_4 = 0.0, y_1_4 = 1.0
x_1_5 = 1.0, y_1_5 = 0.0
x_2_1 = 0.0, y_2_1 = -0.0
x_2_2 = 1.0, y_2_2 = 1.0
x_2_3 = 1.0, y_2_3 = 2.0
x_2_4 = 1.0, y_2_4 = 1.0
x_2_5 = 0.0, y_2_5 = 1.0
x_3_1 = -0.0, y_3_1 = -0.0
x_3_2 = 0.0, y_3_2 = 1.0
x_3_3 = 1.0, y_3_3 = 1.0
x_3_4 = 1.0, y_3_4 = 2.0
x_3_5 = 1.0, y_3_5 = 1.0
x_4_1 = 1.0, y_4_1 = 1.0
x_4_2 = 1.0, y_4_2 = 1.0
x_4_3 = 0.0, y_4_3 = 1.0
x_4_4 = 1.0, y_4_4 = 1.0
x_4_5 = 1.0, y_4_5 = 1.0
x_5_1 = 1.0, y_5_1 = 1.0
x_5_2 = 1.0, y_5_2 = 1.0
x_5_3 = 0.0, y_5_3 = -0.0
x_5_4 = 0.0, y_5_4 = -0.0
x_5_5 = 0.0, y_5_5 = 0.0

可以看出,该模型有解,我们求出了来赢得游戏最优的点击策略。


总结

本文介绍了Flip Game的数学规划模型,并给出了Python调用Gurobi求解Flip Game的数学规划模型的完整代码。笔者并未进行游戏验证,因为笔者水平有限,如果模型和代码有误,还请批评指正。

猜你喜欢

转载自blog.csdn.net/cros1/article/details/132134622