如何在蒙特卡洛积分中查找点x,y是不是在给定矩形内
Posted
技术标签:
【中文标题】如何在蒙特卡洛积分中查找点x,y是不是在给定矩形内【英文标题】:how to find if a point x,y is inside a given rectangle in monte carlo integration如何在蒙特卡洛积分中查找点x,y是否在给定矩形内 【发布时间】:2021-12-11 18:36:11 【问题描述】:我正在对一个矩形进行蒙特卡罗积分,该矩形在封闭矩形内包含矩形。我想找出没有被任何嵌入矩形覆盖的矩形区域。
下面是矩形类和蒙特卡罗积分。我需要帮助来检查一个点是否在给定的矩形内(def inside(...))。我得到了错误
File "/skeleton_assignment01_example1/example1/montecarlo.py", line 67, in inside
number_recs = len(rect)
TypeError: 'method' object cannot be interpreted as an integer
我不知道如何解释这一点,也不是很熟悉使用对象。也许有不同的方法可以做到这一点,或者我的方法是错误的。谢谢
class Rectangle():
def __init__(self, origin_x, origin_y, length, width):
self.origin_x = origin_x
self.origin_y = origin_y
self.length = length
self.width = width
def rect_values(self):
return self.origin_x, self.origin_y, self.length, self.width
from random import random
class MonteCarlo:
def __init__(self, length, width, rectangles):
rect_specs = length or width or rectangles
if isinstance(rect_specs, type(None)):
raise ValueError
self.rec_length = length
self.rec_width = width
self.rects = rectangles
def area(self, num_of_shots):
"""Method to estimate the area of the enclosing rectangle that is not covered by the embedded rectangles
"""
if isinstance(num_of_shots, type(None)):
raise ValueError
inside = 0
total = num_of_shots
for i in range(num_of_shots):
x = random() * self.rec_length
y = random() * self.rec_width
if self.inside(x,y, self.rects) == True:
inside += 1
area = (total - inside) / (total * self.rec_length * self.rec_width)
return area
def inside(self, x, y, rect):
"""Method to determine if a given point (x,y) is inside a given rectangle
"""
if (x or y or rect) == None:
raise ValueError
number_recs = len(rect)
for i in range(number_recs):
origin_x, origin_y, length, width = rect[i].rect_values()
x_line = length+origin_x
y_line = width+origin_y
if (x <= x_line and y <= y_line) and (x >= origin_x and y >= origin_y):
return True
这是运行时抛出错误的长单元测试!希望这会有所帮助。
import unittest
from montecarlo import MonteCarlo
from rectangle import Rectangle
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def get_x(self):
return self.x
def get_y(self):
return self.y
class TestAssignment01ex01Student(unittest.TestCase):
def testMCwith3rects(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rect2 = Rectangle(6.0, 3.0, 6.0, 4.0)
rect3 = Rectangle(10.0, 5.0, 4.0, 4.0)
rects = [rect1, rect2, rect3]
mc = MonteCarlo(15.0, 10.0, rects)
area = mc.area(1000000)
self.assertTrue((area >= 97.5 and area <= 98.5),
"MonteCarlo.area(1000000) with the enclosing rectangle 15.0x10.0 " +
"and the following embedded rectangles failed (area should be +/- 0.5 to the result 98 but your result is: " + str(
area) + " " + self.printRectanglesData(rects))
def testMCwith2Rects(self):
# area of enclosing rectangle is 50
# area of embedded rectangles is 2+12=14
# result is: 50-14=36
#
# embedded rectangle 1 is at position (0,0) with a size of 1x2
rect1 = Rectangle(0.0, 0.0, 1.0, 2.0)
# embedded rectangle 2 is at position (7,1) with a size of 3x4
rect2 = Rectangle(7.0, 1.0, 3.0, 4.0)
rects = [rect1, rect2]
mc = MonteCarlo(10.0, 5.0, rects)
area = mc.area(10000)
# for 10k random points the estimated area should already be close to correct result of 36
self.assertTrue((area > 30 and area < 40),
"MonteCarlo.area() according to the provided unit test failed! Area should be between 30 and 40 but was " + str(
area))
def testInsideRectBorderline1Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, 4.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
def testInsideRectBorderline2Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, 0.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
def testInsideRectBorderline3Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, 4.01)
self.assertFalse(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned True but should be False!")
def testInsideRectBorderline4Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, -0.01)
self.assertFalse(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned True but should be False!")
def testInsideRectBorderline1X(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(0.0, 3.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
def testInsideRectBorderline2X(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(4.0, 3.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
# /*************************************
# *
# * private methods
# *
# */
def printRectanglesData(self, rects):
i = 0
sb = ""
while i < len(rects):
sb += "\n Rectangle ".format(i + 1) + "(x="
sb += str(rects[i].origin_x) + " y=" + str(rects[i].origin_y)
sb += " length="
sb += str(rects[i].length) + " )"
i += 1
return sb
def printRectangleData(self, rect):
sb = " (x="
sb += str(rect.origin_x) + " y=" + str(rect.origin_y)
sb += " length="
sb += str(rect.length) + " )"
return sb
if __name__ == '__main__':
unittest.main()
【问题讨论】:
您希望Rectangle.__len__
做什么?目前该方法只是返回自身,正如错误所说,len()
需要返回一个整数,但您正在返回一个方法
*** 鼓励为您的代码提供 Minimal, Reproducible Example 和错误信息。提供的代码不会导致错误(即您应该添加正在使用的类的示例)。
感谢 DarrylG 指出!
Phydeaux, Rectangle.__len__ 只是我忘记删除的废话,抱歉
@Gunners -- *** 鼓励最小的可重现示例。这是因为你拥有的代码越多,你从读者那里得到答案的可能性就越小。两个建议 1) 最小化代码(即不要包含说明问题所不需要的代码),以及 2) 代码应该适当地从 atted。
【参考方案1】:
主要问题:
方法区域使用时内部的方法需要一个矩形列表 在 testInsideRectBorderline1Y 等单元测试中使用内部方法时,需要一个矩形。 修改了内部方法,使其包含一个或多个矩形代码
文件矩形.py
class Rectangle():
def __init__(self, origin_x, origin_y, length, width):
self.origin_x = origin_x
self.origin_y = origin_y
self.length = length
self.width = width
def rect_values(self):
return self.origin_x, self.origin_y, self.length, self.width
文件 montecarlo.py
from random import random
class MonteCarlo:
def __init__(self, length, width, rectangles):
if None in (length, width, rectangles):
raise ValueError
self.rec_length = length
self.rec_width = width
self.rects = rectangles
def area(self, num_of_shots):
"""Method to estimate the area of the enclosing rectangle that is not covered by the embedded rectangles
"""
if isinstance(num_of_shots, type(None)):
raise ValueError
inside = 0
total = num_of_shots
for i in range(num_of_shots):
x = random() * self.rec_length
y = random() * self.rec_width
if self.inside(x, y, *self.rects): # Use list unpacking into arguments
# https://***.com/questions/7527849/how-to-extract-parameters-from-a-list-and-pass-them-to-a-function-call
inside += 1
area = (total - inside) / (total * self.rec_length * self.rec_width)
return area
def inside(self, x, y, *rects):
"""Method to determine if a given point (x,y) is inside one or more rectangles
"""
if None in (x, y, rects):
raise ValueError
for rect in rects:
origin_x, origin_y, length, width = rect.rect_values()
x_line = length+origin_x
y_line = width+origin_y
# Simplify conditionals and return boolean
if origin_x <= x <= x_line and origin_y <= y < y_line:
return True
return False
文件 main.py
import unittest
from montecarlo import MonteCarlo
from rectangle import Rectangle
class Point():
def __init__(self, x, y):
self.x = x
self.y = y
def get_x(self):
return self.x
def get_y(self):
return self.y
class TestAssignment01ex01Student(unittest.TestCase):
def testMCwith3rects(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rect2 = Rectangle(6.0, 3.0, 6.0, 4.0)
rect3 = Rectangle(10.0, 5.0, 4.0, 4.0)
rects = [rect1, rect2, rect3]
mc = MonteCarlo(15.0, 10.0, rects)
area = mc.area(1000000)
self.assertTrue((area >= 97.5 and area <= 98.5),
"MonteCarlo.area(1000000) with the enclosing rectangle 15.0x10.0 " +
"and the following embedded rectangles failed (area should be +/- 0.5 to the result 98 but your result is: " + str(
area) + " " + self.printRectanglesData(rects))
def testMCwith2Rects(self):
# area of enclosing rectangle is 50
# area of embedded rectangles is 2+12=14
# result is: 50-14=36
#
# embedded rectangle 1 is at position (0,0) with a size of 1x2
rect1 = Rectangle(0.0, 0.0, 1.0, 2.0)
# embedded rectangle 2 is at position (7,1) with a size of 3x4
rect2 = Rectangle(7.0, 1.0, 3.0, 4.0)
rects = [rect1, rect2]
mc = MonteCarlo(10.0, 5.0, rects)
area = mc.area(10000)
# for 10k random points the estimated area should already be close to correct result of 36
self.assertTrue((area > 30 and area < 40),
"MonteCarlo.area() according to the provided unit test failed! Area should be between 30 and 40 but was " + str(
area))
def testInsideRectBorderline1Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, 4.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
def testInsideRectBorderline2Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, 0.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
def testInsideRectBorderline3Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, 4.01)
self.assertFalse(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned True but should be False!")
def testInsideRectBorderline4Y(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(1.0, -0.01)
self.assertFalse(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned True but should be False!")
def testInsideRectBorderline1X(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(0.0, 3.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
def testInsideRectBorderline2X(self):
rect1 = Rectangle(0.0, 0.0, 4.0, 4.0)
rects = []
mc = MonteCarlo(15.0, 10.0, rects)
pt = Point(4.0, 3.0)
self.assertTrue(mc.inside(pt.get_x(), pt.get_y(), rect1),
"MonteCarlo.inside() with point (x=" + str(pt.get_x()) + "/y=" + str(
pt.get_y()) + ") and the rectangle "
+ self.printRectangleData(rect1) + " returned False but should be True!")
# /*************************************
# *
# * private methods
# *
# */
def printRectanglesData(self, rects):
i = 0
sb = ""
while i < len(rects):
sb += "\n Rectangle ".format(i + 1) + "(x="
sb += str(rects[i].origin_x) + " y=" + str(rects[i].origin_y)
sb += " length="
sb += str(rects[i].length) + " )"
i += 1
return sb
def printRectangleData(self, rect):
sb = " (x="
sb += str(rect.origin_x) + " y=" + str(rect.origin_y)
sb += " length="
sb += str(rect.length) + " )"
return sb
if __name__ == '__main__':
unittest.main()
# Note: use line below instead with Jupyter Notebook
# unittest.main(argv=['first-arg-is-ignored'], exit=False)
【讨论】:
以上是关于如何在蒙特卡洛积分中查找点x,y是不是在给定矩形内的主要内容,如果未能解决你的问题,请参考以下文章
C语言,给定一个矩形和一个点,判断这个点与矩形的位置关系(顶点 边 矩形内外),用函数形式并返回