人工智能原理实验一:知识的表示与推理实验

news2024/11/24 23:06:46

一、实验目的

本实验课程是计算机、智能、物联网等专业学生的一门专业课程,通过实验,帮助学生更好地掌握人工智能相关概念、技术、原理、应用等;通过实验提高学生编写实验报告、总结实验结果的能力;使学生对智能程序、智能算法等有比较深入的认识。本实验通过不同知识的表达与推理问题,强化学生对知识表示的了解和应用,为人工智能后续环节的课程奠定基础。

二、基本要求

1、实验前,复习《人工智能》课程中的有关内容。

2、准备好实验数据。

3、编程或验证需要独立完成,程序应加适当的注释。

4、完成实验报告。

三、实验软件

使用C或C++(Visual studio平台等),或其它语言,如matlab或Python。

四、实验内容:

(一)猴子摘香蕉问题

利用一阶谓词逻辑求解猴子摘香蕉问题:房内有一个猴子,一个箱子,天花板上挂了一串香蕉,其位置如图1所示,猴子为了拿到香蕉,它必须把箱子搬到香蕉下面,然后再爬到箱子上。请定义必要的谓词,列出问题的初始化状态(即下图所示状态),目标状态(猴子拿到了香蕉,站在箱子上,箱子位于位置b)。(附加:从初始状态到目标状态的谓词演算过程。) 

1、定义描述环境状态的谓词。

AT(x,w):x在w处,个体域:x?{monkey},w?{a,b,c,box};

HOLD(x,t):x手中拿着t,个体域:t?{box,banana};

EMPTY(x):x手中是空的;

ON(t,y):t在y处,个体域:y?{b,c,ceiling};

CLEAR(y):y上是空的;

BOX(u):u是箱子,个体域:u?{box};

BANANA(v):v是香蕉,个体域:v?{banana};

2、使用谓词、连结词、量词来表示环境状态。

问题的初始状态可表示为:So:AT(monkey,a)->EMPTY(monkey)->ON(box,c)->ON(banana,ceiling)->CLEAR(b)->BOX(box)->BANANA(banana)

要达到的目标状态为:Sg:AT(monkey,box)->HOLD(monkey,banana)->ON(box,b)->CLEAR(ceiling)->CLEAR(c)->BOX(box)->BANANA(banana)

3、从初始状态到目标状态的转化, 猴子需要完成一系列操作, 定义操作类谓词表示其动作。

WALK(m,n):猴子从m走到n处,个体域:m,n?{a,b,c};

CARRY(s,r):猴子在r处拿到s,个体域:r?{c,ceiling},s?{box,banana};

CLIMB(u,b):猴子在b处爬上u;

这3个操作也可分别用条件和动作来表示。条件直接用谓词公式表示,是为完成相应操作所必须具备的条件;当条件中的事实使其均为真时,则可激活操作规则,于是可执行该规则中的动作部分。动作通过前后状态的变化表示,即通过从动作前删除或增加谓词公式来描述动作后的状态。

4、按照行动计划, 一步步进行状态替换, 直至目标状态

AT(monkey,a)?EMPTY(monkey)?ON(box,c)?ON(banana,ceiling)?CLEAR(b)?BOX(box)?

BANANA(banana)

AT(monkey,c)?EMPTY(monkey)?ON(box,c)?ON(banana,ceiling)?CLEAR(b)?BOX(box)?

BANANA(banana)

AT(monkey,c)?HOLD(monkey,box)?ON(banana,ceiling)?CLEAR(b)?CLEAR(c)?BOX(box)?

BANANA(banana)

AT(monkey,b)?HOLD(monkey,box)?ON(banana,ceiling)?CLEAR(b)?CLEAR(c)?BOX(box)?

BANANA(banana)

AT(monkey,box)?EMPTY(monkey)?ON(box,b)?ON(banana,ceiling)?CLEAR(c)?BOX(box)?

BANANA(banana)

AT(monkey,box)?HOLD(monkey,banana)?ON(box,b)?CLEAR(ceiling)?CLEAR(c)?BOX(box)?

BANANA(banana)(目标得解)

猴子行动的规则序列是:WALK(a,c)→CARRY(c,box)→WALK(c,b)→CLIMB(box,b)→

CARRY(banana,ceiling)

5、参考代码:

