7. 数学建模案例分析

功能简介:提供常见数学建模案例,如人口增长模型、传染病模型、经济增长模型等,通过参数调整观察模型变化,计算模型预测值。帮助学生理解数学建模的基本步骤和应用价值。
在这里插入图片描述
ArkTS代码

@Entry
@Component
struct MathematicalModeling {
  @State private model: string = 'population'
  @State private parameters: number[] = [100, 0.1, 0.001]
  @State private predictions: string = ''
  @State private modelResults: number[] = []
  private settings: RenderingContextSettings = new RenderingContextSettings(true)
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)

  build() {
    Column() {
      Text('🔍 数学建模案例分析')
        .fontSize(24).fontWeight(FontWeight.Bold)
        .margin({ bottom: 20 })

      Text('模型类型')
        .fontSize(18).fontWeight(FontWeight.Bold)
        .margin({ bottom: 10 })

      Row() {
        Button('人口增长')
          .width(100)
          .onClick(() => { this.model = 'population'; this.updateModel() })
        Button('传染病')
          .width(100)
          .onClick(() => { this.model = 'epidemic'; this.updateModel() })
        Button('经济增长')
          .width(100)
          .onClick(() => { this.model = 'economic'; this.updateModel() })
      }
      .margin({ bottom: 20 })

      Text('模型参数')
        .fontSize(18).fontWeight(FontWeight.Bold)
        .margin({ bottom: 10 })

      ForEach([0, 1, 2], (index: number) => {
        Row() {
          Text(this.getParameterLabel(index))
            .width(80)
          Slider({
            value: this.parameters[index], 
            min: this.getParamMin(index), 
            max: this.getParamMax(index), 
            step: this.getParamStep(index)
          })
            .width(200)
            .onChange((val: number) => {
              this.parameters[index] = val
              this.updateModel()
            })
          Text(this.parameters[index].toFixed(this.getParamDecimals(index)))
            .width(60)
        }
        .margin({ bottom: 10 })
      })

      Button('运行模型')
        .width(100)
        .margin({ top: 10, bottom: 20 })
        .onClick(() => this.runModel())

      Canvas(this.context)
        .width(400).height(300)
        .backgroundColor('#f5f5f5')
        .onReady(() => this.drawModel())

      Text('模型预测')
        .fontSize(18).fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 10 })

      Text(this.predictions)
        .fontSize(14).fontColor('#666')

      Text('模型说明')
        .fontSize(18).fontWeight(FontWeight.Bold)
        .margin({ top: 20, bottom: 10 })

      Text(this.getModelDescription())
        .fontSize(14).fontColor('#666')
    }
    .padding(20)
  }

  private getParameterLabel(index: number): string {
    switch (this.model) {
      case 'population': return ['初始人口: ', '增长率: ', '死亡率: '][index]
      case 'epidemic': return ['初始感染: ', '传播率: ', '恢复率: '][index]
      case 'economic': return ['初始GDP: ', '增长率: ', '投资率: '][index]
      default: return ''
    }
  }

  private getParamMin(index: number): number {
    switch (this.model) {
      case 'population':
        return [1, 0.01, 0.001][index]
      case 'epidemic':
        return [1, 0.01, 0.01][index]
      case 'economic':
        return [1, 0.01, 0.01][index]
      default:
        return 0.01
    }
  }

  private getParamMax(index: number): number {
    switch (this.model) {
      case 'population':
        return [1000, 0.5, 0.1][index]
      case 'epidemic':
        return [100, 1, 0.5][index]
      case 'economic':
        return [1000, 0.3, 0.5][index]
      default:
        return 1
    }
  }

  private getParamStep(index: number): number {
    switch (this.model) {
      case 'population':
        return [1, 0.01, 0.001][index]
      case 'epidemic':
        return [1, 0.01, 0.01][index]
      case 'economic':
        return [10, 0.01, 0.01][index]
      default:
        return 0.01
    }
  }

  private getParamDecimals(index: number): number {
    switch (this.model) {
      case 'population':
        return [0, 2, 3][index]
      case 'epidemic':
        return [0, 2, 2][index]
      case 'economic':
        return [0, 2, 2][index]
      default:
        return 2
    }
  }

  private updateModel() {
    // 根据模型类型调整参数范围
    switch (this.model) {
      case 'population':
        this.parameters[0] = Math.max(1, Math.min(1000, this.parameters[0]))
        this.parameters[1] = Math.max(0.01, Math.min(0.5, this.parameters[1]))
        this.parameters[2] = Math.max(0.001, Math.min(0.1, this.parameters[2]))
        break
      case 'epidemic':
        this.parameters[0] = Math.max(1, Math.min(100, this.parameters[0]))
        this.parameters[1] = Math.max(0.01, Math.min(1, this.parameters[1]))
        this.parameters[2] = Math.max(0.01, Math.min(0.5, this.parameters[2]))
        break
      case 'economic':
        this.parameters[0] = Math.max(1, Math.min(1000, this.parameters[0]))
        this.parameters[1] = Math.max(0.01, Math.min(0.3, this.parameters[1]))
        this.parameters[2] = Math.max(0.01, Math.min(0.5, this.parameters[2]))
        break
    }
  }

  private runModel() {
    this.modelResults = []
    let predictions = ''
    
    switch (this.model) {
      case 'population':
        this.modelResults = this.runPopulationModel()
        predictions = `人口增长模型预测:\n`
        predictions += `初始人口: ${this.parameters[0].toFixed(0)}\n`
        predictions += `增长率: ${this.parameters[1].toFixed(2)}\n`
        predictions += `死亡率: ${this.parameters[2].toFixed(3)}\n`
        predictions += `10年后人口: ${this.modelResults[9].toFixed(0)}\n`
        predictions += `20年后人口: ${this.modelResults[19].toFixed(0)}\n`
        break
      case 'epidemic':
        this.modelResults = this.runEpidemicModel()
        predictions = `传染病模型预测:\n`
        predictions += `初始感染人数: ${this.parameters[0].toFixed(0)}\n`
        predictions += `传播率: ${this.parameters[1].toFixed(2)}\n`
        predictions += `恢复率: ${this.parameters[2].toFixed(2)}\n`
        predictions += `第10天感染人数: ${this.modelResults[9].toFixed(0)}\n`
        predictions += `第20天感染人数: ${this.modelResults[19].toFixed(0)}\n`
        break
      case 'economic':
        this.modelResults = this.runEconomicModel()
        predictions = `经济增长模型预测:\n`
        predictions += `初始GDP: ${this.parameters[0].toFixed(0)}\n`
        predictions += `增长率: ${this.parameters[1].toFixed(2)}\n`
        predictions += `投资率: ${this.parameters[2].toFixed(2)}\n`
        predictions += `10年后GDP: ${this.modelResults[9].toFixed(2)}\n`
        predictions += `20年后GDP: ${this.modelResults[19].toFixed(2)}\n`
        break
    }
    
    this.predictions = predictions
    this.drawModel()
  }

  private runPopulationModel(): number[] {
    const initial = this.parameters[0]
    const growth = this.parameters[1]
    const death = this.parameters[2]
    const results: number[] = []
    let population = initial
    
    for (let t = 0; t < 20; t++) {
      results.push(population)
      population = population * (1 + growth - death)
    }
    
    return results
  }

  private runEpidemicModel(): number[] {
    const initial = this.parameters[0]
    const beta = this.parameters[1]
    const gamma = this.parameters[2]
    const results: number[] = []
    let infected = initial
    const totalPopulation = 1000 // 假设总人口为1000
    
    for (let t = 0; t < 20; t++) {
      results.push(infected)
      const newInfections = beta * infected * (totalPopulation - infected) / totalPopulation
      const recoveries = gamma * infected
      infected = Math.max(0, infected + newInfections - recoveries)
    }
    
    return results
  }

  private runEconomicModel(): number[] {
    const initial = this.parameters[0]
    const growth = this.parameters[1]
    const investment = this.parameters[2]
    const results: number[] = []
    let gdp = initial
    
    for (let t = 0; t < 20; t++) {
      results.push(gdp)
      gdp = gdp * (1 + growth + investment * 0.5)
    }
    
    return results
  }

  private drawModel() {
    const ctx = this.context
    const width = 400
    const height = 300
    const padding = 50
    
    // 清空画布
    ctx.clearRect(0, 0, width, height)
    
    // 绘制坐标轴
    ctx.beginPath()
    ctx.moveTo(padding, height - padding)
    ctx.lineTo(width - padding, height - padding)
    ctx.moveTo(padding, padding)
    ctx.lineTo(padding, height - padding)
    ctx.strokeStyle = '#000'
    ctx.lineWidth = 1
    ctx.stroke()
    
    // 绘制模型预测曲线
    if (this.modelResults.length > 0) {
      // 计算最大值用于缩放
      let maxValue = 0
      for (let i = 0; i < this.modelResults.length; i++) {
        if (this.modelResults[i] > maxValue) {
          maxValue = this.modelResults[i]
        }
      }
      maxValue = maxValue || 1
      
      // 绘制曲线
      ctx.beginPath()
      ctx.strokeStyle = '#2196F3'
      ctx.lineWidth = 2
      
      for (let t = 0; t < this.modelResults.length; t++) {
        const x = padding + (t / (this.modelResults.length - 1)) * (width - 2 * padding)
        const y = height - padding - (this.modelResults[t] / maxValue) * (height - 2 * padding)
        
        if (t === 0) {
          ctx.moveTo(x, y)
        } else {
          ctx.lineTo(x, y)
        }
      }
      ctx.stroke()
      
      // 绘制数据点
      for (let t = 0; t < this.modelResults.length; t++) {
        const x = padding + (t / (this.modelResults.length - 1)) * (width - 2 * padding)
        const y = height - padding - (this.modelResults[t] / maxValue) * (height - 2 * padding)
        
        ctx.beginPath()
        ctx.arc(x, y, 3, 0, 2 * Math.PI)
        ctx.fillStyle = '#2196F3'
        ctx.fill()
        ctx.strokeStyle = '#000'
        ctx.stroke()
      }
      
      // 绘制标签
      ctx.font = '12px Arial'
      ctx.fillStyle = '#000'
      ctx.fillText('时间', width / 2 - 10, height - padding + 20)
      ctx.save()
      ctx.translate(padding - 20, height / 2)
      ctx.rotate(-Math.PI / 2)
      ctx.fillText(this.getVerticalAxisLabel(), 0, 0)
      ctx.restore()
      
      // 绘制刻度
      for (let i = 0; i <= 4; i++) {
        const x = padding + (i / 4) * (width - 2 * padding)
        ctx.beginPath()
        ctx.moveTo(x, height - padding - 5)
        ctx.lineTo(x, height - padding + 5)
        ctx.stroke()
        ctx.fillText((i * 5).toString(), x - 5, height - padding + 15)
      }
      
      for (let i = 0; i <= 4; i++) {
        const y = height - padding - (i / 4) * (height - 2 * padding)
        ctx.beginPath()
        ctx.moveTo(padding - 5, y)
        ctx.lineTo(padding + 5, y)
        ctx.stroke()
        ctx.fillText(((i / 4) * maxValue).toFixed(0), padding - 40, y + 4)
      }
    }
  }

  private getVerticalAxisLabel(): string {
    switch (this.model) {
      case 'population': return '人口数量'
      case 'epidemic': return '感染人数'
      case 'economic': return 'GDP'
      default: return '值'
    }
  }

  private getModelDescription(): string {
    switch (this.model) {
      case 'population':
        return '人口增长模型:基于指数增长模型,考虑出生率和死亡率的影响。适用于预测人口变化趋势,帮助制定人口政策。'
      case 'epidemic':
        return '传染病模型:基于SIR模型的简化版本,考虑感染率和恢复率的影响。适用于预测传染病的传播趋势,制定防控策略。'
      case 'economic':
        return '经济增长模型:考虑经济增长率和投资率的影响。适用于预测经济发展趋势,制定经济政策。'
      default:
        return ''
    }
  }
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