使用深度搜索分析心理調查問卷的研究

使用深度搜索分析心理調查問卷的研究

背景

昨天我女朋友發了一個心理調查問卷要我做。我向來對這種形似心理調查問卷嗤之以鼻: 一個人的性格怎麼可能由幾個簡單的問題決定。但作爲技術人員,我決定用技術的手段分析這份調查問卷,向女朋友證明其缺乏科學性。

調查問卷的原版如下圖
這裏寫圖片描述

有興趣的朋友可以玩玩~

我想了解如下幾個問題:
1. 問卷是不是有環路?如果有環路,則可證明這份問卷不正規。
2. A 答案是不是不可能達到?因爲4個答案中,只有A答案沒有同的傾向。
3. 如果 A 答案能到達,那麼有多少種可能?佔比是多少?

分析

這種問卷調查有特點:每一個題目都對應多個選項;每一個選項,都對應一個題目或者答案。從一個人答題的路徑來看,其實這就是一個典型的圖結構。

結合我想了解的問題,有如下幾個方面需要考慮:
1. 證明圖沒有環路
2. 使用DFS證明A是可以達到的
3. 統計所有的可能的結果,算出A的佔比

建模

我打算使用 列表模式 構建圖

  @list = [
    [1],
    [2,3],
    [3,4],
    [4,5,6],
    [5,6,7],
    [6,7],
    [7,8,9],
    [8,9],
    [9,10,11],
    [10,11,12],
    [12,13],
    [13,14],
    [13,15],
    [15,18,14],
    [15,18],
    [16,18],
    [17,18,19,20],
    [20,21,'B'],
    [19,'C'],
    [22,'A'],
    [21, 'D'],
    [22, 'B'],
    ['A', 'C', 'D']
  ]

圖的節點有 0 到 22, 再加上 A, B, C, D。
1. 因爲我不想處理下標,所以圖的起始位置,我設置成0;
2. 圖的節點,我簡單的用數組的下標表示;
3. 答案直接輸出,不需要放在節點的集合中;

DFS

圖有沒有環路

代碼如下:

def has_cycle?
  recursion_stack = [false] * 23

  check_cycle(0, recursion_stack)
end

def check_cycle(vertex, recursion_stack)
  recursion_stack[vertex] = true

  @list[vertex].each do |node|
    next if over?(node)

    return true if recursion_stack[node]
    check_cycle(node, recursion_stack)
  end

  recursion_stack[vertex] = false

  return false
end

其中 over?方法是用來判斷遞歸是否結束。

def over?(point)
  ['A', 'B', 'C', 'D'].include?(point.to_s)
end
  1. has_cycle 來判斷是否有迴路,我將一次完全迭代的節點是否訪問到了的信息保存在recursion_stack
  2. 它調用 深度搜索 算法實現的 check_cycle

運行得出的結果是 false

A 可以到達嗎?A如果可以到達,那麼A的可能性有多大?

@result = []

def dfs(node)
  @list[node].each do |vertex|
    if over?(vertex)
      @result << vertex
      next
    end

    dfs(vertex)
  end
end

使用深度有限搜索, 將最後的結果保存在 @result中,將結果打印出來。

def count_charactor(result, charactor)
  result.count { |item| item == charactor }
end

dfs(0)

puts "一共有 %d 可能的答案" % @result.size
('A'..'D').to_a.each do |charactor|
  puts "#{charactor}: %d 種可能, 佔比爲 %f" % [ count_charactor(@result, charactor), count_charactor(@result, charactor).to_f / @result.length]
end

結果如下:

一共有 27860 可能的答案
A: 8960 種可能, 佔比爲 0.321608
B: 3360 種可能, 佔比爲 0.120603
C: 8120 種可能, 佔比爲 0.291457
D: 7420 種可能, 佔比爲 0.266332

輸出能到答案A的100路徑

@i = 0

def dfs(node, stack)
  stack.push node

  @list[node].each do |vertex|
    if over?(vertex)
      @result << vertex

      if vertex == 'A'
        @i += 1
        puts "到A的路徑有:"
        puts stack.join(" -> ")
      end

      break if @i == 100

      next
    end

    dfs(vertex, stack)
  end

  stack.pop
end

用一個棧stack來保存路徑, 到A點將所有的結果輸出

總結

圖的算法應用真的很廣泛,值得深入研究。有時候將實時中的問題抽象成圖的問題,能讓我們從另外的一個角度看問題。再則,用ruby實現圖的算法也是很簡單的。dfsbfs簡單,但收到程序棧的限制。但比較適合本程序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章