#include <stdio.h>
struct State
{
	int monkey; /*-1:Monkey at A;0: Monkey at B;1:Monkey at C;*/
    int box; /*-1:box at A;0:box at B;1:box at C;*/
    int banana; /*Banana at B,Banana=0*/
    int monbox; /*-1: monkey on the box;1: monkey  the box;*/
};
struct State States [150];
char* routesave[150];
/*function monkeygoto,it makes the monkey goto the other place*/
void monkeygoto(int b,int i)
{  
	int a;
	a=b;
	if (a==-1)
	{
		routesave[i]="Monkey go to A";
		States[i+1]=States[i];
		States[i+1].monkey=-1;
	}
	else if(a==0)
	{
		routesave[i]="Monkey go to B";
		States[i+1]=States[i];
		States[i+1].monkey=0;
	}
	else if(a==1)
	{
		routesave[i]="Monkey go to C";
		States[i+1]=States[i];
		States[i+1].monkey=1;
	}
	else
    {
		printf("parameter is wrong");
	}
}
/*end function monkeyygoto*/
/*function movebox,the monkey move the box to the other place*/
void movebox(int a,int i)
{  
	int B;
	B=a;
	if(B==-1)
	{
		routesave[i]="monkey move box to A";
		States[i+1]=States[i];
		States[i+1].monkey=-1;
		States[i+1].box=-1;
	}
	else if(B==0)
	{
		routesave[i] = "monkey move box to B";
		States[i+1]=States[i];
		States[i+1].monkey=0;
		States[i+1].box=0;
	}
	else if(B==1)
	{
		routesave[i] = "monkey move box to C";
		States[i+1]=States[i];
		States[i+1].monkey=1;
		States[i+1].box=1;
	}
	else
	{
		printf("parameter is wrong");
	}
}
/*end function movebox*/
/*function climbonto,the monkey climb onto the box*/
void climbonto(int i)
{
	routesave[i]="Monkey climb onto the box";
	States[i+1]=States[i];
	States[i+1].monbox=1;
}
/*function climbdown,monkey climb down from the box*/
void climbdown(int i)
{  
	routesave[i]="Monkey climb down from the box";
	States[i+1]=States[i];
	States[i+1].monbox=-1;
}
/*function reach,if the monkey,box,and banana are at the same place,the monkey reach banana*/
void reach(int i)
{   
	routesave[i]="Monkey reach the banana";
}
/*output the solution to the problem*/
void showSolution(int i)
{
    int c;
    printf ("%s \n", "Result to problem:");
    for(c=0; c<i+1; c++)
    {
		printf ("Step %d : %s \n",c+1,routesave[c]);
    }
    printf("\n");
}
/*perform next step*/
void nextStep(int i)
{
	int c;
    int j;
    if(i>=150)
    {
		printf("%s  \n", "steplength reached 150,have problem ");
        return;
    }
	for (c=0; c<i; c++) /*if the current state is same to previous,retrospect*/
    {
		if(States[c].monkey==States[i].monkey&&States[c].box==States[i].box&&States[c].banana==States[i].banana&&States[c].monbox==States[i].monbox)
        {
			return;
        }
    }
    if(States[i].monbox==1&&States[i].monkey==0&&States[i].banana==0&&States[i].box==0)
    {
		showSolution(i);
		printf("Press any key to continue \n");
		getchar();/*to save screen for user,press any key to continue*/
		return;
	}  
	j=i+1;    
	if(States[i].monkey==0)
	{ 
		if(States[i].box==0)
		{
			if(States[i].monbox==-1)
			{
				climbonto(i);
				reach(i+1);
				nextStep(j);
				/*monkeygoto(-1,i);
				nextStep(j);
				monkeygoto(0,i);
				nextStep(j);
				movebox(-1,i);
				nextStep(j);
				movebox(0,i);
				nextStep(j);*/
			}
			else
			{
				reach(i+1);
				nextStep(j);
				/*climbdown(i);
				nextStep(j);*/
			}
		}
		else if(States[i].box==1)
		{
			/*monkeygoto(-1,i);
			nextStep(j);*/
			monkeygoto(1,i);
			nextStep(j);
			movebox(0,i);
			nextStep(j);
			climbonto(i);
			reach(i+1);
			nextStep(j);
		}
		else /*box==-1*/
		{
			monkeygoto(-1,i);
			nextStep(j);
			movebox(0,i);
			nextStep(j);
			climbonto(i);
			reach(i+1);
			nextStep(j);
		}
    }
	/*end if*/
	if(States[i].monkey==-1)
    { 
		if(States[i].box==-1)
		{
			if(States[i].monbox==-1)
			{ 
				movebox(0,i);
				nextStep(j);
				climbonto(i);
				reach(i+1);
				nextStep(j);
			}
			else
			{
				climbdown(i);
				nextStep(j);
				movebox(0,i);
				nextStep(j);
				climbonto(i);
				reach(i+1);
				nextStep(j);
			}
		}
		else if(States[i].box==0)
		{ 
			monkeygoto(0,i);
			nextStep(j);
			climbonto(i);
			reach(i+1);
			nextStep(j);
		}
		else
		{
			monkeygoto(1,i);
			nextStep(j);
			movebox(0,i);
			nextStep(j);
			climbonto(i);
			reach(i+1);
			nextStep(j);
		}
	}
	/*end if*/
	if(States[i].monkey==1)
    {	
		if (States[i].box==1)
		{
			if(States[i].monbox==-1)
			{     
				movebox(0,i);
				nextStep(j);
				climbonto(i);
				reach(i+1);
				nextStep(j);
			}
			else
			{
				climbdown(i);
				nextStep(j);
				movebox(0,i);
				nextStep(j);
				climbonto(i);
				reach(i+1);
				nextStep(j);          
			}
		}
		else if(States[i].box==-1)
		{        
			monkeygoto(-1,i);
			nextStep(j);
			movebox(0,i);
			nextStep(j);
 			movebox(0,i);
			nextStep(j);
			climbonto(i);
			reach(i+1);
			nextStep(j);
		}
		else
		{
			monkeygoto(0,i);
			nextStep(j);
			movebox(0,i);
			nextStep(j);
			climbonto(i);
			reach(i+1);
			nextStep(j);
		}
    }
	/*end if*/
}/*end nextStep*/
int main()
{
    States[0].monkey=-1;
    States[0].box=1;
    States[0].banana=0;
    States[0].monbox=-1;
    nextStep(0);
}

