ছোট বর্গক্ষেত্রের ম্যাট্রিক্সের জন্য দ্রুততম লিনিয়ার সিস্টেম সমাধান (10x10)


9

আমি ছোট ম্যাট্রিকেস (10x10), কখনও কখনও ক্ষুদ্র ম্যাট্রিক্স নামে পরিচিত, লিনিয়ার সিস্টেম সমাধানের বাইরে ন্যূনতম অনুকূলকরণে খুব আগ্রহী । এর কি কোনও প্রস্তুত সমাধান আছে? ম্যাট্রিক্সকে নোনসিংুলার ধরে নেওয়া যেতে পারে।

এই সলভারটি একটি ইনটেল সিপিইউতে মাইক্রোসেকেন্ডগুলিতে 1 000 000 বারের বেশি মৃত্যুদন্ড কার্যকর করা উচিত। আমি কম্পিউটার গেমগুলিতে অপ্টিমাইজেশনের স্তরের সাথে কথা বলছি। আমি এটি সমাবেশ এবং আর্কিটেকচার-নির্দিষ্ট, বা অধ্যয়ন যথাযথতা বা নির্ভরযোগ্যতা ট্রেডঅফস হ্রাস ব্যবহার এবং ভাসমান পয়েন্ট হ্যাক ব্যবহার করি তা বিবেচনা করেই আসে না (আমি -ফাস্ট-গণিতের সংকলন পতাকা ব্যবহার করি না, কোনও সমস্যা নেই)। সমাধান এমনকি প্রায় 20% সময়ের জন্য ব্যর্থ হতে পারে!

ইগিজেনের আংশিকপিভলু আমার বর্তমান মানদণ্ডের মধ্যে দ্রুততম, ল্যাপাককে ছাড়িয়ে যায় যখন -O3 এবং একটি ভাল সংকলক দিয়ে অনুকূলিত হয়। তবে এখন আমি একটি কাস্টম লিনিয়ার সলভারকে হস্তশিল্পের বিন্দুতে আছি। যেকোন উপদেশ সাদরে গ্রহণ করা হবে। আমি আমার সমাধানটি মুক্ত উত্স তৈরি করব এবং আমি প্রকাশনা ইত্যাদির মূল অন্তর্দৃষ্টিগুলি স্বীকার করব ..

সম্পর্কিত: ব্লক ডায়াগোনাল ম্যাট্রিক্স সহ রৈখিক সিস্টেমের সমাধানের গতি কয়েক মিলিয়ন ম্যাট্রিককে উল্টানোর দ্রুততম পদ্ধতি কোনটি? https://stackoverflow.com/q/50909385/1489510


7
এটি স্ট্রেচ গোলের মতো দেখাচ্ছে। আসুন ধরে নেওয়া যাক আমরা 4 টি একক নির্ভুলতা টিএফএলওপিগুলির তাত্ত্বিক পিক থ্রুপুট সহ দ্রুততম স্কাইলেক-এক্স জিয়ন প্ল্যাটিনাম 8180 ব্যবহার করি এবং 10x10 সিস্টেমে প্রায় 700 (প্রায় 2 এন ** 3/3) সমাধানের জন্য ভাসমান-পয়েন্ট অপারেশন প্রয়োজন। তারপরে 1M এর মতো ব্যাচের একটি ব্যাচ তাত্ত্বিকভাবে 175 মাইক্রোসেকেন্ডগুলিতে সমাধান করা যেতে পারে। এটি হালকা গতির চেয়ে বেশি ছাড়িয়ে যায় না। আপনি বর্তমানে আপনার দ্রুততম কোডটি দিয়ে কী সম্পাদন করছেন তা ভাগ করে নিতে পারেন? বিটিডাব্লু, ডেটা একক নির্ভুলতা বা ডাবল নির্ভুলতা?
njuffa

@ এনজুফা হ্যাঁ আমি লক্ষ্য করেছিলাম 1 মিমি কাছাকাছি অর্জন করা কিন্তু মাইক্রো আরেকটি গল্প। মাইক্রোটির জন্য আমি ব্যাচের ইনক্রিমেন্টাল ইনভার্স স্ট্রাকচারকে একই ধরণের ম্যাট্রিকগুলি সনাক্ত করে বিবেচনা করেছিলাম, যা প্রায়শই ঘটে। প্রসেসরের উপর নির্ভর করে পারফ 10-1500 মাইলের পরিসরে সর্বাধিক আকারে রয়েছে। যথার্থ ডাবল বা এমনকি জটিল ডাবল। একক নির্ভুলতা ধীর হয় না।
rfabbri

@ এনজুফা আমি গতির জন্য নির্ভুলতা হ্রাস করতে বা আপ করতে পারি
rfabbri

