房间分配问题的讨论

akingli 2007-12-11 05:15:13
对房间分配问题的两种算法的分析:
1、精确算法
精确算法最简单的实现就是用递归,denghui0815写的递归算法是首先能想到的。但是,像房间分配这样的问题,计算量会随着学生数的增加而承几何级数增长,所以递归方法是不可取的。denghui0815同学说32个学生的数据在T2050上单线程跑了2秒,这绝对是他的数据比较特殊。以下我提供了两组数据供各位用递归法的大侠试验,大家可以对比的看一下结果。
2、模糊算法
模拟退火算法属于此类算法。此算法以较大的概率收敛与全局最优解,但是它的效率较低,搜索的时间越长,越接近全局最优解。关于此算法的变种本人正在学习、研究之中。
望大家能在此讨论一下各自的高见。
...全文
731 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
qingweisan 2010-12-07
  • 打赏
  • 举报
回复
可不可以提供几组数据给我?
akingli 2007-12-25
  • 打赏
  • 举报
回复
1、算两个人差别可以压位优化到log50 ,能不能具体解释一下,我也学学。
我现在没用那个大数组了,把计算学生兴趣差放到computeRoomAssignments()里面做了,有很多重复计算,也浪费了很多时间。

2、我发现在用了TBB实现并行计算之后程序的性能比没用TBB之前下降了10倍,intel 双核cpu的使用率到是达到100%了。
感觉TBB做了很多复杂的运算,很多时间浪费在task切换上了。也许是双核cpu不能发挥出TBB的最佳效果,4核可能会好很多。刚刚学TBB,忘大家指点。

3、我的程序片段。
typedef struct _STU_INTEREST_
{
INT32U interest[5]; // 每个INT32U 存放10个数据,每个数据占3位
}STU_INTEREST;

class SumDisharmony
{
INT32U my_student1;
INT32U my_student2;
STU_INTEREST* my_interestArray;
public:
INT32U sum;
void operator()(const blocked_range<size_t>& r)
{
for(size_t i=r.begin(); i!=r.end(); ++i)
{
sum += computeDisharmonyEx(my_student1, my_student2, my_interestArray, i);
}
}

SumDisharmony(SumDisharmony& x, split)
:my_student1(x.my_student1), my_student2(x.my_student2), my_interestArray(x.my_interestArray), sum(0)
{
}

void join(const SumDisharmony& y)
{
sum += y.sum;
}

SumDisharmony(INT32U student1, INT32U student2, STU_INTEREST* interestArray)
:my_student1(student1), my_student2(student2), my_interestArray(interestArray), sum(0)
{
}
};

INT32U computeDisharmonyEx(INT32U student1, INT32U student2, STU_INTEREST* interestArray, INT8U interest)
{
INT32S tempDelta = 0;
INT32U delta = 0;

tempDelta = (interestArray[student1].interest[interest / 10] >> (27 - (interest % 10) * 3)) & 0x07;
tempDelta -= (interestArray[student2].interest[interest / 10] >> (27 - (interest % 10) * 3)) & 0x07;
delta += ABS(tempDelta);

return delta;
}

INT32U computeDisharmony(INT32U student1, INT32U student2, STU_INTEREST* interestArray)
{
SumDisharmony sumDis(student1, student2, interestArray);
parallel_reduce(blocked_range<size_t>(0, STUDENT_INTEREST, 32), sumDis);

return sumDis.sum;
}

class Stream
{
SIMU_ANNEAL* my_ptr;
public:
Stream(SIMU_ANNEAL* root) : my_ptr(root)
{
}

bool pop_if_present(SIMU_ANNEAL*& item)
{
item = my_ptr;
if(item->nowInnerIterNumber >= item->maxInnerIterNumber)
{
return false;
}
else
{
item->nowInnerIterNumber++;
return true;
}
}
};

class Body
{
public:
typedef SIMU_ANNEAL* argument_type;
void operator()(SIMU_ANNEAL* pSimuAnneal) const
{
onceAnneal(pSimuAnneal);
}
};