(二)传教士(牧师)与野人问题

问题描述:

有n个牧师和n个野人准备渡河,但只有一条能容纳c个人的小船,为了防止野人侵犯牧师,要求无论在何处,牧师的人数不得少于野人的人数(除非牧师人数为0),且假定野人与牧师都会划船,试设计一个算法,确定他们能否渡过河去,若能,则给出小船来回次数最少的最佳方案。

实验步骤:

输入:牧师人数(即野人人数):n;小船一次最多载人量:c。  

输出:若问题无解,则显示Failed,否则,显示Successed输出所有可行方案,并标注哪一组是最佳方案。用三元组(X1, X2, X3)表示渡河过程中的状态。并用箭头连接相邻状态以表示迁移过程:初始状态->中间状态->目标状态。   

例:当输入n=2,c=2时,输出:221->200->211->010->021->000;  

其中:X1表示起始岸上的牧师人数;X2表示起始岸上的野人人数;X3表示小船现在位置(1表示起始岸,0表示目的岸)。

要求:写出算法的设计思想和源程序,并有用户界面实现人机交互(控制台或者窗口都可以),进行输入和输出结果,如:

Please input n: 2         Please input c: 2

Optimal Procedure: 221->200->211->010->021->000

Successed or Failed?: Successed     

五、学生实验报告要求

(1)对于猴子摘香蕉问题根据自己编写代码或者参考代码,用不同的初始状态测试代码,记录每种初始状态下的输出结果,并对每个结果进行解释。

(2)完善猴子摘香蕉问题参考代码,参考代码中有什么问题?应该如何修改会更好。

问题:

1. 数组索引和函数调用:

   使用数组索引i访问和更新状态。确保数组索引在范围内,以避免潜在的内存问题。

   考虑将状态数组封装在结构体内部或将其作为参数传递给函数,而不是使用全局数组。

2. 字符串赋值:

   避免直接将字符串赋值给 routesave[i],例如 routesave[i] = "Monkey go to A";,使用strcpy或类似的函数进行字符串赋值,以避免潜在的问题。