2
দেখে মনে হচ্ছে যথার্থতা / নির্ভুলতা আপনার অগ্রাধিকার নয়। আপনার লক্ষ্যের জন্য, তুলনামূলকভাবে অল্প সংখ্যক মূল্যায়নে কাটা একটি পুনরুক্তি পদ্ধতি কার্যকর? বিশেষত আপনার যদি যুক্তিসঙ্গত প্রাথমিক অনুমান থাকে।
স্পেনসার ব্রায়ঞ্জেলসন 3:37 এ

1
আপনি কি পিভট? আপনি কি গাউসিয়ান নির্মূলের পরিবর্তে কিউআর ফ্যাক্টরীকরণ করতে পারবেন? আপনি কি সিস্টেমে ইন্টারলিভ করেন যাতে আপনি সিমডি নির্দেশাবলী ব্যবহার করতে পারেন এবং একসাথে বেশ কয়েকটি সিস্টেম করতে পারেন? আপনি কি কোনও লুপ এবং কোনও অপ্রত্যক্ষ ঠিকানা না দিয়ে সরাসরি লাইনের প্রোগ্রামগুলি লেখেন? আপনি কী সঠিকতা চান এবং আমি কীভাবে কন্ডিশনার করব আপনার সিস্টেম? তাদের কি এমন কোনও কাঠামো রয়েছে যা ব্যবহার করা যেতে পারে?
কার্ল খ্রিস্টান

উত্তর:


7

একটি ইগেন ম্যাট্রিক্স টাইপ ব্যবহার করে যেখানে সংকলনের সময় সারি এবং কলামগুলির সংখ্যা এনকোড করা থাকে তা আপনাকে LAPACK এর ওপরে প্রান্ত দেয়, যেখানে ম্যাট্রিক্সের আকারটি কেবল রানটাইমের সময় জানা যায়। এই অতিরিক্ত তথ্য সংকলকটি প্রচুর শাখার নির্দেশাবলী সরিয়ে পুরো বা আংশিক লুপকে আনআরোলিং করার অনুমতি দেয়। আপনি যদি নিজের কার্নেলগুলি লেখার পরিবর্তে কোনও বিদ্যমান গ্রন্থাগার ব্যবহারের দিকে তাকিয়ে থাকেন তবে ম্যাট্রিক্সের আকারটি সি ++ টেম্পলেট প্যারামিটার হিসাবে অন্তর্ভুক্ত করা যেতে পারে এমন একটি ডেটা টাইপ থাকা সম্ভবত প্রয়োজনীয় হবে। আমি কেবলমাত্র অন্যান্য গ্রন্থাগারই এটি জানি এটি জ্বলজ্বল , যাতে ইগেনের বিরুদ্ধে মানদণ্ডগুলি মূল্যবান হতে পারে।

যদি আপনি নিজের প্রয়োগটি রোল করার সিদ্ধান্ত নেন তবে আপনি পেতে পারেন যে পিইটিএসসি এর ব্লক সিএসআর ফর্ম্যাটটির জন্য একটি দরকারী উদাহরণ হতে পারে, যদিও পিইটিএসসি নিজেই সম্ভবত আপনার মনে মনে রাখার সঠিক সরঞ্জাম হবে না। একটি লুপ লেখার পরিবর্তে, তারা ছোট ম্যাট্রিক্স-ভেক্টর গুণমানের জন্য প্রতিটি একক ক্রিয়াকলাপ স্পষ্টভাবে লেখেন ( তাদের ভান্ডারে এই ফাইলটি দেখুন )। এটি গ্যারান্টি দেয় যে কোনও শাখার নির্দেশনা নেই আপনার মতো লুপটি পেতে পারে। অ্যাভিএক্স নির্দেশাবলী সহ কোডটির সংস্করণগুলি প্রকৃতপক্ষে ভেক্টর এক্সটেনশনগুলি কীভাবে ব্যবহার করতে হয় তার একটি ভাল উদাহরণ। উদাহরণস্বরূপ, এই ফাংশনটি ব্যবহার করে__m256dডেটা টাইপ একই সাথে চারটি ডাবল একই সময়ে কাজ করতে। ভ্যাটর এক্সটেনশানগুলি স্পষ্টভাবে সমস্ত ক্রিয়াকলাপগুলি ম্যাট্রিক্স-ভেক্টর গুণক পরিবর্তে LU ফ্যাক্টেরাইজেশন ব্যবহার করে স্পষ্টভাবে লিখে লিখে আপনি একটি প্রশংসনীয় পারফরম্যান্স উত্সাহ পেতে পারেন। আসলে হাতে হাতে সি কোড লেখার পরিবর্তে, আপনি এটি তৈরি করতে কোনও স্ক্রিপ্ট ব্যবহার করা ভাল better নির্দেশিকা পাইপলাইনের আরও ভালভাবে সুবিধা গ্রহণের জন্য আপনি যখন কিছু অপারেশন পুনরায় অর্ডার করেন তখন কোনও প্রশংসনীয় পারফরম্যান্স পার্থক্য রয়েছে কিনা তাও মজাদার হতে পারে।

