การเขียนโปรแกรมเชิงเส้นจำนวนเต็ม


21

บทนำ

เขียนแก้สำหรับการเขียนโปรแกรมเชิงเส้นจำนวนเต็ม

ท้าทาย

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

ตัวอย่างเช่นสำหรับความไม่เท่าเทียมกัน (ตัวอย่างที่นำมาจากการเขียนโปรแกรมเชิงเส้นจำนวนเต็มแบบผสม )

 4x+2y-15≤0
  x+2y- 8≤0
  x+ y- 5≤0
- x      ≤0
   - y   ≤0

และฟังก์ชั่นวัตถุประสงค์3x+2yสูงสุดของฟังก์ชั่นวัตถุประสงค์ควรจะ12( x=2,y=3) ในขณะที่ขั้นต่ำควรจะ0( x=y=0)

อินพุตถูกกำหนดเป็นอาร์เรย์ 2d (หรือเทียบเท่าตามข้อกำหนดมาตรฐาน) แต่ละแถวสอดคล้องกับความไม่เท่าเทียมกันหนึ่งข้อยกเว้นแถวสุดท้าย ตัวเลขในอาร์เรย์เป็นค่าสัมประสิทธิ์และ≤0ส่วนที่ถูกละเว้นเสมอ หากมีnองค์ประกอบในแต่ละแถวก็หมายความว่ามีn-1สิ่งแปลกปลอม

แถวสุดท้ายของอาร์เรย์สอดคล้องกับฟังก์ชันเชิงเส้น ค่าสัมประสิทธิ์มีการระบุไว้

ตัวอย่างเช่นอาร์เรย์อินพุตสำหรับปัญหาข้างต้นคือ

[[4,2,-15],[1,2,-8],[1,1,-5],[-1,0,0],[0,-1,0],[3,2,0]].

ผลลัพธ์ควรเป็นค่าต่ำสุดและค่าสูงสุดที่กำหนดในรูปแบบที่สมเหตุสมผล

สำหรับปัญหาต่อไปนี้ (ข้อ จำกัด สองข้อถูกนำออกจากปัญหาข้างต้น):

[[4,2,-15],[1,2,-8],[1,1,-5],[3,2,0]].

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

[[4,2,-15],[-1,-2,7],[-1,0,3],[0,1,0],[3,2,0]].

ในกรณีนี้ค่าเท็จควรส่งออกเช่นกัน มันจะเป็นการดีที่จะแยกแยะกรณีที่ "ค่าที่ดีที่สุด" สำหรับฟังก์ชั่นวัตถุประสงค์คืออินฟินิตี้และกรณีที่ไม่มีวิธีแก้ปัญหาเลย แต่สิ่งนี้ไม่จำเป็น

อินพุตมีค่าสัมประสิทธิ์จำนวนเต็มทั้งสำหรับความไม่เท่าเทียมกันและสำหรับฟังก์ชันวัตถุประสงค์เท่านั้น สิ่งที่ไม่ทราบทั้งหมดเป็นจำนวนเต็มด้วย เมทริกซ์สัมประสิทธิ์ของความไม่เท่าเทียมกันรับประกันว่าจะมีอันดับเต็ม

กรณีทดสอบ

เครดิตให้กับ @KillillL สำหรับการค้นหาจุดบกพร่องในชุดทดสอบดั้งเดิมและทำให้ฉันเข้าใจปัญหา ILP ได้มากขึ้น

Input
Output

[[4,2,-15],[1,2,-8],[1,1,-5],[-1,0,0],[0,-1,0],[3,2,1]]
[1,13]

[[4,2,-15],[1,2,-8],[1,1,-5],[3,2,0]]
[-inf, 12]

[[4,2,-15],[-1,-2,7],[-1,0,3],[0,1,0],[3,2,0]]
[NaN, NaN]

[[-1,-1,-1,-1,-1,8],[1,1,1,1,0,0],[5,5,5,5,6,7]]
[55, inf]

[[-1,-1,-1,-1,-1,8],[1,1,1,1,0,0],[0,0,0,0,0,4]]
[4, 4]

[[4,2,-15],[-1,-2,7],[-1,0,3],[0,1,0],[0,0,4]]
[NaN, NaN]

รายละเอียด

  • ไม่จำเป็นต้องกังวลเกี่ยวกับการจัดการข้อยกเว้น

  • นี่คือจำนวนไบต์ต่ำสุดชนะ

  • 9จำนวนสูงสุดของราชวงศ์: 12จำนวนสูงสุดของความไม่เท่าเทียมกัน:

  • คุณสามารถรับอินพุตและให้เอาต์พุตผ่านรูปแบบมาตรฐานและคุณสามารถเลือกรูปแบบได้ฟรี

  • ตามปกติช่องโหว่เริ่มต้นจะมีผลที่นี่



คุณยังไม่ได้กล่าวถึงอย่างชัดเจนในคำอธิบายงาน แต่ฉันสงสัยว่าคุณกำลังมองหาการใช้อัลกอริธึมดั้งเดิมและไม่ใช่รหัสที่น่าเบื่อที่ใช้ไลบรารีที่มีอยู่ใช่หรือไม่ อย่างไรก็ตามฉันเล่นกับกรณีทดสอบของคุณใน R และไม่สามารถทำซ้ำผลลัพธ์ได้แน่นอน EG, [55, inf] กรณีนี้จะทำงานเฉพาะเมื่อตัวแปรถูกผูกไว้ว่าจะไม่เป็นลบ แต่กรณี [-inf, 12] ก็ให้ผลลัพธ์ปกติ [0, 12] ในทางกลับกันเมื่อขอบเขตล่างคือ -inf ตัวพิมพ์เล็ก [55, inf] จะไม่สามารถแก้ปัญหาได้ทั้งในนาทีและสูงสุด
Kirill L.