3. 未使用的变量:

   movebox函数中声明了变量int B;但未使用。移除它以避免混淆。

4. 递归函数:

   nextStep 函数是递归的,它一直调用自身。这可能会导致大量步骤时发生堆栈溢出。考虑使用迭代方法,或者根据需要增加堆栈大小。

5. 内存管理:

   代码使用一个固定大小的数组 (States[150]) 存储状态。如果状态数量不能事先确定,考虑使用动态内存分配或其他数据结构。

(3)传教士(牧师)与野人问题,写出状态表示的数据结构,还有每种解的状态迁移图示。

struct State {
    int m;//传教士
    int c;//野人
    int dep;//已划船次数
    int boat;//左岸是否有船
    bool friend operator <(const struct State& a, const struct State& b)//为实现自定义类型的set提供排序规则
    {
        return a.dep < b.dep;//升序排序
    }
};

例:n=2,c=2时:

1.(2,2,1) -> (2,0,0) -> (2,1,1) -> (0,1,0) -> (0,2,1) -> (0,0,0)

2.(2,2,1) -> (2,0,0) -> (2,1,1) -> (0,1,0) -> (1,1,1) -> (0,0,0)

3.(2,2,1) -> (1,1,0) -> (2,1,1) -> (0,1,0) -> (0,2,1) -> (0,0,0)

4.(2,2,1) -> (1,1,0) -> (2,1,1) -> (0,1,0) -> (1,1,1) -> (0,0,0)

(4)写出传教士(牧师)与野人问题的程序清单(语言不限)

#include<iostream>
#include<set>
#include<vector>
using namespace std;

int n, c;//传教士的人数及船的载客量
int min_deep = INT_MAX;//船的最小来回次数
int path = 0;//可达路径的数量

struct State {
    int m;//传教士
    int c;//野人
    int dep;//已划船次数
    int boat;//左岸是否有船
    bool friend operator <(const struct State& a, const struct State& b)//为实现自定义类型的set提供排序规则
    {
        return a.dep < b.dep;//升序排序
    }
};
set<State> Set;//自定义类型State实现set
vector<vector<State>> res;//保存所有路径

//判断状态是否已经在当前路径中,避免重复加入
bool isExist(State next)
{
    for (auto it = Set.begin(); it != Set.end(); it++)
        if (it->m == next.m && it->c == next.c && it->boat == next.boat)
            return true;
    return false;
}
//输出路径
void output()
{
    for (int i = 0; i < res.size(); i++)
    {
        if (res[i].size() == min_deep + 1)//判断是否为最优路径
            cout << "optimal" << endl;
        cout << "Solution" << i + 1 << endl;
        for (int j = 0; j < res[i].size(); j++)//依次输出路径上的各个状态
            cout << "(" << res[i][j].m << "," << res[i][j].c << "," << res[i][j].boat << ")" << endl;
        cout << endl;
    }
}
//用深度优先进行搜索
void dfs(State s)
{
    Set.insert(s);//加入当前路径的集合中(已按状态的先后顺序排序)
    if (s.m == 0 && s.c == 0)//目标状态
    {
        if (s.dep < min_deep)//记录最短路径的划船次数
            min_deep = s.dep;
        path++;
        vector<State> v(Set.begin(), Set.end());
        res.push_back(v);//保存该路径
        Set.erase(--Set.end());//已达终点,进行回退
        return;
    }
    if (s.boat == 1)//左岸
    {
        for (int i = c; i >= 1; i--)//船载i从左往右划
        {
            if (i > s.m + s.c)//i多于左岸的总人数
                continue;
            for (int j = i; j >= 0; j--)//船上有j个野人
            {
                if (j > s.c || i - j > s.m)//多于左岸传教士、野人的实际人数
                    continue;
                if (j != i && j > i - j)//船上传教士的人数少于野人的人数
                    continue;
                if (s.m - (i - j) != 0 && s.m - (i - j) != n && s.m - (i - j) != s.c - j)//左岸剩下的传教士与野人的人数不相等
                    continue;
                State next;
                next.boat = 0;
                next.m = s.m - (i - j);
                next.c = s.c - j;
                next.dep = s.dep + 1;
                if (!isExist(next))//判断当前路径是否存在该状态
                    dfs(next);
            }
        }
    }
    else//右岸
    {
        for (int i = c; i >= 1; i--)//船载i个人从右往左划
        {
            if (i > (n - s.m) + (n - s.c))//i多于右岸的总人数
                continue;
            for (int j = i; j >= 0; j--)//船上有j个野人
            {
                if (j > n - s.c || i - j > n - s.m)//多于右岸传教士、野人的实际人数
                    continue;
                if (j != i && j > i - j)//船上野人的数量大于传教士的数量
                    continue;
                if (n - s.m - (i - j) != 0 && n - s.m - (i - j) != n && n - s.m - (i - j) != n - s.c - j)//右岸剩下的传教士人数与野人不相等
                    continue;
                State next;
                next.boat = 1;
                next.m = s.m + (i - j);
                next.c = s.c + j;
                next.dep = s.dep + 1;
                if (!isExist(next))//判断当前路径是否存在该状态
                    dfs(next);
            }
        }
    }
    Set.erase(--Set.end());//无路可走,进行回退
}