void onceAnneal(SIMU_ANNEAL *pSimuAnneal)
{
INT32U index1 = 0;
INT32U index2 = 0;
INT32U tempIndex = 0;
INT32S delTatotalDis = 0;
float chgProbability = 0.0;
float random = 0.0;

changeStudent2opt(pSimuAnneal->studentNumber, index1, index2);

delTatotalDis = countDeltaDis(index1, index2, pSimuAnneal->indexArray, pSimuAnneal->interestArray);
if(delTatotalDis <= 0)
{
tempIndex = pSimuAnneal->indexArray[index1];
pSimuAnneal->indexArray[index1] = pSimuAnneal->indexArray[index2];
pSimuAnneal->indexArray[index2] = tempIndex;
}

// 大规模随机数据的随机算法产生的
// 局部最优解近似全局最优解,故此处
// 舍去模拟退火算法中跳出局部最优解
// 的算法。
#if 0
else
{
chgProbability = exp(-(delTatotalDis / pSimuAnneal->nowTemperature));
random = (rand() % 10000) /10000.0;

if(chgProbability > random)
{
tempIndex = pSimuAnneal->indexArray[index1];
pSimuAnneal->indexArray[index1] = pSimuAnneal->indexArray[index2];
pSimuAnneal->indexArray[index2] = tempIndex;
}
}
#endif
}


void parallelAnneal(SIMU_ANNEAL& simuAnneal)
{
tbb::parallel_while<Body> w;
Stream s(&simuAnneal);
Body annealBody;
w.run(s, annealBody);
}

kelkch 2007-12-25
  • 打赏
  • 举报
回复
我用的就是两个两个减出来加总的. 我想用汇编优化一下, 结果还不如C++的快
akingli 2007-12-24
  • 打赏
  • 举报
回复
呵呵 我的错! 居然用这么大的一个数组。完全没有必要的~
cosechy 2007-12-24
  • 打赏
  • 举报
回复
肯定不能两两算差别,要不就可以直接用匹配了

写程序中,不为了学习。。争取能今天写出来
街坊跳舞 2007-12-24
  • 打赏
  • 举报
回复
学习中,不为了参赛,就为了学习点东西!
denghui0815 2007-12-24
  • 打赏
  • 举报
回复
算两个人差别可以压位优化到log50

2^28 个学生 两两算差别 够你算了
cosechy 2007-12-23
  • 打赏
  • 举报
回复
2^28,这么大的数,每一组学生都穷举一遍都不可能

算两个人差别可以压位优化到log50。。
akingli 2007-12-14
  • 打赏
  • 举报
回复
在学生数超过30720的时候,我发现以下几点运算相当慢!
1、 for(row = 0; row < studentNumber; row++)
{
for(line = 0; line < studentNumber; line++)
{
if(line > row)
{
for(interestIndex = 0; interestIndex < STUDENT_INTEREST; interestIndex++)
{
delta = interestArray[row][interestIndex] - interestArray[line][interestIndex];
disharmonyArray[row][line] += ABS(delta);
}
}
else
{
disharmonyArray[row][line] = disharmonyArray[line][row];
}
}

}
给disharmonyArray[][]这个二维数组赋值,计算的很慢;与它相关的指针操作也很慢。

2、exp()这个函数的效率很低,计算的很慢。
akingli 2007-12-14
  • 打赏
  • 举报
回复
对于马尔可夫链的长度问题,理论上应该由学生数来决定。但是在解决实际问题时,出于对时间限制和机器性能的考虑,我们应该给它设一个上限,来保证算法的高效、结果的相对最优!
akingli 2007-12-14
  • 打赏
  • 举报
回复
模拟退火算法以概率1收敛与全局最优解,这是理论! 但是这个算法得出的结果对你当初选的初始化温度、马尔可夫链的长度是很敏感的,初值选的不好,要么结果很坏、要么搜索时间超长!
denghui0815 2007-12-11
  • 打赏
  • 举报
回复
The initial Disharmony is 0.420000
Time to compute room assignments is 0.14 seconds
Final Disharmony is 0.380000
请按任意键继续. . .

这个是用模拟退火的结果
denghui0815 2007-12-11
  • 打赏
  • 举报
回复
The initial Disharmony is 0.420000
Time to compute room assignments is 0.14 seconds
Final Disharmony is 0.380000
请按任意键继续. . .

这个是用模拟退火的结果

566

社区成员

发帖
与我相关
我的任务
社区描述
英特尔® 边缘计算,聚焦于边缘计算、AI、IoT等领域,为开发者提供丰富的开发资源、创新技术、解决方案与行业活动。
社区管理员
  • 英特尔技术社区
  • shere_lin
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