Эффективная таблица для динамического программирования в Haskell

Я закодировал 0-1 задачу о ранце на Haskell. Я очень горжусь достигнутой ленью и уровнем универсальности.

Я начинаю с предоставления функций для создания и работы с ленивой 2-мерной матрицей.

mkList f = map f [0..]
mkTable f = mkList (\i -> mkList (\j -> f i j))

tableIndex table i j = table !! i !! j

Затем я составляю конкретную таблицу для данной задачи о рюкзаке

knapsackTable = mkTable f
    where f 0 _ = 0
          f _ 0 = 0
          f i j | ws!!i > j = leaveI
                | otherwise = max takeI leaveI
              where takeI  = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i
                    leaveI = tableIndex knapsackTable (i-1) j

-- weight value pairs; item i has weight ws!!i and value vs!!i
ws  = [0,1,2, 5, 6, 7] -- weights
vs  = [0,1,7,11,21,31] -- values

] И закончите парой вспомогательных функций для просмотра таблицы

viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table
printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ

Это было довольно просто. Но я хочу пойти дальше.

Мне нужна лучшая структура данных для таблицы. В идеале это должно быть

  • распакованное (неизменяемое) [править] не говоря уже об этом
  • Ленивый
  • Неограниченный
  • O (1) время для построения
  • O (1) временная сложность поиска данной записи,
    Мы закодировали 0-1 задачу о ранце на Haskell. Я очень горжусь достигнутой ленью и уровнем универсальности.

    Я начинаю с предоставления функций для создания и работы с ленивой 2-мерной матрицей.

    mkList f = map f [0..]
    mkTable f = mkList (\i -> mkList (\j -> f i j))
    
    tableIndex table i j = table !! i !! j
    

    Затем я составляю конкретную таблицу для данной задачи о рюкзаке

    knapsackTable = mkTable f
        where f 0 _ = 0
              f _ 0 = 0
              f i j | ws!!i > j = leaveI
                    | otherwise = max takeI leaveI
                  where takeI  = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i
                        leaveI = tableIndex knapsackTable (i-1) j
    
    -- weight value pairs; item i has weight ws!!i and value vs!!i
    ws  = [0,1,2, 5, 6, 7] -- weights
    vs  = [0,1,7,11,21,31] -- values
    

    ] И закончите парой вспомогательных функций для просмотра таблицы

    viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table
    printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ
    

    Это было довольно просто. Но я хочу пойти дальше.

    Мне нужна лучшая структура данных для таблицы. В идеале это должно быть

    • распакованное (неизменяемое) [править] не говоря уже об этом
    • Ленивый
    • Неограниченный
    • O (1) время, чтобы построить
    • O (1) временная сложность поиска данной записи,
      Мы закодировали 0-1 задачу о ранце на Haskell. Я очень горжусь достигнутой ленью и уровнем универсальности.

      Я начинаю с предоставления функций для создания и работы с ленивой 2-мерной матрицей.

      mkList f = map f [0..]
      mkTable f = mkList (\i -> mkList (\j -> f i j))
      
      tableIndex table i j = table !! i !! j
      

      Затем я составляю конкретную таблицу для данной задачи о рюкзаке

      knapsackTable = mkTable f
          where f 0 _ = 0
                f _ 0 = 0
                f i j | ws!!i > j = leaveI
                      | otherwise = max takeI leaveI
                    where takeI  = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i
                          leaveI = tableIndex knapsackTable (i-1) j
      
      -- weight value pairs; item i has weight ws!!i and value vs!!i
      ws  = [0,1,2, 5, 6, 7] -- weights
      vs  = [0,1,7,11,21,31] -- values
      

      ] И закончите парой вспомогательных функций для просмотра таблицы

      viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table
      printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ
      

      Это было довольно просто. Но я хочу пойти дальше.

      Мне нужна лучшая структура данных для таблицы. В идеале это должно быть

      • распакованное (неизменяемое) [править] не говоря уже об этом
      • Ленивый
      • Неограниченный
      • O (1) время для построения
      • O (1) временная сложность поиска данной записи,
        Я очень горжусь достигнутой ленью и уровнем универсальности.

        Я начинаю с предоставления функций для создания и работы с ленивой 2-мерной матрицей.

        mkList f = map f [0..]
        mkTable f = mkList (\i -> mkList (\j -> f i j))
        
        tableIndex table i j = table !! i !! j
        

        Затем я составляю конкретную таблицу для данной задачи о рюкзаке

        knapsackTable = mkTable f
            where f 0 _ = 0
                  f _ 0 = 0
                  f i j | ws!!i > j = leaveI
                        | otherwise = max takeI leaveI
                      where takeI  = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i
                            leaveI = tableIndex knapsackTable (i-1) j
        
        -- weight value pairs; item i has weight ws!!i and value vs!!i
        ws  = [0,1,2, 5, 6, 7] -- weights
        vs  = [0,1,7,11,21,31] -- values
        

        И закончите парой вспомогательных функций для просмотра таблицы

        viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table
        printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ
        

        Это было довольно просто. Но я хочу пойти дальше.

        Мне нужна лучшая структура данных для таблицы. В идеале это должно быть

        • распакованное (неизменяемое) [править] не говоря уже об этом
        • Ленивый
        • Неограниченный
        • O (1) время, чтобы построить
        • O (1) временная сложность поиска данной записи,
          Я очень горжусь достигнутой ленью и уровнем универсальности.

          Я начинаю с предоставления функций для создания и работы с ленивой 2-мерной матрицей.

          mkList f = map f [0..]
          mkTable f = mkList (\i -> mkList (\j -> f i j))
          
          tableIndex table i j = table !! i !! j
          

          Затем я составляю конкретную таблицу для данной задачи о рюкзаке

          knapsackTable = mkTable f
              where f 0 _ = 0
                    f _ 0 = 0
                    f i j | ws!!i > j = leaveI
                          | otherwise = max takeI leaveI
                        where takeI  = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i
                              leaveI = tableIndex knapsackTable (i-1) j
          
          -- weight value pairs; item i has weight ws!!i and value vs!!i
          ws  = [0,1,2, 5, 6, 7] -- weights
          vs  = [0,1,7,11,21,31] -- values
          

          И закончите парой вспомогательных функций для просмотра таблицы

          viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table
          printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ
          

          Это было довольно просто. Но я хочу пойти дальше.

          Мне нужна лучшая структура данных для таблицы. В идеале это должно быть

          • распакованное (неизменяемое) [править] не говоря уже об этом
          • Ленивый
          • Неограниченный
          • O (1) время, чтобы построить
          • O (1) временная сложность поиска данной записи,
            mkList f = map f [0..]
            mkTable f = mkList (\i -> mkList (\j -> f i j))
            
            tableIndex table i j = table !! i !! j
            

            Затем я составляю конкретную таблицу для данной задачи о рюкзаке

            knapsackTable = mkTable f
                where f 0 _ = 0
                      f _ 0 = 0
                      f i j | ws!!i > j = leaveI
                            | otherwise = max takeI leaveI
                          where takeI  = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i
                                leaveI = tableIndex knapsackTable (i-1) j
            
            -- weight value pairs; item i has weight ws!!i and value vs!!i
            ws  = [0,1,2, 5, 6, 7] -- weights
            vs  = [0,1,7,11,21,31] -- values
            

            И заканчиваю парой вспомогательных функций для просмотра таблицы

            viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table
            printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ
            

            Это было довольно просто. Но я хочу пойти дальше.

            Мне нужна лучшая структура данных для таблицы. В идеале это должно быть

            • распакованное (неизменяемое) [править] не говоря уже об этом
            • Ленивый
            • Неограниченный
            • O (1) время для построения
            • O (1) временная сложность поиска данной записи,
              mkList f = map f [0..]
              mkTable f = mkList (\i -> mkList (\j -> f i j))
              
              tableIndex table i j = table !! i !! j
              

              Затем я составляю конкретную таблицу для данной задачи о рюкзаке

              knapsackTable = mkTable f
                  where f 0 _ = 0
                        f _ 0 = 0
                        f i j | ws!!i > j = leaveI
                              | otherwise = max takeI leaveI
                            where takeI  = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i
                                  leaveI = tableIndex knapsackTable (i-1) j
              
              -- weight value pairs; item i has weight ws!!i and value vs!!i
              ws  = [0,1,2, 5, 6, 7] -- weights
              vs  = [0,1,7,11,21,31] -- values
              

              И заканчиваю парой вспомогательных функций для просмотра таблицы

              viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table
              printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ
              

              Это было довольно просто. Но я хочу пойти дальше.

              Мне нужна лучшая структура данных для таблицы. В идеале это должно быть

              • распакованное (неизменяемое) [править] не говоря уже об этом
              • Ленивый
              • Неограниченный
              • O (1) время для построения
              • O (1) временная сложность поиска данной записи,
                (more realistically, at worst O(log n), where n is i*j for looking up the entry at row i, column j)

              Bonus points if you can explain why/how your solution satisfies these ideals.

              Also bonus points if you can further generalize knapsackTable, and prove that it is efficient.

              In improving the data structure you should try to satisfy the following goals:

              • If I ask for the solution where the maximum weight is 10 (in my current code, that would be indexTable knapsackTable 5 10, the 5 means include items 1-5) only the minimal amount of work necessary should be performed. Ideally this means no O(i*j) work for forcing the spine of each row of the table to necessary column length. You could say this isn't "true" DP, if you believe DP means evaluating the entirety of the table.
              • If I ask for the entire table to be printed (something like printTable knapsackTable 5 10), the values of each entry should be computed once and only once. The values of a given cell should depend on the values of other cells (DP style: the idea being, never recompute the same subproblem twice)

              Ideas:

              Answers that make some compromises to my stated ideals will be upvoted (by me, anyways) as long as they are informative. The answer with the least compromises will probably be the "accepted" one.

15
задан Community 23 May 2017 в 12:19
поделиться