int main()
{
    cout << "请输入传教士(野人)人数:";
    cin >> n;
    cout << endl;
    cout << "请输入船的载人量:";
    cin >> c;
    State start;//初始状态
    start.m = start.c = n;
    start.boat = 1;
    start.dep = 0;
    dfs(start);
    cout << "Successed or Failed?:";
    if (path == 0)
        cout << "failed" << endl;
    else
    {
        cout << "Successed" << endl;
        output();
        cout << "共有" << path << "条路径。" << endl;
        cout << "min_deep=" << min_deep << endl;
    }
}

(5)实验结果讨论。

这是n=2,c=2的情况,共有四种情况的最短路径,最短路径为5

这是n=3,c=2的情况,共有四种情况的最短路径,最短路径为11

3 汉诺塔问题

汉诺塔问题来自一个古老的传说:在世界刚被创建的时候有一座钻石宝塔(塔A),其上有64个金碟。所有碟子按从大到小的次序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔(塔B和塔C)。从世界创始之日起,婆罗门的牧师们就一直在试图把塔A上的碟子移动到塔C上去,其间借助于塔B的帮助。每次只能移动一个碟子,任何时候都不能把一个碟子放在比它小的碟子上面。当牧师们完成任务时,世界末日也就到了。

  采用问题归约法把汉诺塔问题分成以下三个步骤实现:

  1. 将塔A上的n-1个碟子借助塔C先移到塔B上
  2. 把塔A上剩下的一个碟子移到塔C上
  3. 把n-1个碟子从塔B借助于塔A移到塔C上

实验要求: 

  1. 让盘子数从2 开始到7进行实验,记录程序运行时间和递归调用次数。

2.画出盘子数n和运行时间t 、递归调用次数m的关系图,并进行分析

分析:

运行时间 vs 盘子数(n): 通常来说,汉诺塔问题的解决时间呈指数增长。图表中应该看到一个指数曲线,显示随着盘子数的增加,解决问题所需的时间迅速增加。但是运行时间都太短了,看不出明显趋势。

递归调用次数 vs 盘子数(n): 递归调用次数也是指数级增长的,因为每增加一个盘子,递归调用次数就翻倍。这与汉诺塔问题的递归性质相一致。

在解决类似指数级增长问题时,递归算法可能会面临的性能挑战。

实验代码:

import time

def hanoi(n, source, target, auxiliary):
    global recursive_calls
    if n > 0:
        recursive_calls += 1
        hanoi(n - 1, source, auxiliary, target)
        # 移动盘子
        # print(f"Move disk {n} from {source} to {target}")
        hanoi(n - 1, auxiliary, target, source)

def run_experiment(n):
    global recursive_calls
    recursive_calls = 0
    start_time = time.time()
    hanoi(n, 'A', 'C', 'B')
    end_time = time.time()
    execution_time = end_time - start_time
    return execution_time, recursive_calls

# 实验
results = []
for i in range(2, 8):
    time_taken, calls_made = run_experiment(i)
    results.append((i, time_taken, calls_made))

# 打印结果
print("n\tTime(s)\tRecursive Calls")
for result in results:
    print(f"{result[0]}\t{result[1]:.6f}\t{result[2]}")

import matplotlib.pyplot as plt

