การบรรจบกันของกระบวนการมาร์คอฟ


10

ท้าทาย

ให้เมทริกซ์ซ้ายหรือขวาสุ่มซึ่งขีด จำกัด เมื่อ x เข้าใกล้อนันต์ของเมทริกซ์กับกำลังของ x เข้าใกล้เมทริกซ์ด้วยค่า จำกัด ทั้งหมดคืนเมทริกซ์ที่เมทริกซ์ลู่เข้าหากัน โดยพื้นฐานแล้วคุณต้องการคูณเมทริกซ์ด้วยตัวเองจนกว่าผลลัพธ์จะไม่เปลี่ยนแปลงอีกต่อไป

กรณีทดสอบ

[[7/10, 4/10], [3/10, 6/10]] -> [[4/7, 4/7], [3/7, 3/7]]
[[2/5, 4/5], [3/5, 1/5]] -> [[4/7, 4/7], [3/7, 3/7]]
[[1/2, 1/2], [1/2, 1/2]] -> [[1/2, 1/2], [1/2, 1/2]]
[[1/3, 2/3], [2/3, 1/3]] -> [[1/2, 1/2], [1/2, 1/2]]
[[1/10, 2/10, 3/10], [4/10, 5/10, 6/10], [5/10, 3/10, 1/10]] -> [[27/130, 27/130, 27/130], [66/130, 66/130, 66/130], [37/130, 37/130, 37/130]]
[[1/7, 2/7, 4/7], [2/7, 4/7, 1/7], [4/7, 1/7, 2/7]] -> [[1/3, 1/3, 1/3], [1/3, 1/3, 1/3], [1/3, 1/3, 1/3]]

กฎระเบียบ

  • ช่องโหว่มาตรฐานใช้
  • คุณอาจเลือกว่าคุณต้องการเมทริกซ์ขวาหรือซ้ายสุ่ม
  • คุณสามารถใช้ประเภทตัวเลขที่สมเหตุสมผลเช่นลอย, ปันส่วน, ทศนิยมที่ไม่มีที่สิ้นสุดอย่างแม่นยำ ฯลฯ
  • นี่คือดังนั้นการส่งที่สั้นที่สุดในหน่วยไบต์สำหรับแต่ละภาษาจะถูกประกาศให้เป็นผู้ชนะสำหรับภาษานั้น ๆ จะไม่ยอมรับคำตอบ

@FryAmTheEggman ดูเหมือนว่าความคิดเห็นก่อนหน้านี้ถูกลบไปแล้วดังนั้นนี่อาจซ้ำซ้อน แต่เมทริกซ์ที่ลดได้และคาบจะถูกแยกออกโดย "รับเมทริกซ์ซ้ายหรือขวาสุ่มซึ่งขีด จำกัด เมื่อ x เข้าใกล้อินฟินิตี้ของเมทริกซ์กับกำลัง ของ x เข้าใกล้เมทริกซ์ที่มีค่า จำกัด ทั้งหมด "ซึ่งฉันอ่านเป็นการบอกว่าอินพุตรับประกันว่าจะมาบรรจบกับโซลูชันที่ไม่เหมือนใคร (เช่นเมทริกซ์อินพุทรับประกันได้ว่าเป็นอัตลักษณ์)
นาธาเนียล

@ นาธาเนียลมันไม่เป็นความจริงเหมือนกับว่าโซ่สามารถลดได้คุณสามารถมีผลลัพธ์ (เช่นเมทริกซ์เอกลักษณ์) ที่ตรงกับสิ่งที่คุณพูด แต่เชนที่อธิบายนั้นไม่สามารถลดได้ดังนั้นข้อมูลจะไม่ถูกรับประกัน เป็นอัตลักษณ์ (เพราะจะไม่เกิดขึ้นอีกในเชิงบวก) การรับประกันความถูกต้องตามหลักสรีรศาสตร์คือสิ่งที่ OP ต้องการและฉันคิดว่าพวกเขามีตอนนี้ด้วยข้อ จำกัด เพิ่มเติมของค่าแถวทั้งหมดที่เหมือนกัน หากคุณรู้วิธีที่ดีกว่าในการ จำกัด การป้อนข้อมูลโดยไม่จำเป็นต้องเพิ่มคำอธิบายของโซ่มาร์คอฟฉันแน่ใจว่า HyperNeutrino จะขอบคุณมัน! :)
FryAmTheEggman

