NS3学习——tcpVegas算法代码详解(1)

news2024/12/26 18:33:43

目录

一、源码

二、详解

1.定义日志和命名空间

2.注册Typeld类:TcpVegas和GetTypeId方法的实现

3.构造函数和析构函数

4.TcpVegas类中成员函数

(1) Fork函数

(2) PktsAcked函数

(3) EnableVegas函数

(4) DisableVegas函数


一、源码

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2016 ResiliNets, ITTC, University of Kansas
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Author: Truc Anh N. Nguyen <annguyen@ittc.ku.edu>
 *
 * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
 * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
 * Information and Telecommunication Technology Center (ITTC)
 * and Department of Electrical Engineering and Computer Science
 * The University of Kansas Lawrence, KS USA.
 */

#include "tcp-vegas.h"
#include "tcp-socket-state.h"

#include "ns3/log.h"

namespace ns3 {

NS_LOG_COMPONENT_DEFINE ("TcpVegas");
NS_OBJECT_ENSURE_REGISTERED (TcpVegas);

TypeId
TcpVegas::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::TcpVegas")
    .SetParent<TcpNewReno> ()
    .AddConstructor<TcpVegas> ()
    .SetGroupName ("Internet")
    .AddAttribute ("Alpha", "Lower bound of packets in network",
                   UintegerValue (2),
                   MakeUintegerAccessor (&TcpVegas::m_alpha),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("Beta", "Upper bound of packets in network",
                   UintegerValue (4),
                   MakeUintegerAccessor (&TcpVegas::m_beta),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("Gamma", "Limit on increase",
                   UintegerValue (1),
                   MakeUintegerAccessor (&TcpVegas::m_gamma),
                   MakeUintegerChecker<uint32_t> ())
  ;
  return tid;
}

TcpVegas::TcpVegas (void)
  : TcpNewReno (),
    m_alpha (2),
    m_beta (4),
    m_gamma (1),
    m_baseRtt (Time::Max ()),
    m_minRtt (Time::Max ()),
    m_cntRtt (0),
    m_doingVegasNow (true),
    m_begSndNxt (0)
{
  NS_LOG_FUNCTION (this);
}

TcpVegas::TcpVegas (const TcpVegas& sock)
  : TcpNewReno (sock),
    m_alpha (sock.m_alpha),
    m_beta (sock.m_beta),
    m_gamma (sock.m_gamma),
    m_baseRtt (sock.m_baseRtt),
    m_minRtt (sock.m_minRtt),
    m_cntRtt (sock.m_cntRtt),
    m_doingVegasNow (true),
    m_begSndNxt (0)
{
  NS_LOG_FUNCTION (this);
}

TcpVegas::~TcpVegas (void)
{
  NS_LOG_FUNCTION (this);
}

Ptr<TcpCongestionOps>
TcpVegas::Fork (void)
{
  return CopyObject<TcpVegas> (this);
}

void
TcpVegas::PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
                     const Time& rtt)
{
  NS_LOG_FUNCTION (this << tcb << segmentsAcked << rtt);

  if (rtt.IsZero ())
    {
      return;
    }

  m_minRtt = std::min (m_minRtt, rtt);
  NS_LOG_DEBUG ("Updated m_minRtt = " << m_minRtt);

  m_baseRtt = std::min (m_baseRtt, rtt);
  NS_LOG_DEBUG ("Updated m_baseRtt = " << m_baseRtt);

  // Update RTT counter
  m_cntRtt++;
  NS_LOG_DEBUG ("Updated m_cntRtt = " << m_cntRtt);
}

void
TcpVegas::EnableVegas (Ptr<TcpSocketState> tcb)
{
  NS_LOG_FUNCTION (this << tcb);

  m_doingVegasNow = true;
  m_begSndNxt = tcb->m_nextTxSequence;
  m_cntRtt = 0;
  m_minRtt = Time::Max ();
}

void
TcpVegas::DisableVegas ()
{
  NS_LOG_FUNCTION (this);

  m_doingVegasNow = false;
}

void
TcpVegas::CongestionStateSet (Ptr<TcpSocketState> tcb,
                              const TcpSocketState::TcpCongState_t newState)
{
  NS_LOG_FUNCTION (this << tcb << newState);
  if (newState == TcpSocketState::CA_OPEN)
    {
      EnableVegas (tcb);
    }
  else
    {
      DisableVegas ();
    }
}

void
TcpVegas::IncreaseWindow (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked)
{
  NS_LOG_FUNCTION (this << tcb << segmentsAcked);

  if (!m_doingVegasNow)
    {
      // If Vegas is not on, we follow NewReno algorithm
      NS_LOG_LOGIC ("Vegas is not turned on, we follow NewReno algorithm.");
      TcpNewReno::IncreaseWindow (tcb, segmentsAcked);
      return;
    }

  if (tcb->m_lastAckedSeq >= m_begSndNxt)
    { // A Vegas cycle has finished, we do Vegas cwnd adjustment every RTT.

      NS_LOG_LOGIC ("A Vegas cycle has finished, we adjust cwnd once per RTT.");

      // Save the current right edge for next Vegas cycle
      m_begSndNxt = tcb->m_nextTxSequence;

      /*
       * We perform Vegas calculations only if we got enough RTT samples to
       * insure that at least 1 of those samples wasn't from a delayed ACK.
       */
      if (m_cntRtt <= 2)
        {  // We do not have enough RTT samples, so we should behave like Reno
          NS_LOG_LOGIC ("We do not have enough RTT samples to do Vegas, so we behave like NewReno.");
          TcpNewReno::IncreaseWindow (tcb, segmentsAcked);
        }
      else
        {
          NS_LOG_LOGIC ("We have enough RTT samples to perform Vegas calculations");
          /*
           * We have enough RTT samples to perform Vegas algorithm.
           * Now we need to determine if cwnd should be increased or decreased
           * based on the calculated difference between the expected rate and actual sending
           * rate and the predefined thresholds (alpha, beta, and gamma).
           */
          uint32_t diff;
          uint32_t targetCwnd;
          uint32_t segCwnd = tcb->GetCwndInSegments ();

          /*
           * Calculate the cwnd we should have. baseRtt is the minimum RTT
           * per-connection, minRtt is the minimum RTT in this window
           *
           * little trick:
           * desidered throughput is currentCwnd * baseRtt
           * target cwnd is throughput / minRtt
           */
          double tmp = m_baseRtt.GetSeconds () / m_minRtt.GetSeconds ();
          targetCwnd = static_cast<uint32_t> (segCwnd * tmp);
          NS_LOG_DEBUG ("Calculated targetCwnd = " << targetCwnd);
          NS_ASSERT (segCwnd >= targetCwnd); // implies baseRtt <= minRtt

          /*
           * Calculate the difference between the expected cWnd and
           * the actual cWnd
           */
          diff = segCwnd - targetCwnd;
          NS_LOG_DEBUG ("Calculated diff = " << diff);

          if (diff > m_gamma && (tcb->m_cWnd < tcb->m_ssThresh))
            {
              /*
               * We are going too fast. We need to slow down and change from
               * slow-start to linear increase/decrease mode by setting cwnd
               * to target cwnd. We add 1 because of the integer truncation.
               */
              NS_LOG_LOGIC ("We are going too fast. We need to slow down and "
                            "change to linear increase/decrease mode.");
              segCwnd = std::min (segCwnd, targetCwnd + 1);
              tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
              tcb->m_ssThresh = GetSsThresh (tcb, 0);
              NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<
                            " ssthresh=" << tcb->m_ssThresh);
            }
          else if (tcb->m_cWnd < tcb->m_ssThresh)
            {     // Slow start mode
              NS_LOG_LOGIC ("We are in slow start and diff < m_gamma, so we "
                            "follow NewReno slow start");
              TcpNewReno::SlowStart (tcb, segmentsAcked);
            }
          else
            {     // Linear increase/decrease mode
              NS_LOG_LOGIC ("We are in linear increase/decrease mode");
              if (diff > m_beta)
                {
                  // We are going too fast, so we slow down
                  NS_LOG_LOGIC ("We are going too fast, so we slow down by decrementing cwnd");
                  segCwnd--;
                  tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
                  tcb->m_ssThresh = GetSsThresh (tcb, 0);
                  NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<
                                " ssthresh=" << tcb->m_ssThresh);
                }
              else if (diff < m_alpha)
                {
                  // We are going too slow (having too little data in the network),
                  // so we speed up.
                  NS_LOG_LOGIC ("We are going too slow, so we speed up by incrementing cwnd");
                  segCwnd++;
                  tcb->m_cWnd = segCwnd * tcb->m_segmentSize;
                  NS_LOG_DEBUG ("Updated cwnd = " << tcb->m_cWnd <<
                                " ssthresh=" << tcb->m_ssThresh);
                }
              else
                {
                  // We are going at the right speed
                  NS_LOG_LOGIC ("We are sending at the right speed");
                }
            }
          tcb->m_ssThresh = std::max (tcb->m_ssThresh, 3 * tcb->m_cWnd / 4);
          NS_LOG_DEBUG ("Updated ssThresh = " << tcb->m_ssThresh);
        }