def plot_results(results):
    n_values = [result[0] for result in results]
    time_values = [result[1] for result in results]
    calls_values = [result[2] for result in results]

    # Plotting time vs n
    plt.figure(figsize=(10, 5))
    plt.subplot(1, 2, 1)
    plt.plot(n_values, time_values, marker='o')
    plt.title('Time vs Number of Disks')
    plt.xlabel('Number of Disks (n)')
    plt.ylabel('Time (s)')

    # Plotting recursive calls vs n
    plt.subplot(1, 2, 2)
    plt.plot(n_values, calls_values, marker='o', color='r')
    plt.title('Recursive Calls vs Number of Disks')
    plt.xlabel('Number of Disks (n)')
    plt.ylabel('Recursive Calls')

    plt.tight_layout()
    plt.show()

# 实验
results = []
for i in range(2, 8):
    time_taken, calls_made = run_experiment(i)
    results.append((i, time_taken, calls_made))

# 绘制图表
plot_results(results)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2228851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

混凝土裂缝图像分割系统:快速图像识别

混凝土裂缝图像分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-RFAConv&#xff06;yolov8-seg-C2f-SCConv等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Glo…

不再输入单号查快递,批量查快递单号信息的新方法,智能排序快递时效并查找时效相同的单号,一站式物流查询解决方案

厌倦了逐个输入快递单号查询物流信息的繁琐过程&#xff1f;想要一键就能批量查询快递单号&#xff0c;并且智能排序快递时效&#xff0c;轻松查找时效相同的单号&#xff1f;那么&#xff0c;恭喜你&#xff0c;你即将解锁快递查询的新境界&#xff01;快递批量查询高手软件&a…

国标GB28181设备管理软件EasyGBS国标GB28181公网平台应用到“雪亮工程”

随着信息技术的飞速发展&#xff0c;视频监控领域正经历从传统安防向智能化、网络化安防的深刻转变。在这一变革中&#xff0c;国标GB28181设备管理软件EasyGBS凭借其强大的功能和广泛的应用场景&#xff0c;成为推动这一转变的重要力量。特别是在“雪亮工程”这一重要的群众性…

Redis 哨兵 总结

前言 相关系列 《Redis & 目录》《Redis & 哨兵 & 源码》《Redis & 哨兵 & 总结》《Redis & 哨兵 & 问题》 参考文献 《Redis的主从复制和哨兵机制详解》《Redis中的哨兵&#xff08;Sentinel&#xff09;》《【Redis实现系列】Sentinel自动故…

springboot使用配置类从 application.yml 或 application.properties 文件中读取静态属性

springboot使用配置类从 application.yml 或 application.properties 文件中读取静态属性 1. 配置类定义 通过 ConfigurationProperties(prefix “data-base-check”)&#xff0c;Spring Boot 将带有 data-base-check 前缀的属性从 application.yml 或 application.propertie…

Java 中的微服务架构与 Spring Boot 集成(30/30)

目录 Java 中的微服务架构与 Spring Boot 集成 1. 微服务架构概述 2. Spring Boot 简介 2.1 Spring Boot 的特点 3. 使用 Spring Boot 构建微服务 3.1 构建一个简单的微服务 4. 服务发现与注册中心 4.1 使用 Eureka 实现服务注册和发现 5. 使用 Spring Cloud Gateway …

ssm020基于ssm的人才招聘网站+jsp(论文+源码)_kaic

摘 要 随着科技的发展&#xff0c;人才招聘的方式也发生着改变。本基于ssm的人才招聘网站正是采用计算机技术和网络设计的新型系统&#xff0c;可以有效的把招聘信息与网络相结合&#xff0c;为用户提供工作帮助和管理需求。本系统采用mysql数据库存储数据&#xff0c;兼容性…

Servlet 3.0 新特性全解

文章目录 Servlet3.0新特性全解Servlet 3.0 新增特性Servlet3.0的注解Servlet3.0的Web模块支持servlet3.0提供的异步处理提供异步原因实现异步原理配置servlet类成为异步的servlet类具体实现异步监听器改进的ServletAPI(上传文件) Servlet3.0新特性全解 tomcat 7以上的版本都支…

全球最大开源系统遭“绑架”,华为携国产系统冲出国门,优势尽显

被“绑架”的Linux 在科技飞速发展的今天&#xff0c;开源软件已成为全球技术合作与创新的重要基石。其中大家熟知的开源系统Linux内核项目&#xff0c;自1991年由芬兰学生Linus Torvalds创建以来&#xff0c;一直以其开放性、协作性和透明性著称。它鼓励全球各地的开发者共同…