আপনি STOKE সরঞ্জামটি থেকে কিছু মাইলেজ পেতে পারেন যা একটি দ্রুত সংস্করণ সন্ধান করার জন্য এলোমেলোভাবে সম্ভাব্য প্রোগ্রাম রূপান্তরের স্থানটি অন্বেষণ করবে।


TX। আমি ইতিমধ্যে মানচিত্র <কনট ম্যাট্রিক্স <জটিল, 10, 10>> এএ (এ) এর মতো ইগেন ব্যবহার করেছি। অন্যান্য জিনিস পরীক্ষা করা হবে।
rfabbri

আইগেন এর কাছে এভিএক্স এবং এমনকি একটি জটিল শিরোনাম রয়েছে। এর জন্য পিইটিএসসি কেন? এক্ষেত্রে ইয়েগেনের সাথে প্রতিযোগিতা করা শক্ত। আমি ইগেনকে আমার সমস্যার জন্য আরও বিশেষভাবে তৈরি করেছি এবং একটি আনুমানিক পাইভট কৌশল নিয়ে যে একটি কলামের উপরে সর্বাধিক গ্রহণের পরিবর্তে, যখন তৃতীয় আকারের 3 টি বড় আকারের অন্য কোনও সন্ধান পায় তখন সঙ্গে সঙ্গে একটি পিভটকে অদলবদল করে।
rfabbri

1
@rfabbri আমি আপনাকে প্রস্তাব দিইনি যে আপনি এর জন্য PETSc ব্যবহার করুন, কেবলমাত্র তারা that বিশেষ পরিস্থিতিতে যা করেন তা শিক্ষামূলক হতে পারে। আরও পরিষ্কার করার জন্য আমি উত্তরটি সম্পাদনা করেছি।
ড্যানিয়েল শাপেরো

4

আর একটি ধারণা হতে পারে জেনারেটর পদ্ধতির (কোনও প্রোগ্রাম লেখার একটি প্রোগ্রাম) ব্যবহার করা। লেখক একটি (মেটা) প্রোগ্রাম যা 10x10 সিস্টেমে অপরিবর্তিত ** এলইউ সঞ্চালনের জন্য সি / সি ++ নির্দেশাবলীর অনুক্রমকে আলাদা করে দেয় .. মূলত কে / আই / জ লুপ নীড় গ্রহণ করে এবং এটি (1000) বা আরও লাইনগুলিতে সমতল করে তোলে স্ক্যালার পাটিগণিত। তারপরে যে উত্পন্ন প্রোগ্রামটিকে যেকোনও অনুকূলিতকরণকারী সংকলক হিসাবে ফিড দিন। আমি এখানে যা কিছু ধরণের আকর্ষণীয় বলে মনে করি, লুপগুলি অপসারণ করে প্রতিটি তথ্য নির্ভরতা এবং অপ্রয়োজনীয় সুবে এক্সপ্রেশন প্রকাশ করে এবং সংকলককে নির্দেশাবলীর পুনঃক্রম করার সর্বাধিক সুযোগ দেয় যাতে তারা প্রকৃত হার্ডওয়্যারগুলিতে (যেমন এক্সিকিউশন ইউনিট, বিপদ / স্টলগুলির সংখ্যা, তাই) চালু).

যদি আপনি ম্যাট্রিক্সের সমস্ত (বা তাদের মধ্যে কয়েকটি মাত্র) জানার ক্ষেত্রে ঘটে থাকেন তবে আপনি স্কেলার কোডের পরিবর্তে সিমড ইনট্রিন্সিক / ফাংশন (এসএসই / এভিএক্স) কল করে থ্রুপুট উন্নত করতে পারেন। এখানে আপনি একক দৃষ্টান্তের মধ্যে কোনও সমান্তরালতার পিছনে পিছনে গিয়ে উদাহরণস্বরূপ বিব্রতকর সমান্তরালতাটি ব্যবহার করছেন। উদাহরণস্বরূপ, আপনি রেজিস্টারটিকে "জুড়ে" জুড়ে 4 টি ম্যাট্রিক্স প্যাক করে এবং তাদের সকলের উপর একই ক্রিয়াকলাপ ** করে একযোগে 4 টি ডাবল নির্ভুলতা এলইউ করতে পারেন AV

