Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 快速块布局算法,需要建议吗?_Algorithm_Packing_Bisection - Fatal编程技术网

Algorithm 快速块布局算法,需要建议吗?

Algorithm 快速块布局算法,需要建议吗?,algorithm,packing,bisection,Algorithm,Packing,Bisection,我需要模拟窗口管理器的窗口放置策略 作为一个粗略的指导,想象一下随机大小的窗口一次填满一个屏幕,其中每个窗口的粗略大小导致屏幕上平均有80个窗口,没有任何窗口重叠 如果您的系统上安装了Fluxbox和Xterm,您可以尝试使用BASH脚本来查看我希望发生的事情的大致原型。请看我写的关于它的注释,解释它的作用和应该如何使用 需要注意的是,窗口将关闭,以前关闭的窗口占用的空间将再次用于放置新窗口。 该算法需要“以串行方式逐块”处理数据,即按照输入输入到算法的顺序,而不必从一开始就提供整个输入 Flu

我需要模拟窗口管理器的窗口放置策略

作为一个粗略的指导,想象一下随机大小的窗口一次填满一个屏幕,其中每个窗口的粗略大小导致屏幕上平均有80个窗口,没有任何窗口重叠

如果您的系统上安装了Fluxbox和Xterm,您可以尝试使用BASH脚本来查看我希望发生的事情的大致原型。请看我写的关于它的注释,解释它的作用和应该如何使用

需要注意的是,窗口将关闭,以前关闭的窗口占用的空间将再次用于放置新窗口。

该算法需要“以串行方式逐块”处理数据,即按照输入输入到算法的顺序,而不必从一开始就提供整个输入

Fluxbox窗口放置策略有三个二进制选项,我想模仿它们:

  • Windows构建水平行或垂直列(可能)

  • 窗口从左到右放置或从右到左放置

  • 窗口从上到下放置或从下到上放置

目标算法和窗口放置算法之间的差异

坐标单位不是像素。将放置块的网格为128 x 128个单位。此外,放置区域可以通过放置在网格内的边界区域进一步缩小

为什么算法有问题?

它需要在音频应用程序中实时线程的截止日期前运行

此刻我只关心获得一个快速算法,而不关心实时线程的含义以及由此带来的编程障碍

虽然算法永远不会放置与另一个窗口重叠的窗口,但用户将能够放置和移动某些类型的块,重叠窗口将存在。用于存储窗口和/或可用空间的数据结构需要能够处理这种重叠

到目前为止,我有两个选择,我已经建立了松散的原型:

1)将Fluxbox放置算法的端口插入我的代码。

问题是,当我尝试使用该算法放置256个块的最坏情况时,客户端(我的程序)会被踢出音频服务器()。该算法在放置第256个窗口时,对已放置的块列表执行14000次完整(线性)扫描

为了演示这一点,我创建了一个名为的程序,该程序将文本文件作为输入,并将其排列在ASCII框中。发布
make
来构建它。有点不友好,请使用
--help
(或任何其他无效选项)查看命令行选项列表。必须使用选项指定文本文件

2)我的替代方法。

此方法仅部分实现,对矩形空闲未使用的空间的每个区域使用数据结构(窗口列表可以完全分开,并且不需要测试此算法)。数据结构充当双链接列表(带有排序插入)中的节点,并包含左上角的坐标以及宽度和高度

此外,每个块数据结构还包含四个链接,这些链接连接到四面上的每个紧邻(接触)块

重要规则:每个区块每侧只能接触一个区块。这是一条特定于算法存储空闲未使用空间的方法的规则,不考虑实际窗口相互接触的数量

这种方法的问题是,它非常复杂。我已经实施了一些简单的案例,其中1)从块的一个角移除空间,2)分割相邻块,以便遵守重要规则

不太简单的情况是,要删除的空间只能在一列或一行框中找到,仅部分实现-如果要删除的块之一与宽度(即列)或高度(即行)完全匹配,则会出现问题。甚至不要提及这样一个事实:它只检查一个框宽的列和一个框高的行