一体化运维监控管理平台:构建高效、可靠的IT运维体系

在当今数字化转型的浪潮中&#xff0c;企业的IT系统日益复杂&#xff0c;运维工作面临着前所未有的挑战。如何确保IT基础设施的稳定运行&#xff0c;提高运维效率&#xff0c;成为每个企业关注的焦点。为此&#xff0c;我们推出了一体化运维监控管理平台&#xff0c;旨在通过全…

操作系统笔记(五)信号量,经典的IPC问题(读写者问题...)

信号量 一个信号量是一个包含两部分内容的数据结构&#xff1a; (a) 一个整数计数器, COUNT (b) 一个记录阻塞进程ID的队列, Q 信号量有两个原子操作&#xff1a; UP(V操作&#xff09; 和 DOWN (P操作) DOWN(S): if (S.count > 0) S.count …

基于SpringBoot+Vue的前后端分离的大学自动排课系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 在这个背景下&#xf…

【IEEE出版|:IEEE Xplore,EI Compendex,Scopus检索|征稿正在进行中!】

第七届机械工程与智能制造国际会议&#xff08;WCMEIM 2024&#xff09; 2024 7th World Conference on Mechanical Engineering and Intelligent Manufacturing 【会议信息】 会议日期&#xff1a;2024年11月15-17日 会议地点&#xff1a;中国武汉&#xff08;武汉纺织大学…

HTMLCSS:3D旋转动画机器人摄像头

效果演示 创建了一个3D机器人摄像头效果。 HTML <div class"modelViewPort"><div class"eva"><div class"head"><div class"eyeChamber"><div class"eye"></div><div class&quo…

ZeroNL2SQL:零样本 NL2SQL

发布于&#xff1a;2024 年 10 月 30 日 星期三 #RAG #NL2SQL # Zero-Shot 自然语言到 SQL&#xff08;NL2SQL&#xff09;的转换是一个重要的研究领域&#xff0c;它允许非技术用户轻松访问和分析数据&#xff0c;在商业智能、数据分析等领域具有广泛的应用前景。然而&#x…

Qgis 开发初级 《ToolBox》

Qgis 有个ToolBox 的&#xff0c;在Processing->ToolBox 菜单里面&#xff0c;界面如下。 理论上Qgis这里面的工具都是可以用脚本或者C 代码调用的。界面以Vector overlay 为例子简单介绍下使用方式。Vector overlay 的意思是矢量叠置分析&#xff0c;和arcgis软件类似的。点…

三合一无线键鼠中射频芯片-PHY6233

PHY6233 三合一键鼠芯片在键鼠领域占据着重要的地位。它以其强大的性能和广泛的适用性&#xff0c;成为众多键鼠产品的核心组件。PHY6233 芯片能够提供出色的操作体验。它可以支持多达几乎 100 个按键的支持&#xff0c;满足了用户对多功能键鼠的需求。同时&#xff0c;该芯片还…

基于STM32F103的计秒设计

基于STM32F103的计秒设计 仿真软件&#xff1a; Proteus 8.17 编程软件&#xff1a; Keil 5 仿真实现&#xff1a; 在4位数码管上进行计秒显示&#xff0c;每100ms改变一次数值。 数码管原理&#xff1a; 数码管是一种常用的显示器件&#xff0c;主要用于显示数字和一些字母…

万圣夜,Codigger

在这个神秘的万圣节&#xff0c;让Codigger&#xff0c;一个专业的分布式操作系统&#xff0c;带领你踏入未知的编程世界&#xff01;就像变装成各种角色一样&#xff0c;Codigger也以其独特的能力和技巧&#xff0c;在数字世界中展现无穷魅力。让我们一起在这个神秘的节日里&a…

探索光耦:光耦——光伏逆变器中的智慧守护者

在全球清洁能源的浪潮中&#xff0c;光伏产业正以前所未有的速度蓬勃发展。作为光伏发电系统的核心设备&#xff0c;光伏逆变器扮演着将直流电转化为交流电的关键角色&#xff0c;其性能直接关系到整个系统的效率和安全性。而在这一复杂而精细的转换过程中&#xff0c;光电耦合…