ใช่ฉันกำลังมองหาการใช้งานดั้งเดิม
Weijun Zhou

@KirillL คุณสามารถให้เวกเตอร์ที่ฟังก์ชันในกรณีทดสอบ [55, inf] ให้ค่าน้อยกว่า 55 ได้หรือไม่? ฉันเพิ่งตรวจสอบกับผู้แก้ปัญหาออนไลน์และคดีนี้ดูเหมือนจะไม่เป็นไร ฉันมีเหตุผลต่อไปนี้เมื่อสร้างกรณีทดสอบ: ข้อ จำกัด แรกต้องการผลรวมของตัวแปรอิสระทั้งหมดเป็น geq 8 แต่ข้อที่สองต้องการผลรวมของทั้งหมดยกเว้นอันสุดท้ายเป็น leq 0 หากเราพยายามลด เป้าหมายโดยการลดวาร์อิสระอิสระ 4 ตัวแรกนั้นจะต้องเพิ่มวาร์สุดท้ายด้วยจำนวนเดียวกันดังนั้นจึงมีค่าที่มากขึ้นสำหรับเป้าหมาย
Weijun Zhou

นี่คือตัวอย่างของฉันแม้ว่ามันจะไม่ทำงานบน TIO เนื่องจากห้องสมุดหายไป สิ่งนี้จะให้ 55 แต่ออกด้วย "model is unbounded" เมื่อฉันไม่ใส่เครื่องหมายบรรทัด set.bounds ค่อนข้างเป็นไปได้ว่าข้อผิดพลาดอยู่ข้างฉัน คุณสามารถให้ลิงค์ไปยังนักแก้ปัญหาออนไลน์ได้หรือไม่
Kirill L.

คำตอบ:


2

Python 3 , 534 ไบต์

import itertools as t
import operator as o
I=float("inf")
e=lambda p,A:sum([i[0]*i[1]for i in zip(p,A[:-1])])+A[-1]
def w(x,j):
	d=len(x[0])-1;C=[0]*d;v,w=I,I
	while 1:
		L={(*n,):(sum([0 if e(n,A)<=0 else e(n,A)for A in x[:-1]]),j*e(n,x[-1]))for n in [[sum(a) for a in zip(C,c)]for c in t.product(*[[-1,0,1]]*d)]};C,P=min(L.items(),key=o.itemgetter(1))[0],C;v,w,p,q=L[C][0],L[C][1],v,w
		if(all([e(C,A)<=e(P,A)for A in x[:-1]]))*(j*(e(C,x[-1])-e(P,x[-1]))<0)+(p==v>0):return I
		if(p==v)*(q<=w):return j*q
f=lambda x:(w(x,1),w(x,-1))

ลองออนไลน์!

ภาพรวม

มันเป็นอัลกอริทึมซ้ำเริ่มต้นจาก origo มันรวบรวมตำแหน่งเพื่อนบ้านและกำหนดฟังก์ชั่นที่มีศักยภาพ: x:(a,b)ที่ไหนxคือตำแหน่งaคือผลรวมของระยะทางของตำแหน่งจากครึ่งช่องว่างของความไม่เท่าเทียมกันเชิงเส้นแต่ละอันbคือค่าของวัตถุประสงค์ที่ตำแหน่งนั้น

x:(a,b) < y:(c,d)iff a<cหรือa=c and b<d

การทำซ้ำจะหยุดเมื่อ:

  • พิกัดแรกของศักยภาพไม่ลดลงและเป็นบวก: ระบบไม่สามารถทำได้
  • ระยะห่างจากทุกครึ่งอวกาศลดลงเช่นเดียวกับวัตถุประสงค์: ระบบนั้นไม่ได้ จำกัด ขอบเขต
  • ไม่เคยมีมาก่อนและความเป็นไปได้ที่ไม่ลดลง: เป็นค่าที่เหมาะสมที่สุด

1

Matlab, 226 ไบต์

การปฏิเสธความรับผิด : ไม่ใช่การใช้ "ดั้งเดิม" เพื่อความสนุกสนานเท่านั้น

ทางออกที่ง่ายการใช้ประโยชน์จากintlinprogฟังก์ชั่น:

function r=f(a);b=-1*a(1:end-1,end);p=a(end,1:end-1);c=a(1:end-1,1:end-1);[~,f,h]=intlinprog(p,1:size(a,2)-1,c,b);[~,g,i]=intlinprog(-p,1:size(a,2)-1,c,b);s=[inf,nan,f];t=[inf,nan,g];r=a(end,end)+[s(4-abs(h)) -t(4-abs(i))];end

ส่งคืนค่าที่ดีที่สุดหรือ inf (-inf) หากปัญหาไม่ได้ จำกัด หรือน่านถ้าเป็นไปไม่ได้

a = [4 2 -15; 1 2 -8; 1 1 -5; -1 0 0; 0 -1 0; 3 2 1]
b = [4 2 -15; 1 2 -8; 1 1 -5; 3 2 0]
c = [4 2 -15; -1 -2 7; -1 0 3; 0 1 0; 3 2 0]
d = [-1 -1 -1 -1 -1 8;  1 1 1 1 0 0; 0 0 0 0 0 4]
e = [4 2 -15; -1 -2 7; -1 0 3; 0 1 0; 0 0 4]

>> f(a)
ans =

     1    13

>> f(b)
ans =

   Inf    12

>> f(c)
ans =

   NaN   NaN

>> f(d)
ans =

     4     4

>> f(e)
ans =

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