      // Reset cntRtt & minRtt every RTT
      m_cntRtt = 0;
      m_minRtt = Time::Max ();
    }
  else if (tcb->m_cWnd < tcb->m_ssThresh)
    {
      TcpNewReno::SlowStart (tcb, segmentsAcked);
    }
}

std::string
TcpVegas::GetName () const
{
  return "TcpVegas";
}

uint32_t
TcpVegas::GetSsThresh (Ptr<const TcpSocketState> tcb,
                       uint32_t bytesInFlight)
{
  NS_LOG_FUNCTION (this << tcb << bytesInFlight);
  return std::max (std::min (tcb->m_ssThresh.Get (), tcb->m_cWnd.Get () - tcb->m_segmentSize), 2 * tcb->m_segmentSize);
}

} // namespace ns3

二、详解

1.定义日志和命名空间

#include "tcp-vegas.h" //包含TCP Vegas算法的头文件。
#include "tcp-socket-state.h"  //包含TCP套接字状态的头文件
 
#include "ns3/log.h"  //包含NS-3日志功能的头文件

namespace ns3 {

NS_LOG_COMPONENT_DEFINE ("TcpVegas"); //定义了一个日志组件,用于记录日志信息。
NS_OBJECT_ENSURE_REGISTERED (TcpVegas);

2.注册Typeld类:TcpVegas和GetTypeId方法的实现

TypeId
TcpVegas::GetTypeId (void)
{
  static TypeId tid = TypeId ("ns3::TcpVegas") //设置类的名称为TcpVegas 位于ns3命名空间下
    .SetParent<TcpNewReno> () //设置TcpVegas的父类为TcpNewReno
    .AddConstructor<TcpVegas> () //添加TcpVegas类的构造函数 创建相关对象
    .SetGroupName ("Internet") //将TcpVegas分类到"Internet"组下
     .AddAttribute ("Alpha", "Lower bound of packets in network",
                   UintegerValue (2),
                   MakeUintegerAccessor (&TcpVegas::m_alpha),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("Beta", "Upper bound of packets in network",
                   UintegerValue (4),
                   MakeUintegerAccessor (&TcpVegas::m_beta),
                   MakeUintegerChecker<uint32_t> ())
    .AddAttribute ("Gamma", "Limit on increase",
                   UintegerValue (1),
                   MakeUintegerAccessor (&TcpVegas::m_gamma),
                   MakeUintegerChecker<uint32_t> ())
  ;
  return tid; //返回TcpVegas的TypeId对象
}

AddAttribute方法用于添加类的属性,这些属性可以在NS-3的配置系统中设置和获取。

  •  "Alpha"、"Beta"和"Gamma"是TcpVegas算法的三个参数,它们分别控制算法的行为:
    • "Alpha":网络中数据包的下界,初始值为2。
    • "Beta":网络中数据包的上界,初始值为4。
    • "Gamma":增加的极限,初始值为1。
  • UintegerValue:设置属性的初始值。
  • MakeUintegerAccessor:创建一个访问器,用于访问和修改属性值。
  • MakeUintegerChecker<uint32_t>():创建一个检查器,确保属性值是有效的无符号整数。

该段代码在NS-3中注册TcpVegas类,并设置其属性和行为,使得TcpVegas可以在NS-3的模拟中被创建和配置。

3.构造函数和析构函数

TcpVegas::TcpVegas (void) //默认构造函数
  : TcpNewReno (), //TcpVegas通过调用其父类TcpNewReno的默认构造函数来进行初始化
    m_alpha (2),
    m_beta (4),   
    m_gamma (1), 
    m_baseRtt (Time::Max ()),
    m_minRtt (Time::Max ()),
    m_cntRtt (0),
    m_doingVegasNow (true),
    m_begSndNxt (0)
{
  NS_LOG_FUNCTION (this); //日志记录构造函数的调用,this指向当前对象的指针
}

TcpVegas::TcpVegas (const TcpVegas& sock) //复制构造函数
  : TcpNewReno (sock),
    m_alpha (sock.m_alpha),
    m_beta (sock.m_beta),
    m_gamma (sock.m_gamma),
    m_baseRtt (sock.m_baseRtt),
    m_minRtt (sock.m_minRtt),
    m_cntRtt (sock.m_cntRtt),
    m_doingVegasNow (true),
    m_begSndNxt (0)
{
  NS_LOG_FUNCTION (this);
}

TcpVegas::~TcpVegas (void) //析构函数
{
  NS_LOG_FUNCTION (this);
}

默认构造函数:

  • m_alpha (2)m_beta (4)m_gamma (1):这些行初始化TcpVegas算法的参数alphabetagamma,分别设置为2、4和1。
  • m_baseRtt (Time::Max ())m_minRtt (Time::Max ()):将基础往返时间(baseRtt)和最小往返时间(minRtt)初始化为最大时间值,表示它们尚未被设置。
  • m_cntRtt (0):初始化往返时间计数器(cntRtt)为0。即用于计数自连接建立以来观测到的RTT样本数量。
  • m_doingVegasNow (true):初始化标志doingVegasNowtrue,表示Vegas算法默认是启用的。
  • m_begSndNxt (0):初始化发送下一个序列号(begSndNxt)为0。
  • 日志系统记录构造函数的调用,this指向当前对象的指针。

复制构造函数:用于创建一个与另一个TcpVegas对象sock相同的新对象。

  • : TcpNewReno (sock):表明TcpVegas复制构造函数首先调用其父类TcpNewReno的复制构造函数来复制父类成员。
  • 接下来,复制sock对象中的alphabetagammabaseRttminRttcntRtt成员变量的值到新对象。
  • m_doingVegasNow (true)m_begSndNxt (0):与默认构造函数类似,初始化doingVegasNowtruebegSndNxt为0。
  • const TcpVegas& sock:参数sockTcpVegas类型的对象引用,它指向一个已经存在的对象

4.TcpVegas类中成员函数

(1) Fork函数

Ptr<TcpCongestionOps>
TcpVegas::Fork (void)
{
  return CopyObject<TcpVegas> (this);
}
  • Fork函数用于创建当前TcpVegas对象的一个副本,并返回这个副本的智能指针;
  • Ptr<TcpCongestionOps>是一个智能指针,指向TcpCongestionOps类型的对象。Ptr是NS-3中用于管理对象生命周期的智能指针模板类,而TcpCongestionOps是一个抽象基类,代表TCP拥塞控制操作。
  • CopyObject<TcpVegas> (this):这是NS-3中用于复制对象的模板函数,它创建了当前对象的一个副本,并返回一个指向新对象的智能指针。这里的this指针指向当前的TcpVegas对象。

(2) PktsAcked函数

void
TcpVegas::PktsAcked (Ptr<TcpSocketState> tcb, uint32_t segmentsAcked,
                     const Time& rtt)
{
  NS_LOG_FUNCTION (this << tcb << segmentsAcked << rtt);

  if (rtt.IsZero ())
    {
      return;
    }

  m_minRtt = std::min (m_minRtt, rtt);
  NS_LOG_DEBUG ("Updated m_minRtt = " << m_minRtt);

  m_baseRtt = std::min (m_baseRtt, rtt);
  NS_LOG_DEBUG ("Updated m_baseRtt = " << m_baseRtt);

  // Update RTT counter
  m_cntRtt++;
  NS_LOG_DEBUG ("Updated m_cntRtt = " << m_cntRtt);
}
  • PktsAcked函数在收到ACK时被调用,用于更新最小 RTT(m_minRtt)和基础 RTT(m_baseRtt),并统计 RTT 样本的数量 (m_cntRtt)。
  • 如果 rtt 为零,则直接返回,不进行任何操作。这通常是为了避免处理无效的数据(例如无效的 ACK 或零延迟的情况)。
  • std::min 是 C++ 标准库中的一个函数模板,它返回两个参数中的较小值。
  • m_minRtt 表示当前连接或当前窗口内的最小 RTT。在每次收到 ACK 包时,如果新的 RTT 比当前记录的 m_minRtt 小,就会更新 m_minRtt。
    std::min(m_minRtt, rtt) 会选择 m_minRtt 和当前 RTT 中较小的一个,并将其赋值给 m_minRtt。确保 m_minRtt 始终保持为最小的 RTT 值。
  • m_baseRtt 用于记录连接过程中观察到的最小 RTT(通常是在连接的初期或网络的稳定阶段)。这代表了网络的基准延迟(即理想的延迟)。
  • 与 m_minRtt 类似,m_baseRtt 会更新为当前 RTT 和已有的 m_baseRtt 中的最小值。这可以确保 m_baseRtt 始终为连接期间的最小延迟。
  • m_cntRtt 是 RTT 样本的计数器。每次收到 ACK 包时,都会增加 m_cntRtt 的值,表示新的 RTT 样本被记录。

baseRtt 和 minRtt的区别见:

TCP Vegas拥塞控制算法——baseRtt 和 minRtt的区别-CSDN博客

(3) EnableVegas函数

void
TcpVegas::EnableVegas (Ptr<TcpSocketState> tcb)
{
  NS_LOG_FUNCTION (this << tcb);

  m_doingVegasNow = true;
  m_begSndNxt = tcb->m_nextTxSequence;
  m_cntRtt = 0;
  m_minRtt = Time::Max ();
}

void
TcpVegas::DisableVegas ()
{
  NS_LOG_FUNCTION (this);

  m_doingVegasNow = false;
}
  • EnableVegas函数用于启用Vegas算法。
  • m_doingVegasNow标志被设置为true,表示Vegas算法现在被激活。
  • m_begSndNxt被设置为下一个传输序列号,用于跟踪Vegas周期的开始。
  • m_cntRtt成员变量重置为0,在每个新的Vegas周期开始时重置这个计数器。
  • m_minRtt重置为Time::Max(),即最大可能的时间值;用于在新的Vegas周期中重新寻找最小的RTT值。

(4) DisableVegas函数

void TcpVegas::DisableVegas ()
{
  NS_LOG_FUNCTION (this);

  m_doingVegasNow = false;
}
  • DisableVegas函数用于禁用Vegas算法。
  • m_doingVegasNow标志被设置为false,表示Vegas算法现在被禁用。

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

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

相关文章

论文解读 | EMNLP2024 一种用于大语言模型版本更新的学习率路径切换训练范式

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 点击 阅读原文 观看作者讲解回放&#xff01; 作者简介 王志豪&#xff0c;厦门大学博士生 刘诗雨&#xff0c;厦门大学硕士生 内容简介 新数据的不断涌现使版本更新成为大型语言模型&#xff08;LLMs&#xff…

FFmpeg 的常用API

FFmpeg 的常用API 附录&#xff1a;FFmpeg库介绍 库介绍libavcodec音视频编解码核心库编码 (avcodec_send_frame, avcodec_receive_packet)。解码 (avcodec_send_packet, avcodec_receive_frame)。libavformat提供了音视频流的解析和封装功能&#xff0c;多种多媒体封装格式&…

trap命令

信号 linux信号是由一个整数构成的异步消息&#xff0c;可以由某个进程发给其他的进程&#xff0c;也可以在用户按下特定键发生某种异常事件时&#xff0c;由系统发给某个进程 信号列表 kill -l trap -l 在使用信号名时&#xff0c;需要省略SIG前缀 trap trap命令用于指定…

Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码 【AI辅助开发系列】

&#x1f380;&#x1f380;&#x1f380;【AI辅助编程系列】&#x1f380;&#x1f380;&#x1f380; Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码Visual Studio 安装和管理 GitHub CopilotVisual Studio 使用 GitHub Copilot 扩展Visual Studio 使用 GitHu…

Llama 3 模型系列解析(一)

目录 1. 引言 1.1 Llama 3 的简介 1.2 性能评估 1.3 开源计划 1.4 多模态扩展 ps 1. 缩放法则 2. 超额训练&#xff08;Over-training&#xff09; 3. 计算训练预算 4. 如何逐步估算和确定最优模型&#xff1f; 2. 概述 2.1 Llama 3 语言模型开发两个主要阶段 2.2…

【多时段】含sop的配电网重构【含分布式电源】【已更新视频讲解】

1 主要内容 之前分享了很多配电网重构的程序&#xff0c;每个程序针对场景限定性比较大&#xff0c;程序初学者修改起来难度较大&#xff0c;本次分享一个基础程序&#xff0c;针对含sop的配电网重构模型&#xff0c;含风电和光伏&#xff0c;优化了33节点网络电压合理性&…

使用 Elastic AI Assistant 简化威胁情报报告

作者&#xff1a;来自 Tommy Bumford 了解 SRE 不断扩展的角色以及所需的新技能&#xff1a;成本管理和 AI。 通过 AI 驱动的报告为分析师提供支持 在不断发展的网络安全领域&#xff0c;威胁分析师不断被新的威胁情报 (threat intelligence - TI) 数据淹没。挑战不仅在于理解…

64.基于SpringBoot + Vue实现的前后端分离-新闻资讯系统(项目 + 论文)

项目介绍 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;文章信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足广…

word无法创建工作文件,检查临时环境变量。

word无法创建工作文件&#xff0c;检查临时环境变量。 word preview版本&#xff0c;关联打开文件出现报错。word无法创建工作文件&#xff0c;检查临时环境变量。 打开注册表&#xff0c;删除键 Word Preview: HKCR\CLSID{84F66100-FF7C-4fb4-B0C0-02CD7FB668FE} PowerPoint …

人工智能ACA(七)——计算机视觉基础

一、自然语言处理基本介绍 1. 自然语言处理的定义 1-1 自然语言 人类使用的在社会生活中自然形成的语言 1-2 自然语言处理 目标是让计算机能够理解、解析、生成和处理人类的自然语言 包含自然语言理解和自然语言生成两部分组成 2. 自然语言处理的发展趋势 3.自然语言处理…

(带源码)宠物主题商场系统 计算机项目 P10083

项目说明 本号所发布的项目均由我部署运行验证&#xff0c;可保证项目系统正常运行&#xff0c;以及提供完整源码。 如需要远程部署/定制/讲解系统&#xff0c;可以联系我。定制项目未经同意不会上传&#xff01; 项目源码获取方式放在文章末尾处 注&#xff1a;项目仅供学…

编程考古-传奇的开始Delphi(中)

发布会 这是 Delphi 发布的邀请&#xff1a; 许多曾经风靡一时的开发工具已逐渐淡出人们的视野&#xff0c;被历史的洪流所淹没。然而&#xff0c;Delphi不仅没有被遗忘&#xff0c;反而持续保持着其独特的魅力和广泛的用户基础。这不仅彰显了Delphi在快速变化的技术领域中的持…

山景BP1048增加AT指令,实现单片机串口控制播放音乐(一)

1、设计目的 山景提供的SDK是蓝牙音箱demo&#xff0c;用户使用ADC按键或者IR遥控器&#xff0c;进行人机交互。然而现实很多场景&#xff0c;需要和单片机通信&#xff0c;不管是ADC按键或者IR接口都不适合和单片机通信。这里设计个AT指令用来和BP1048通信。AT指令如下图所示…

IntelliJ IDEA Docker集成

一、概述 Docker是一种用于在隔离和可复制环境中部署和运行可执行文件的工具。这可能很有用&#xff0c;例如&#xff0c;在与生产相同的环境中测试代码。 IntelliJ IDEA集成了Docker功能&#xff0c;并为创建Docker映像、运行Docker容器、管理Docker Compose应用程序、使用公…

43. Three.js案例-绘制100个立方体

43. Three.js案例-绘制100个立方体 实现效果 知识点 WebGLRenderer&#xff08;WebGL渲染器&#xff09; WebGLRenderer是Three.js中最常用的渲染器之一&#xff0c;用于将3D场景渲染到网页上。 构造器 WebGLRenderer(parameters : Object) 参数类型描述parametersObject…

Linux------进程处理(system库函数)

视频&#xff1a; 【尚硅谷嵌入式Linux应用层开发&#xff0c;linux网络编程&#xff0c;linux进程线程&#xff0c;linux文件io】https://www.bilibili.com/video/BV1DJ4m1M77z?p34&vd_source342079de7c07f82982956aad8662b467 #include <stdlib.h> #include <…

自然语言处理与知识图谱的融合与应用

目录 前言1. 知识图谱与自然语言处理的关系1.1 知识图谱的定义与特点1.2 自然语言处理的核心任务1.3 二者的互补性 2. NLP在知识图谱构建中的应用2.1 信息抽取2.1.1 实体识别2.1.2 关系抽取2.1.3 属性抽取 2.2 知识融合2.3 知识推理 3. NLP与知识图谱融合的实际应用3.1 智能问答…

【数据库初阶】数据库基础知识

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; 数据库初阶 &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们&#xff0c;大家好&#xff01;在这篇文章中&#xff0c;我们将深入浅出地为大家讲解 数据库…

【LeetCode】726、原子的数量

【LeetCode】726、原子的数量 文章目录 一、递归: 嵌套类问题1.1 递归: 嵌套类问题 二、多语言解法 一、递归: 嵌套类问题 1.1 递归: 嵌套类问题 遇到 ( 括号, 则递归计算子问题 遇到大写字母, 或遇到 ( 括号, 则清算历史, 并开始新的记录 记录由两部分组成: 大写字母开头的 …

财经英语期末考试复习

文章目录 第一篇第二篇第三篇第四篇思路梳理作文撰写 第一篇 李宁是中国运动服装和鞋类行业的领导者,这源于其创始人,同名体操冠军李宁的愿景. Ling-Ning is the Chinese leader in athletic apparel and footwear, rooted in the vision of its founder and namesake,the cha…