1
@FryAmTheEggman อ่าใช่แล้วขอโทษด้วย ฉันกำลังคิดถึงการทำซ้ำพลังแทนที่จะเพิ่มเมทริกซ์เป็นพลังงาน (ดังนั้นโดย "โซลูชันที่ไม่ซ้ำกัน" ฉันหมายถึง "อันที่เป็นอิสระจากจุดเริ่มต้นของกระบวนการทำซ้ำ" แต่นั่นไม่เกี่ยวข้องที่นี่) ฉันยอมรับว่าเงื่อนไข 'ทุกแถวเหมือนกัน' ทำงานได้ ฉันคิดว่า OP อาจจะพูดว่า "ห่วงโซ่มาร์คอฟรับประกันได้ว่าเป็นอัตลักษณ์" ซึ่งจะทำให้คนที่ชอบเราที่น่าจะเป็นห่วง!
นาธาเนียล

ที่จริงถ้าBเป็นวิธีการแก้BA = Bแล้วเพื่อให้เป็นCBสำหรับค่าคงที่ใด ๆ เกลาค ดังนั้นวิธีแก้ปัญหาที่ไม่เป็นศูนย์จะไม่ซ้ำกันอย่างเด็ดขาดเว้นแต่คุณจะแก้ไขสเกล (ต้องการให้Bเป็นค่าสโทแคสติกจะทำ) นอกจากนี้แน่นอนว่าแถวหรือคอลัมน์ของBที่เท่ากันจะขึ้นอยู่กับว่าAเป็นซ้ายหรือขวาสุ่ม
Ilmari Karonen

2
สำหรับคนอื่น ๆ ที่ไม่เคยเรียนรู้เกี่ยวกับการฝึกอบรมในช่วงคณิตศาสตร์ชั้นในโรงเรียนมัธยมและวิธีการคูณพวกเขา: mathsisfun.com/algebra/matrix-multiplying.html ฉันต้องค้นหามันเพื่อทำความเข้าใจกับสิ่งที่ถูกถาม .. บางทีมันอาจเป็นความรู้ทั่วไปที่อื่นในโลก .. : S
Kevin Cruijssen

คำตอบ:


7

R ,  44  43 ไบต์

function(m){X=m
while(any(X-(X=X%*%m)))0
X}

ลองออนไลน์!

แค่คูณมันเรื่อย ๆ จนกระทั่งพบเมทริกซ์คงที่ เห็นได้ชัดว่าX!=(X=X%*%m)ไม่เปรียบเทียบแล้ว reassigns Xเพื่อให้เป็นที่เรียบร้อย

ขอบคุณ @Vlo สำหรับการกำจัดไบต์ แม้ว่าขีดฆ่า 44 ยังคงเป็นปกติ 44


1
ฉันสงสัยว่าทำไมfunction(m){ while(any(m!=(m=m%*%m)))0 m}ไม่ทำงาน ความไม่ถูกต้องเชิงตัวเลขที่ป้องกันไม่ให้เกิดเงื่อนไขการเลิกจ้างเรียก?
CodesInChaos

@CodesInChaos เป็นไปได้มากว่ามันขาดความแม่นยำ การสลับไปใช้ไลบรารีที่มีความแม่นยำตามอำเภอใจไม่ได้ช่วยอะไรเช่นกันพวกเขาหมดเวลา (Rmpfr) หรือล้มเหลว (gmp) ในลักษณะเดียวกันแม้ว่าฉันอาจทำอะไรผิด
จูเซปเป้

@iuseppe ฉันเดาว่าแนวทางที่แนะนำนั้นกำลังทำซ้ำกำลังสองจนกว่าจะไม่มีการเปลี่ยนแปลงอีกต่อไป (ฉันอ่าน R ไม่ได้)
user202729

@ user202729 ใช่มันเป็น R ใช้ตัวเลขทศนิยม 64 บิตและฉันรู้ว่ามีข้อผิดพลาดเกิดขึ้นอย่างรวดเร็ว
จูเซปเป้

ฉันคิดว่าอัลกอริทึมไม่เสถียร เยลลี่ก็มีปัญหาเหมือนกัน (สิ่งที่ต้องทำพิสูจน์ได้และหาทางเลือกอื่น)
user202729

5

ระดับแปดเสียง45 42 35 ไบต์

@(A)([v,~]=eigs(A,1))/sum(v)*any(A)

ลองออนไลน์!

บันทึกแล้ว 3 ไบต์ขอบคุณ Giuseppe และขอขอบคุณ Luis Mendo อีก 7 คน!

