Mysql 需要一个实用的解决方案来创建15个谜题的模式数据库(5-5-5)

Mysql 需要一个实用的解决方案来创建15个谜题的模式数据库(5-5-5),mysql,jdbc,recursion,artificial-intelligence,stack-overflow,Mysql,Jdbc,Recursion,Artificial Intelligence,Stack Overflow,关于静态模式数据库(5-5-5),请参见(第290页和第283页),或有以下说明。对于 我正在创建一个静态模式数据库(5-5-5)。此代码用于将条目填充到第一个表中。我是通过递归函数insertInDB()实现的。递归函数的第一个输入是这样的(实际上,输入拼图包含在1-D数组中。为了更好地理解,我在下面将其表示为2-D) 1234 0600 0 0 这是我的代码: class DBClass { public Connection connection; public Re

关于静态模式数据库(5-5-5),请参见(第290页和第283页),或有以下说明。对于
我正在创建一个静态模式数据库(5-5-5)。此代码用于将条目填充到第一个表中。我是通过递归函数
insertInDB()
实现的。递归函数的第一个输入是这样的(实际上,输入拼图包含在1-D数组中。为了更好地理解,我在下面将其表示为2-D)


1234
0600
0
0


这是我的代码:

class DBClass
{
    public Connection connection;
     public ResultSet rs;
      public PreparedStatement ps1;
    public PreparedStatement ps2;
    public int k;
      String read_statement,insert_statement;

    public DBClass()
    {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
            try {
                connection = DriverManager
                    .getConnection("jdbc:mysql://localhost/feedback?"
                        + "user=ashwin&password=ashwin&autoReconnect=true&useUnicode=true&characterEncoding=utf8&validationQuery=Select 1");
                insert_statement="insert into staticpdb1(hash,permutation,cost) values(?,?,?)";
                read_statement="select SQL_NO_CACHE * from staticpdb1 where hash=? and permutation= ? LIMIT 1";
                 ps1=connection.prepareStatement(read_statement, ResultSet.TYPE_SCROLL_SENSITIVE, 
                            ResultSet.CONCUR_UPDATABLE);
                ps2=connection.prepareStatement(insert_statement);
                k=0;
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }
    public int updateIfNecessary(FifteenPuzzle sub) 
       {
           String str=sub.toDBString();
           try
           {

               ps1.setInt(1, sub.hashcode());
               ps1.setString(2,str);
               rs=ps1.executeQuery();
           if(rs.next())
              {
                  //if a row exists, check if the cost is greater than sub's
                  int cost=rs.getInt(3);
                  if(sub.g_n<cost)  //if the cost of sub is less than db row's cost
                  {
                      //replace the cost
                      rs.updateInt(3, sub.g_n);
                      rs.updateRow();
                      return 1;   //only examine - do not insert
                  }
                  else
                      return 0;   //dont examine - return

              }
           else
               return 2;      //insert and examine
           }
           catch(SQLException e)
           {

               System.out.println("here1"+e);
               System.err.println("reported recursion level was "+e.getStackTrace().length);
               return 0;
           }
           finally{

               try{
                   rs.close();}
               catch(final Exception e1)
               {
                   System.out.println("here2"+e1);
               }

           }


       }
    public void insert(FifteenPuzzle sub)
    {

        try{
        String str=sub.toDBString();


         ps2.setInt(1,sub.hashcode());
         ps2.setString(2, str);
         ps2.setInt(3,sub.g_n);
         ps2.executeUpdate();
         ps2.clearParameters();
        }catch(SQLException e)
        {
            System.out.println("here3"+e);
        }
    }

    public void InsertInDB(FifteenPuzzle sub) throws SQLException
       {

           System.out.println(k++);

           int i;

           int p=updateIfNecessary(sub);
          if(p==0)
          {
              System.out.println("returning");
           return;
          }
          if(p==2)
          {
          insert(sub);
          System.out.println("inserted");
          }


           //FifteenPuzzle temp=new FifteenPuzzle(sub.puzzle.clone(),2,sub.g_n);
           for(i=0;i<sub.puzzle.length;i++)
           {
               if(sub.puzzle[i]!=0)
               {

                   //check the positions it can be moved to
                   if(i%4!=0 && sub.puzzle[i-1]==0)  //left
                   {
                       //create another clone and increment the moves
                       FifteenPuzzle temp_inner=new FifteenPuzzle(sub.puzzle.clone(),2,sub.g_n+1);
                       //exchange positions
                        int t=temp_inner.puzzle[i];
                        temp_inner.puzzle[i]=temp_inner.puzzle[i-1];
                        temp_inner.puzzle[i-1]=t;
                        InsertInDB(temp_inner);
                   }
                   if(i%4!=3 && sub.puzzle[i+1]==0)  //right
                   {
                       //create another clone and increment the moves
                       FifteenPuzzle temp_inner=new FifteenPuzzle(sub.puzzle.clone(),2,sub.g_n+1);
                       //exchange positions
                        int t=temp_inner.puzzle[i];
                        temp_inner.puzzle[i]=temp_inner.puzzle[i+1];
                        temp_inner.puzzle[i+1]=t;
                        InsertInDB(temp_inner);
                   }
                   if(i/4!=0 && sub.puzzle[i-4]==0)  //up
                   {
                       //create another clone and increment the moves
                       FifteenPuzzle temp_inner=new FifteenPuzzle(sub.puzzle.clone(),2,sub.g_n+1);
                       //exchange positions
                        int t=temp_inner.puzzle[i];
                        temp_inner.puzzle[i]=temp_inner.puzzle[i-4];
                        temp_inner.puzzle[i-4]=t;
                        InsertInDB(temp_inner);
                   }
                   if(i/4!=3 && sub.puzzle[i+4]==0)  //down
                   {
                       //create another clone and increment the moves
                       FifteenPuzzle temp_inner=new FifteenPuzzle(sub.puzzle.clone(),2,sub.g_n+1);
                       //exchange positions
                        int t=temp_inner.puzzle[i];
                        temp_inner.puzzle[i]=temp_inner.puzzle[i+4];
                        temp_inner.puzzle[i+4]=t;
                        InsertInDB(temp_inner);

                  }
             }   
       }

现在,其他函数-
updateIfNecessary(FifteenPuzzle)
-此函数检查传递的FifteenPuzzle对象的数组是否已存在于数据库中。如果数据库中已经存在,它将检查当前对象的成本是否小于以DB为单位的成本。如果是,则将其替换为当前成本,否则不起任何作用。函数-
insert(FifteenPuzzle)
插入一个新的具有成本的排列。

注意:
fifteenuzzle.g\u n
是拼图的成本。对于表示上述矩阵的初始拼图,成本为
0
,并且对于每个移动,成本为
增加1


对于运行配置中的堆栈大小,我已将堆栈大小设置为-
Xss128m
(1024、512和256给出了一个致命错误)
当前递归数或深度为
7500000
和计数(值为
System.out.println(k++);
)。
可能的组合总数为


但深度已经达到750万。这是因为产生了重复状态。目前数据库中的条目数为513423。你可能认为现在只有10000个条目需要填写。但是现在输入的速率急剧下降,大约每30分钟输入一次。这永远不会过去


我需要一个实用的解决方案-带或不带递归。有可能吗?

我想您的问题与资源管理不当有关,而不是递归本身。此外,您正试图使您的实现变得比您需要的更复杂。我建议如下:

  • 创建将向数据库插入/更新数据的方法。在这里管理你的资源。这不需要是递归的
  • 在递归方法中,调用此方法向数据库插入/更新数据
这更干净,因为您知道特定于数据库的方法将在返回递归之前关闭所有资源。但是,我建议您在调用此方法时应该重用连接对象

另外,确保在finally块中关闭语句、结果集甚至连接。首先,我看到的一个问题是:

  • 您正在尝试在try块或if块中关闭preparedstatement。如果您没有点击if块,并且在有机会关闭资源之前点击了异常,该怎么办?您的PreparedStatement和其他资源将永远不会关闭

我猜您的问题与资源管理不当有关,而不是递归本身。此外,您正试图使您的实现变得比您需要的更复杂。我建议如下:

  • 创建将向数据库插入/更新数据的方法。在这里管理你的资源。这不需要是递归的
  • 在递归方法中,调用此方法向数据库插入/更新数据
这更干净,因为您知道特定于数据库的方法将在返回递归之前关闭所有资源。但是,我建议您在调用此方法时应该重用连接对象

另外,确保在finally块中关闭语句、结果集甚至连接。首先,我看到的一个问题是:

  • 您正在尝试在try块或if块中关闭preparedstatement。如果您没有点击if块,并且在有机会关闭资源之前点击了异常,该怎么办?您的PreparedStatement和其他资源将永远不会关闭

    • 您不应该调用递归。这样做会将另一个地址放在内存中的堆栈上,如果这种情况太频繁,您的内存就会耗尽,在您的情况下就是这样:
      stackoverflowerr


      尝试创建一种方法,让您只需输入一次数据,然后在循环中调用该方法,直到所有数据都保存在数据库中。

      您不应调用recursive。这样做会将另一个地址放在内存中的堆栈上,如果这种情况太频繁,您的内存就会耗尽,在您的情况下就是这样:
      stackoverflowerr


      尝试创建一种方法,让您只输入一次数据,然后在循环中调用该方法,直到所有数据都保存在数据库中。

      重要的部分是第一行:
      java.lang.StackOverflowerError
      。递归要求很高


      尝试只递归地执行算法部分,同时将DB访问放在一个额外的方法中。

      重要的部分是第一行:
      java.lang.StackOverflowerError
      。递归要求很高


      尝试只递归地执行算法部分,同时将DB访问放在一个额外的方法中。

      您正在每个方法调用中创建新的
      PreparedStatement
      对象,这里是一个递归方法。例如,
      ps=connection.prepareStatement(读取语句)
      ps=连接。准备声明(插入声明)。为这两个对象创建两个单独的PreparedStatement对象,并将它们移出方法并调用
      ps.clearParameters()(对于两个对象)。因此,你只需要处理tw
      
      16!/(16-5)! = 524160
      
      16!/(16-5)! = 524160
      
      1 2 3 4    1 2 3 4
      0 6 0 0    6 0 0 0
      0 0 0 0    0 0 0 0
      0 0 0 0    0 0 0 0
        (0)        (1)
      
      1 2 3 4    1 2 3 4
      0 0 0 0    0 0 0 0
      6 0 0 0    0 0 0 0
      0 0 0 0    6 0 0 0
        (2)        (3)
      
                 State-1    State-2    State-3
      1 2 3 4    1 2 3 4    1 2 3 4    1 2 3 4
      0 0 0 0    0 0 0 0    0 0 0 0    0 0 0 0
      0 0 0 0    0 0 0 0    0 0 0 0    0 0 0 0
      6 0 0 0    0 6 0 0    0 0 6 0    0 0 0 6
        (3)        (4)        (5)        (6)
      
      1 2 3 4    1 2 3 4
      0 6 0 0    6 0 0 0
      0 0 0 0    0 0 0 0
      0 0 0 0    0 0 0 0
        (0)        (1)
      
      1 2 3 4    1 2 3 4
      0 0 6 0    0 0 0 0
      0 0 0 0    0 6 0 0
      0 0 0 0    0 0 0 0
        (1)        (1)
      
      Initialize no_of_moves by 0
      enqueue(startingPosition)
      insertIntoDB(startingPattern, no_of_moves)
      while((currentPattern = dequeue()) is not null)
          if(currentPattern is not already traversed)
              insertIntoDB(currentPattern);
              list<Pattern> allPatterns = patterns which can be reached from currentPattern in just 1 move
              no_of_moves++
              enqueue(allPatterns, no_of_moves)
          end if
      end while