** অতএব অপরিবর্তিত এলইউতে ফোকাস। পিভোটিং এই পদ্ধতিকে দু'ভাবে লুণ্ঠন করে। প্রথমত, এটি পিভট নির্বাচনের কারণে শাখাগুলি উপস্থাপন করে যার অর্থ আপনার ডেটা নির্ভরতা ততটা সঠিকভাবে জানা যায় না। দ্বিতীয়ত, এর অর্থ হ'ল ভিন্ন সিমডি "স্লটগুলি" বিভিন্ন কাজ করতে হবে, কারণ উদাহরণ এ-এর চেয়ে আলাদাভাবে বিভক্ত হতে পারে বি। সুতরাং আপনি যদি এর কোনটি অনুসরণ করেন তবে আমি গণনা করার আগে আপনার ম্যাট্রিকগুলি স্থিতিশীলভাবে পাইভোট করার পরামর্শ দেব (বৃহত্তম প্রবেশপথের অনুমতি দিন) প্রতিটি কলামের তির্যক)


যেহেতু ম্যাট্রিকগুলি এত ছোট, সম্ভবত পিভটিংটি যদি পূর্ব-স্কেল করা হয় তবে তা শেষ করা যায়। এমনকি ম্যাট্রিকগুলি প্রি-পাইভোটিংও নয়। আমাদের কেবলমাত্র এন্ট্রিগুলি একে অপরের परिमाणের 2-3 আদেশের মধ্যে থাকা দরকার।
rfabbri

2

আপনার প্রশ্ন দুটি ভিন্ন বিবেচনার দিকে নিয়ে যায়।

প্রথমত, আপনাকে সঠিক অ্যালগরিদম বাছাই করতে হবে। সুতরাং, প্রশ্নটি ম্যাট্রিকগুলির কোনও কাঠামো আছে কিনা তা বিবেচনা করা উচিত। উদাহরণস্বরূপ, যখন ম্যাট্রিকগুলি প্রতিসম হয়, একটি Cholesky পচন LU এর চেয়ে বেশি কার্যকর। যখন আপনার কেবলমাত্র সীমিত পরিমাণের নির্ভুলতার প্রয়োজন হবে তখন একটি পুনরাবৃত্তি পদ্ধতি দ্রুততর হতে পারে।

দ্বিতীয়ত, আপনাকে দক্ষতার সাথে অ্যালগরিদমটি প্রয়োগ করতে হবে। এটি করতে, আপনাকে আপনার অ্যালগরিদমের বাধা জানতে হবে। আপনার বাস্তবায়ন কি মেমরি স্থানান্তরের গতি বা গণনার গতির দ্বারা আবদ্ধ? যেহেতু আপনি কেবল বিবেচনা করুন10×10ম্যাট্রিক্স, আপনার ম্যাট্রিক্স সিপিইউ ক্যাশে সম্পূর্ণরূপে ফিট করা উচিত। সুতরাং, আপনার সিমড ইউনিটগুলি (এসএসই, এভিএক্স, ইত্যাদি) এবং আপনার প্রসেসরের কোরগুলি ব্যবহার করা উচিত, যতটা সম্ভব চক্র প্রতি কমপিটেশন করা যায়।

সব মিলিয়ে আপনার প্রশ্নের উত্তরটি আপনি যে হার্ডওয়্যার এবং ম্যাট্রিকগুলিতে বিবেচনা করছেন তার উপর নির্ভর করে। সম্ভবত কোনও নির্দিষ্ট উত্তর নেই এবং একটি অনুকূল পদ্ধতি খুঁজে পেতে আপনাকে কয়েকটি জিনিস চেষ্টা করতে হবে try


এখনও অবধি ইগেন ইতিমধ্যে ভারীভাবে অনুকূল করে ফেলেছে, এসই, এভিএক্স ইত্যাদি ব্যবহার করে এবং আমি প্রাথমিক পরীক্ষায় পুনরাবৃত্ত পদ্ধতিগুলি চেষ্টা করেছি এবং তারা সাহায্য করেনি। আমি ইন্টেল এমকেএল চেষ্টা করেছি তবে অপ্টিমাইজড জিসিসি পতাকা সহ ইগেনের চেয়ে ভাল আর কিছু নেই। আমি বর্তমানে ইগেনের চেয়ে ভাল এবং সহজ কিছু হ্যান্ডক্রাফ্ট করার এবং পুনরাবৃত্ত পদ্ধতিগুলির সাথে আরও বিশদ পরীক্ষা করার চেষ্টা করছি।
rfabbri

1

আমি ব্লকওয়্যার বিপরীত চেষ্টা করব।

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 ম্যাট্রিক্সকে উল্টে দেয় (এবং হ্যাঁ, আমার কোনও বিপরীতের স্বতন্ত্র সহগ প্রয়োজন তাই সরাসরি লিনিয়ার সিস্টেমের সমাধান করা সবসময় বিকল্প নয়) ।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.