สิ่งนี้ใช้ว่า eigenvector สอดคล้องกับ eigenvalue 1 (เช่น eigenvalue สูงสุด) เป็นเวกเตอร์คอลัมน์ที่ทำซ้ำสำหรับแต่ละค่าของเมทริกซ์ที่ จำกัด เราต้องทำให้เวกเตอร์เป็นปกติให้มีผลรวม 1 เพื่อให้สุ่ม, จากนั้นเราก็ทำซ้ำเพื่อกรอกเมทริกซ์ ฉันไม่เชี่ยวชาญในการเล่นกอล์ฟอ็อกเทฟมากเกินไป แต่ฉันไม่สามารถหาวิธีที่ใช้ในการคูณซ้ำได้และโปรแกรมเต็มดูเหมือนว่ามันจะนานกว่านี้

เราสามารถใช้any(A)ตั้งแต่ข้อ จำกัด ที่เรารู้ว่าเมทริกซ์จะต้องอธิบายห่วงโซ่มาร์คอฟที่ลดไม่ได้และแต่ละรัฐจะต้องสามารถเข้าถึงได้จากรัฐอื่น ๆ ดังนั้นอย่างน้อยหนึ่งค่าในแต่ละคอลัมน์จะต้องไม่ใช่ศูนย์


วิธีการที่ไม่eigsเสมอกลับวิคเตอร์ที่สอดคล้องกับ1? ความทรงจำเกี่ยวกับโซ่มาร์คอฟของฉันค่อนข้างคลุมเครือ
จูเซปเป้


@Giuseppe เนื่องจากเมทริกซ์นั้นสุ่มและอีกสองอย่างค่าลักษณะเฉพาะสูงสุดคือ 1 และeigsส่งกลับเริ่มต้นจากค่าลักษณะเฉพาะที่ใหญ่ที่สุด ขอบคุณสำหรับสนามกอล์ฟ!
FryAmTheEggman

อ่าใช่มั้ย โซ่มาร์คอฟอยู่ในการสอบครั้งต่อไปของฉัน แต่เนื่องจากมันมีไว้สำหรับนักคณิตศาสตร์ศาสตร์รายละเอียดบางอย่างจึงขาดหายไป
จูเซปเป้



3

APL (Dyalog) , 18 6 ไบต์

บันทึก 12 ไบต์ด้วย @ H.PWiz

+.×⍨⍣≡

ลองออนไลน์!


+.×⍨⍣≡6 ไบต์ นั่นคือสี่เหลี่ยมจนกระทั่งไม่มีอะไรเปลี่ยนแปลง
H.PWiz

@ H.PWiz ฉันเชื่อว่ามันเป็น ฉันไม่รู้ว่าทำไมฉันไม่ทำมันตั้งแต่แรก ขอบคุณ!
Uriel

3

k / q, 10 ไบต์

k / q เนื่องจากโปรแกรมเหมือนกันทั้งสองภาษา รหัสเป็นจริงเพียงสำนวน k / q

{$[x]/[x]}

คำอธิบาย

{..}อยู่นอกไวยากรณ์แลมบ์ดาพร้อมกับxพารามิเตอร์ implicit

$[x] มี $ เป็นตัวดำเนินการคูณเมทริกซ์ไบนารีโดยมีเพียงพารามิเตอร์เดียวเท่านั้นที่สร้างโอเปอเรเตอร์ยูนารีที่เหลืออยู่คูณด้วยมาร์คอฟเมตริกซ์

/[x] ใช้การคูณทางซ้ายจนกระทั่งการบรรจบกันเริ่มต้นด้วย x เอง


3

C (gcc) , 207 192 190 181 176 ไบต์ + 2 ตั้งค่าสถานะไบต์-lm

  • ที่บันทึกไว้ สิบห้า สิบเจ็ดยี่สิบ-ไบต์ที่สองต้องขอบคุณceilingcat
  • บันทึกเก้าไบต์ ลบreturn A;ลบ
float*f(A,l,k,j)float*A;{for(float B[l*l],S,M=0,m=1;fabs(m-M)>1e-7;wmemcpy(A,B,l*l))for(M=m,m=0,k=l*l;k--;)for(S=j=0;j<l;)m=fmax(m,fdim(A[k],B[k]=S+=A[k/l*l+j]*A[k%l+j++*l]));}

ลองออนไลน์!


@ceilingcat การนับจำนวนแฟล็กคอมไพเลอร์จะให้ผลลัพธ์เป็น 192 อีกครั้ง รวมถึงข้อเสนอแนะของคุณอย่างไรก็ตาม
Jonathan Frech

@ceilingcat ขอบคุณ
Jonathan Frech

2

Python 3 , 75 61 ไบต์

f=lambda n:n if allclose(n@n,n)else f(n@n)
from numpy import*

ลองออนไลน์!

