MPI:区间分割法解代数方程

问题描述

区间分割法求解代数方程:给定一个函数,然后给定一个区间(保证函数在该区间内单调且有且仅有一个解),使用并行程序设计方法求出该解。(对于非单调、有多解的情况可能不适用,最多能找到一个解)

方法描述

  1. 进程0接收区间输入,并且限定仅接收一次。
  2. 进程0将区间划分为size(进程数目)个小区间。
  3. 然后进程0将(size-1)个区间广播给其它进程,进程0自己判断一个区间。
  4. 各进程判断要寻找的解是否在自己负责的区间;若在进程0负责的区间,更新区间信息,到步骤5;若在其他进程负责的区间,则将该区间发送给进程0。
  5. 进程0接收到新的区间后,判断该区间是否达到精度要求,达到则输区间中值作为近似解,同时进程0将结束信息发送给各进程;若未达到精度要求,则执行步骤2。

代码

#include <mpi.h>
#include <iostream>
#include <math.h>
using namespace std;

double func(double x) {
	return pow((x - 0.11),2)-3; //定义函数
}


int main(int argc, char* argv[]) {
	
	double a=0, b=0; //初始求解区间
	int fin = 1;
	double jd = 1.0 / 1000;// 精度
	double N=0;
	int flag = 1;
	double x, y;
	int gg = 1;
	
	int rank, size;
	MPI_Init(&argc, &argv);
	MPI_Comm_size(MPI_COMM_WORLD, &size);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Status status;
	
	while (flag==1) {
		
		if (rank == 0 and fin == 1) {
			cout << "输入初始求解区间:";
			cin >> a >> b;
			fin = 0;
			cout << a << b << size << endl;
		}
		
		if (rank == 0) {
			
			N = ((b - a) * 1.0) / size; // 分成size个区间的区间大小
			cout  << "N= " << N << endl;
			
			
			// 进程0广播
			for (int i = 1; i <= size - 1; i++) {
				x = a + i * N;
				y = a + (i + 1) * N;
				MPI_Send(&x, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
				MPI_Send(&y, 1, MPI_DOUBLE, i, 1, MPI_COMM_WORLD);
				cout << "进程0广播到进程"<< i << endl;
			}
			
			
			// 对进程0自身判断
			if (func(a) * func(a + N) <= 0) {
				b = a + N;
				gg = 0;
			}
			
			//进程0等待接收
			if (gg == 1) {
				MPI_Recv(&a, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 0, MPI_COMM_WORLD, &status);
				MPI_Recv(&b, 1, MPI_DOUBLE, MPI_ANY_SOURCE, 1, MPI_COMM_WORLD, &status);
			}
			
			gg = 1;
			cout << "新的区间(" << a << " , " << b << ")" << endl;
			if (b - a < jd) { //区间达到精度要求
				flag = 0;
				cout << "一个近似的解:" << (a + b) * 1.0 / 2 << endl;
				for (int i = 1; i <= size - 1; i++) {
					
					MPI_Send(&flag, 1, MPI_DOUBLE, i, 0, MPI_COMM_WORLD);
					MPI_Send(&flag, 1, MPI_DOUBLE, i, 1, MPI_COMM_WORLD);
					cout << "进程0广播结束标志到进程" << i << endl;
				}
			}}
		else {
			
			MPI_Recv(&x, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &status);
			MPI_Recv(&y, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, &status);
			
			if(x == y){
				flag = 0;
				cout << "进程" << rank << "接收来自进程0的结束进程广播" << endl;
				continue;}
			
			cout << "进程" << rank << "接收来自进程0的广播" << endl;
			if (func(x) * func(y) <= 0) { // 异号 或 有一个值是解
				MPI_Send(&x, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
				MPI_Send(&y, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
				cout << "*****进程" << rank << "将消息发送给进程0 " << endl;
			}
		}}
	cout << "进程 "<<rank<<" 结束!" << endl;
	
	MPI_Finalize();
	return 0;
}


结果展示

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我的size=8,因此[0,2]划分为8个区间,每个区间长度为0.25。第一次找到近似解在区间[1.75,2],不满足精度,然后进行第二次的区间划分,长度为0.03125。然后找到新的解区间[1.8125,1.84375],仍然不满足区间精度,继续划分,长度为0.00390625。然后找到新的解区间[1.83984,1.84375],仍不满足精度,继续划分,长度为0.000488281。然后找到新的解区间[1.8418,1.84204],满足精度,输出区间中值作为近似解。结束所有进程。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

同学陈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值