我已经用C语言实现了这个算法(我用了这个项目的语言(我用C++几年了,在把所有注意力都放在C开发上之后,我不喜欢它,这是一个爱好)。实现是700多行代码(包括大量的空行、大括号行、注释等)。该实现仅适用于水平行+左右+上下放置策略

因此,我要么要添加一些方法,使这+700行代码适用于其他7个布局策略选项,要么我要为其他7个选项复制+700行代码。这两种方法都没有吸引力,第一种是因为现有代码足够复杂,第二种是因为代码膨胀

由于缺少功能,该算法甚至还没有达到我可以在实时最坏情况下使用它的阶段,因此我仍然不知道它的实际性能是否比第一种方法更好或更差

该算法的C实现的当前状态为。我使用
gcc-O0-ggdb freespace.c
构建,并在大小至少为124 x 60个字符的xterm中运行它

还有什么?

我略过并打折:

  • 装箱算法 强调最佳配合并不重要 符合本标准的要求 算法

  • 递归二分法
    struct block{
        int free_x[4]; // 0 = top left, 1 = top right,
        int free_y[4]; // 2 = bottom left, 3 = bottom right
        int n_windows; // number of windows that occupy this block
        int window_id[4]; // IDs of windows that occupy this block
    };
    block blocks[NX][NY];
    
    struct window{
        int id;
        int used_block_x[2]; // 0 = first index of used block,
        int used_block_y[2]; // 1 = last index of used block
    };
    
    _Bool freespace_remove( freespace* fs,
                            int width,     int height,
                            int* resultx,  int* resulty)
    {
        int x = 0;
        int y = 0;
        const int rx = FSWIDTH - width;
        const int by = FSHEIGHT - height;
    
        *resultx = -1;
        *resulty = -1;
    
        char* buf[height];
    
        for (y = 0; y < by; ++y)
        {
            x = 0;
            char* scanx = fs->buf[y];
    
            while (x < rx)
            {
                while(x < rx && *(scanx + x))
                    ++x;
    
                int w, h;
    
                for (h = 0; h < height; ++h)
                    buf[h] = fs->buf[y + h] + x;
    
                _Bool usable = true;
                w = 0;
    
                while (usable && w < width)
                {
                    h = 0;
                    while (usable && h < height)
                        if (*(buf[h++] + w))
                            usable = false;
                    ++w;
                }
    
                if (usable)
                {
                    for (w = 0; w < width; ++w)
                        for (h = 0; h < height; ++h)
                            *(buf[h] + w) = 1;
    
                    *resultx = x;
                    *resulty = y;
                    return true;
                }
    
                x += w;
            }
        }
    
        return false;
    }
    
    #include <limits.h>
    #include <stdbool.h>
    #include <stddef.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <string.h>
    
    
    #define FSWIDTH 128
    #define FSHEIGHT 128
    
    
    #ifdef USE_64BIT_ARRAY
        #define FSBUFBITS 64
        #define FSBUFWIDTH 2
        typedef uint64_t fsbuf_type;
        #define TRAILING_ZEROS( v ) __builtin_ctzl(( v ))
        #define LEADING_ONES( v )   __builtin_clzl(~( v ))
    #else
    #ifdef USE_32BIT_ARRAY
        #define FSBUFBITS 32
        #define FSBUFWIDTH 4
        typedef uint32_t fsbuf_type;
        #define TRAILING_ZEROS( v ) __builtin_ctz(( v ))
        #define LEADING_ONES( v )   __builtin_clz(~( v ))
    #else
    #ifdef USE_16BIT_ARRAY
        #define FSBUFBITS 16
        #define FSBUFWIDTH 8
        typedef uint16_t fsbuf_type;
        #define TRAILING_ZEROS( v ) __builtin_ctz( 0xffff0000 | ( v ))
        #define LEADING_ONES( v )   __builtin_clz(~( v ) << 16)
    #else
    #ifdef USE_8BIT_ARRAY
        #define FSBUFBITS 8
        #define FSBUFWIDTH 16
        typedef uint8_t fsbuf_type;
        #define TRAILING_ZEROS( v ) __builtin_ctz( 0xffffff00 | ( v ))
        #define LEADING_ONES( v )   __builtin_clz(~( v ) << 24)
    #else
        #define FSBUFBITS 1
        #define FSBUFWIDTH 128
        typedef unsigned char fsbuf_type;
        #define TRAILING_ZEROS( v ) (( v ) ? 0 : 1)
        #define LEADING_ONES( v )   (( v ) ? 1 : 0)
    #endif
    #endif
    #endif
    #endif
    
    
    static const fsbuf_type fsbuf_max =   ~(fsbuf_type)0;
    static const fsbuf_type fsbuf_high =  (fsbuf_type)1 << (FSBUFBITS - 1);
    
    
    typedef struct freespacegrid
    {
        fsbuf_type buf[FSHEIGHT][FSBUFWIDTH];
    
        _Bool left_to_right;
        _Bool top_to_bottom;
    
    } freespace;
    
    
    void freespace_dump(freespace* fs)
    {
        int x, y;
    
        for (y = 0; y < FSHEIGHT; ++y)
        {
            for (x = 0; x < FSBUFWIDTH; ++x)
            {
                fsbuf_type i = FSBUFBITS;
                fsbuf_type b = fs->buf[y][x];
    
                for(; i != 0; --i, b <<= 1)
                    putchar(b & fsbuf_high ? '#' : '/');
    /*
                if (x + 1 < FSBUFWIDTH)
                    putchar('|');
    */
            }
            putchar('\n');
        }
    }
    
    
    freespace* freespace_new(void)
    {
        freespace* fs = malloc(sizeof(*fs));
    
        if (!fs)
            return 0;
    
        int y;
    
        for (y = 0; y < FSHEIGHT; ++y)
        {
            memset(&fs->buf[y][0], 0, sizeof(fsbuf_type) * FSBUFWIDTH);
        }
    
        fs->left_to_right = true;
        fs->top_to_bottom = true;
    
        return fs;
    }
    
    
    void freespace_delete(freespace* fs)
    {
        if (!fs)
            return;
    
        free(fs);
    }
    
    /* would be private function: */
    void fs_set_buffer( fsbuf_type buf[FSHEIGHT][FSBUFWIDTH],
                        unsigned x,
                        unsigned y1,
                        unsigned xoffset,
                        unsigned width,
                        unsigned height)
    {
        fsbuf_type v;
        unsigned y;
    
        for (; width > 0 && x < FSBUFWIDTH; ++x)
        {
            if (width < xoffset)
                v = (((fsbuf_type)1 << width) - 1) << (xoffset - width);
            else if (xoffset < FSBUFBITS)
                v = ((fsbuf_type)1 << xoffset) - 1;
            else
                v = fsbuf_max;
    
            for (y = y1; y < y1 + height; ++y)
            {
    #ifdef FREESPACE_DEBUG
                if (buf[y][x] & v)
                    printf("**** over-writing area ****\n");
    #endif
                buf[y][x] |= v;
            }
    
            if (width < xoffset)
                return;
    
            width -= xoffset;
            xoffset = FSBUFBITS;
        }
    }
    
    
    _Bool freespace_remove(   freespace* fs,
                              unsigned width, unsigned height,
                              int* resultx,   int* resulty)
    {
        unsigned x, x1, y;
        unsigned w, h;
        unsigned xoffset, x1offset;
        unsigned tz; /* trailing zeros */
    
        fsbuf_type* xptr;
        fsbuf_type mask =   0;
        fsbuf_type v;
    
        _Bool scanning = false;
        _Bool offset = false;
    
        *resultx = -1;
        *resulty = -1;
    
        for (y = 0; y < (unsigned) FSHEIGHT - height; ++y)
        {
            scanning = false;
            xptr = &fs->buf[y][0];
    
            for (x = 0; x < FSBUFWIDTH; ++x, ++xptr)
            {
                if(*xptr == fsbuf_max)
                {
                    scanning = false;
                    continue;
                }
    
                if (!scanning)
                {
                    scanning = true;
                    x1 = x;
                    x1offset = xoffset = FSBUFBITS;
                    w = width;
                }
    retry:
                if (w < xoffset)
                    mask = (((fsbuf_type)1 << w) - 1) << (xoffset - w);
                else if (xoffset < FSBUFBITS)
                    mask = ((fsbuf_type)1 << xoffset) - 1;
                else
                    mask = fsbuf_max;
    
                offset = false;
    
                for (h = 0; h < height; ++h)
                {
                    v = fs->buf[y + h][x] & mask;
    
                    if (v)
                    {
                        tz = TRAILING_ZEROS(v);
                        offset = true;
                        break;
                    }
                }
    
                if (offset)
                {
                    if (tz)
                    {
                        x1 = x;
                        w = width;
                        x1offset = xoffset = tz;
                        goto retry;
                    }
                    scanning = false;
                }
                else
                {
                    if (w <= xoffset) /***** RESULT! *****/
                    {
                        fs_set_buffer(fs->buf, x1, y, x1offset, width, height);
                        *resultx = x1 * FSBUFBITS + (FSBUFBITS - x1offset);
                        *resulty = y;
                        return true;
                    }
                    w -= xoffset;
                    xoffset = FSBUFBITS;
                }
            }
        }
        return false;
    }
    
    
    int main(int argc, char** argv)
    {
        int x[1999];
        int y[1999];
        int w[1999];
        int h[1999];
    
        int i;
    
        freespace* fs = freespace_new();
    
        for (i = 0; i < 1999; ++i, ++u)
        {
            w[i] = rand() % 18 + 4;
            h[i] = rand() % 18 + 4;
    
            freespace_remove(fs, w[i], h[i], &x[i], &y[i]);
    /*
            freespace_dump(fs);
            printf("w:%d h:%d x:%d y:%d\n", w[i], h[i], x[i], y[i]);
            if (x[i] == -1)
                printf("not removed space %d\n", i);
            getchar();
    */
        }
    
        freespace_dump(fs);
        freespace_delete(fs);
    
        return 0;
    }