ในกรณีทดสอบมีความคลาดเคลื่อนลอยตัวดังนั้นค่าอาจแตกต่างกันเล็กน้อยจากเศษส่วนที่แน่นอน

PS numpy.allclose()ใช้เพราะnumpy.array_equal()มีความยาวมากกว่าและมีแนวโน้มที่จะลอยคลาดเคลื่อน

-14 bytes ขอบคุณ HyperNeutrino;) โอ้ใช่ฉันลืม @ operator; P


ใช้dotแทนmatmul: D
HyperNeutrino

ที่จริงใช้อาร์เรย์ numpy เป็นอินพุตและทำx=n@n: P tio.run/…
HyperNeutrino


เพิ่มกลับไปf=ที่ด้านหน้าเพราะมันถูกเรียกซ้ำ ๆ )
Shieru Asakoto

โอ้ใช่คุณพูดถูก :) โทรดี!
HyperNeutrino

2

Java 8, 356 339 ไบต์

import java.math.*;m->{BigDecimal t[][],q;RoundingMode x=null;for(int l=m.length,f=1,i,k;f>0;m=t.clone()){for(t=new BigDecimal[l][l],i=l*l;i-->0;)for(f=k=0;k<l;t[i/l][i%l]=(q!=null?q:q.ZERO).add(m[i/l][k].multiply(m[k++][i%l])))q=t[i/l][i%l];for(;++i<l*l;)f=t[i/l][i%l].setScale(9,x.UP).equals(m[i/l][i%l].setScale(9,x.UP))?f:1;}return m;}

-17 ไบต์ขอบคุณที่@ceilingcat

ไม่ใช่ภาษาที่ถูกต้องแน่นอน .. ความแม่นยำของจุดลอยตัวประณาม ..

คำอธิบาย:

ลองออนไลน์

import java.math.*;     // Required import for BigDecimal and RoundingMode
m->{                    // Method with BigDecimal-matrix as both parameter and return-type
  BigDecimal t[][],q;   //  Temp BigDecimal-matrix
  RoundingMode x=null;  //  Static RoundingMode value to reduce bytes
  for(int l=m.length,   //  The size of the input-matrix
          f=1,          //  Flag-integer, starting at 1
          i,k;          //  Index-integers
      f>0;              //  Loop as long as the flag-integer is still 1
      m=t.clone()){     //    After every iteration: replace matrix `m` with `t`
    for(t=new BigDecimal[l][l],
                        //   Reset matrix `t`
        i=l*l;i-->0;)   //   Inner loop over the rows and columns
      for(f=k=0;        //    Set the flag-integer to 0
          k<l           //    Inner loop to multiply
          ;             //      After every iteration:
           t[i/l][i%l]=(q!=null?q:q.ZERO).add(
                        //       Sum the value at the current cell in matrix `t` with:
             m[i/l][k]  //        the same row, but column `k` of matrix `m`,
             .multiply(m[k++][i%l])))
                        //        multiplied with the same column, but row `k` of matrix `m`
        q=t[i/l][i%l];  //     Set temp `q` to the value of the current cell of `t`
    for(;++i<l*l;)      //   Loop over the rows and columns again
      f=t[i/l][i%l].setScale(9,x.UP).equals(m[i/l][i%l].setScale(9,x.UP))?
                        //    If any value in matrices `t` and `m` are the same:
         f              //     Leave the flag-integer unchanged
        :               //    Else (they aren't the same):
         1;}            //     Set the flag-integer to 1 again
  return m;}            //  Return the modified input-matrix `m` as our result

ฟังก์ชั่นหลักทำไม verbose เหรอ?
user202729

@ user202729 เนื่องจากfloat/ doubleไม่มีความแม่นยำของจุดลอยตัวที่เหมาะสมjava.math.BigDecimalควรใช้แทน และแทนที่จะ+-*/, BigDecimals ใช้.add(...), .subtract(...), ,.multiply(...) .divide(...)ดังนั้นสิ่งที่เป็นเพียงกลายเป็น7/10 new BigDecimal(7).divide(new BigDecimal(10))นอกจากนี้,scale,RoundingModeในdivideที่จำเป็นสำหรับค่าด้วย 'อนันต์' ทศนิยมค่า (เช่น1/3เป็น0.333...) แน่นอนว่าวิธีการหลักสามารถเล่นกอล์ฟได้ แต่ฉันไม่ต้องกังวลเมื่อฉันค้นหาและแทนที่เพื่อแปลงลอยเป็น BigDecimals
Kevin Cruijssen

@ceilingcat ขอบคุณ!
Kevin Cruijssen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.