আমি ব্লকওয়্যার বিপরীত চেষ্টা করব।
https://en.wikipedia.org/wiki/Invertible_matrix#Blockwise_inversion
ইগেন 4x4 ম্যাট্রিক্সের বিপরীত গণনা করতে একটি অনুকূলিত রুটিন ব্যবহার করে, যা সম্ভবত আপনি সবচেয়ে ভাল যাচ্ছেন। যতটা সম্ভব ব্যবহার করার চেষ্টা করুন।
http://www.eigen.tuxfamily.org/dox/Inverse__SSE_8h_source.html
শীর্ষ বাম: 8x8। শীর্ষ ডানদিকে: 8x2। নীচে বাম: 2x8। নীচের ডানদিকে: 2x2। অপ্টিমাইজড 4x4 ইনভার্সন কোডটি ব্যবহার করে 8x8 বিপরীত করুন। বাকিটি ম্যাট্রিক্স পণ্য।
সম্পাদনা: 6x6, 6x4, 4x6, এবং 4x4 ব্লক ব্যবহার করে আমি উপরে বর্ণিত চেয়ে কিছুটা দ্রুত গতিতে দেখায়।
using namespace Eigen;
template<typename Scalar, int tl_size, int br_size>
Matrix<Scalar, tl_size + br_size, tl_size + br_size> blockwise_inversion(const Matrix<Scalar, tl_size, tl_size>& A, const Matrix<Scalar, tl_size, br_size>& B, const Matrix<Scalar, br_size, tl_size>& C, const Matrix<Scalar, br_size, br_size>& D)
{
Matrix<Scalar, tl_size + br_size, tl_size + br_size> result;
Matrix<Scalar, tl_size, tl_size> A_inv = A.inverse().eval();
Matrix<Scalar, br_size, br_size> DCAB_inv = (D - C * A_inv * B).inverse();
result.topLeftCorner<tl_size, tl_size>() = A_inv + A_inv * B * DCAB_inv * C * A_inv;
result.topRightCorner<tl_size, br_size>() = -A_inv * B * DCAB_inv;
result.bottomLeftCorner<br_size, tl_size>() = -DCAB_inv * C * A_inv;
result.bottomRightCorner<br_size, br_size>() = DCAB_inv;
return result;
}
template<typename Scalar, int tl_size, int br_size>
Matrix<Scalar, tl_size + br_size, tl_size + br_size> my_inverse(const Matrix<Scalar, tl_size + br_size, tl_size + br_size>& mat)
{
const Matrix<Scalar, tl_size, tl_size>& A = mat.topLeftCorner<tl_size, tl_size>();
const Matrix<Scalar, tl_size, br_size>& B = mat.topRightCorner<tl_size, br_size>();
const Matrix<Scalar, br_size, tl_size>& C = mat.bottomLeftCorner<br_size, tl_size>();
const Matrix<Scalar, br_size, br_size>& D = mat.bottomRightCorner<br_size, br_size>();
return blockwise_inversion<Scalar,tl_size,br_size>(A, B, C, D);
}
template<typename Scalar>
Matrix<Scalar, 10, 10> invert_10_blockwise_8_2(const Matrix<Scalar, 10, 10>& input)
{
Matrix<Scalar, 10, 10> result;
const Matrix<Scalar, 8, 8>& A = input.topLeftCorner<8, 8>();
const Matrix<Scalar, 8, 2>& B = input.topRightCorner<8, 2>();
const Matrix<Scalar, 2, 8>& C = input.bottomLeftCorner<2, 8>();
const Matrix<Scalar, 2, 2>& D = input.bottomRightCorner<2, 2>();
Matrix<Scalar, 8, 8> A_inv = my_inverse<Scalar, 4, 4>(A);
Matrix<Scalar, 2, 2> DCAB_inv = (D - C * A_inv * B).inverse();
result.topLeftCorner<8, 8>() = A_inv + A_inv * B * DCAB_inv * C * A_inv;
result.topRightCorner<8, 2>() = -A_inv * B * DCAB_inv;
result.bottomLeftCorner<2, 8>() = -DCAB_inv * C * A_inv;
result.bottomRightCorner<2, 2>() = DCAB_inv;
return result;
}
template<typename Scalar>
Matrix<Scalar, 10, 10> invert_10_blockwise_6_4(const Matrix<Scalar, 10, 10>& input)
{
Matrix<Scalar, 10, 10> result;
const Matrix<Scalar, 6, 6>& A = input.topLeftCorner<6, 6>();
const Matrix<Scalar, 6, 4>& B = input.topRightCorner<6, 4>();
const Matrix<Scalar, 4, 6>& C = input.bottomLeftCorner<4, 6>();
const Matrix<Scalar, 4, 4>& D = input.bottomRightCorner<4, 4>();
Matrix<Scalar, 6, 6> A_inv = my_inverse<Scalar, 4, 2>(A);
Matrix<Scalar, 4, 4> DCAB_inv = (D - C * A_inv * B).inverse().eval();
result.topLeftCorner<6, 6>() = A_inv + A_inv * B * DCAB_inv * C * A_inv;
result.topRightCorner<6, 4>() = -A_inv * B * DCAB_inv;
result.bottomLeftCorner<4, 6>() = -DCAB_inv * C * A_inv;
result.bottomRightCorner<4, 4>() = DCAB_inv;
return result;
}
এখানে দশ লক্ষ Eigen::Matrix<double,10,10>::Random()
ম্যাট্রিক এবং Eigen::Matrix<double,10,1>::Random()
ভেক্টর ব্যবহার করে একটি বেঞ্চ চিহ্নের ফলাফল রয়েছে । আমার সমস্ত পরীক্ষায়, আমার বিপরীত সবসময় দ্রুত হয়। আমার সমাধানের রুটিনে অন্তর্নির্মিত গণনা করা এবং তারপরে এটি কোনও ভেক্টর দ্বারা গুণ করা জড়িত। কখনও কখনও এটি ইগেনের চেয়ে দ্রুত, কখনও কখনও তা নয়। আমার বেঞ্চ চিহ্নিতকরণ পদ্ধতিটি ত্রুটিযুক্ত হতে পারে (টার্বো বুস্ট ইত্যাদি অক্ষম করে না)। এছাড়াও, আইগেনের এলোমেলো ক্রিয়াকলাপগুলি বাস্তব ডেটার প্রতিনিধিত্ব করতে পারে না।
- ইগেন আংশিক পাইভট বিপরীত: 3036 মিলিসেকেন্ড
- 8x8 উপরের ব্লকের সাথে আমার বিপরীত: 1638 মিলিসেকেন্ড
- 6x6 উপরের ব্লকের সাথে আমার বিপরীত: 1234 মিলিসেকেন্ড
- আইজেন আংশিক পাইভোট সমাধান: 1791 মিলিসেকেন্ড
- 8x8 উপরের ব্লকটির সাথে আমার সমাধান: 1739 মিলিসেকেন্ড
- 6x6 উপরের ব্লকটির সাথে আমার সমাধান: 1286 মিলিসেকেন্ড
আমি এটি দেখতে আগ্রহী যে কেউ এটিকে আরও অনুকূল করতে পারে কিনা, কারণ আমার কাছে একটি সীমাবদ্ধ উপাদান প্রয়োগ রয়েছে যা গাজিলিয়ন 10x10 ম্যাট্রিক্সকে উল্টে দেয় (এবং হ্যাঁ, আমার কোনও বিপরীতের স্বতন্ত্র সহগ প্রয়োজন তাই সরাসরি লিনিয়ার সিস্টেমের সমাধান করা সবসময় বিকল্প নয়) ।