def backward(self): grad_pos, grad_vel = self.grad_out() # Run for 100 iterations it = m.UInt32(100) loop = m.Loop(it, grad_pos, grad_vel) n = ek.width(grad_pos) while loop.cond(it > 0): # Retrieve loop variables, reverse chronological order it -= 1 index = it * n + ek.arange(m.UInt32, n) pos = ek.gather(m.Array2f, self.temp_pos, index) vel = ek.gather(m.Array2f, self.temp_vel, index) # Differentiate loop body in reverse mode ek.enable_grad(pos, vel) pos_out, vel_out = self.timestep(pos, vel) ek.set_grad(pos_out, grad_pos) ek.set_grad(vel_out, grad_vel) ek.enqueue(pos_out, vel_out) ek.traverse(m.Float, reverse=True) # Update loop variables grad_pos.assign(ek.grad(pos)) grad_vel.assign(ek.grad(vel)) self.set_grad_in('pos', grad_pos) self.set_grad_in('vel', grad_vel)
def ravel(buf, dim=3): idx = dim * UInt32.arange(ek.slices(buf) // dim) if dim == 2: return Vector2f(ek.gather(buf, idx), ek.gather(buf, idx + 1)) elif dim == 3: return Vector3f(ek.gather(buf, idx), ek.gather(buf, idx + 1), ek.gather(buf, idx + 2))
def test19_gather_fwd(m): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) ek.forward(x) ref = [-1.55556, -1.55556, -1.11111, -0.666667] assert ek.allclose(ek.grad(y), ref)
def gather_(cls, source, index, mask, permute): assert source.Depth == 1 sr = max(len(index), len(mask)) result = cls.empty_(sr if cls.Size == Dynamic else 0) for i in range(sr): result[i] = _ek.gather(cls.Value, source, index[i], mask[i], permute) return result
def test16_custom(cname): t = get_class(cname) v1 = ek.zero(t, 100) v2 = ek.empty(t, 100) assert len(v1.state) == 100 assert len(v2.inc) == 100 v2.state = v1.state v1.state = ek.arange(type(v1.state), 100) v3 = ek.select(v1.state < 10, v1, v2) assert v3.state[3] == 3 assert v3.state[11] == 0 assert ek.width(v3) == 100 v4 = ek.zero(t, 1) ek.schedule(v4) ek.resize(v4, 200) assert ek.width(v4) == 200 assert ek.width(v3) == 100 v4 = ek.zero(t, 1) ek.resize(v4, 200) assert ek.width(v4) == 200 index = ek.arange(type(v1.state), 100) ek.scatter(v4, v1, index) v5 = ek.gather(t, v4, index) ek.eval(v5) assert v5.state == v1.state and v5.inc == v1.inc
def test12_binary_search(cname): t = get_class(cname) import numpy as np data_np = np.float32(np.sort(np.random.normal(size=10000))) search_np = np.float32(np.random.normal(size=10000)) data = t(data_np) search = t(search_np) index = ek.binary_search(0, len(data) - 1, lambda index: ek.gather(t, data, index) < search) value = ek.gather(t, data, index) cond = ek.eq(index, len(data) - 1) | (value >= search) assert ek.all(cond)
def test18_gather(m): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) z = ek.hsum_async(y) ek.backward(z) ref = [0, -1.55556 * 2, -1.11111, -0.666667, 0, 0, 0, 0, 0, 0] assert ek.allclose(ek.grad(x), ref)
def test50_gather_fwd_eager(m): with EagerMode(): x = ek.linspace(m.Float, -1, 1, 10) ek.enable_grad(x) ek.set_grad(x, 1) y = ek.gather(m.Float, x * x, m.UInt(1, 1, 2, 3)) ref = [-1.55556, -1.55556, -1.11111, -0.666667] assert ek.allclose(ek.grad(y), ref)
def test07_gather_ravel_unravel(pkg): get_class(pkg.__name__) str_1 = '[[0.0, 1.0, 2.0],\n [3.0, 4.0, 5.0],\n [6.0, 7.0, 8.0],\n' \ ' [9.0, 10.0, 11.0]]' str_2 = '[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0]' a = ek.arange(pkg.Float, 100) b = ek.gather(pkg.Array3f, a, pkg.UInt(0, 1, 2, 3)) assert repr(b) == str_1 c = ek.ravel(b) assert repr(c) == str_2 d = ek.unravel(pkg.Array3f, c) assert repr(d) == str_1
def test06_discr_bruteforce(variant_packet_rgb): # Brute force validation of discrete distribution sampling from mitsuba.core import DiscreteDistribution, Float, PCG32, UInt64 rng = PCG32(initseq=UInt64.arange(50)) for size in range(2, 20): for i in range(2, 50): density = Float(rng.next_uint32_bounded(i)[0:size]) if ek.hsum(density) == 0: continue ddistr = DiscreteDistribution(density) x = ek.linspace(Float, 0, 1, 20) y = ddistr.sample(x) z = ek.gather(ddistr.cdf(), y - 1, y > 0) x *= ddistr.sum() # Did we sample the right interval? assert ek.all((x > z) | (ek.eq(x, 0) & (x >= z)))
def _render_helper(scene, spp=None, sensor_index=0): """ Internally used function: render the specified Mitsuba scene and return a floating point array containing RGB values and AOVs, if applicable """ from mitsuba.core import (Float, UInt32, UInt64, Vector2f, is_monochromatic, is_rgb, is_polarized) from mitsuba.render import ImageBlock sensor = scene.sensors()[sensor_index] film = sensor.film() sampler = sensor.sampler() film_size = film.crop_size() if spp is None: spp = sampler.sample_count() total_sample_count = ek.hprod(film_size) * spp if sampler.wavefront_size() != total_sample_count: sampler.seed(ek.arange(UInt64, total_sample_count)) pos = ek.arange(UInt32, total_sample_count) pos //= spp scale = Vector2f(1.0 / film_size[0], 1.0 / film_size[1]) pos = Vector2f(Float(pos % int(film_size[0])), Float(pos // int(film_size[0]))) pos += sampler.next_2d() rays, weights = sensor.sample_ray_differential( time=0, sample1=sampler.next_1d(), sample2=pos * scale, sample3=0 ) spec, mask, aovs = scene.integrator().sample(scene, sampler, rays) spec *= weights del mask if is_polarized: from mitsuba.core import depolarize spec = depolarize(spec) if is_monochromatic: rgb = [spec[0]] elif is_rgb: rgb = spec else: from mitsuba.core import spectrum_to_xyz, xyz_to_srgb xyz = spectrum_to_xyz(spec, rays.wavelengths) rgb = xyz_to_srgb(xyz) del xyz aovs.insert(0, Float(1.0)) for i in range(len(rgb)): aovs.insert(i + 1, rgb[i]) del rgb, spec, weights, rays block = ImageBlock( size=film.crop_size(), channel_count=len(aovs), filter=film.reconstruction_filter(), warn_negative=False, warn_invalid=False, border=False ) block.clear() block.put(pos, aovs) del pos del aovs data = block.data() ch = block.channel_count() i = UInt32.arange(ek.hprod(block.size()) * (ch - 1)) weight_idx = i // (ch - 1) * ch values_idx = (i * ch) // (ch - 1) + 1 weight = ek.gather(data, weight_idx) values = ek.gather(data, values_idx) return values / (weight + 1e-8)
def run(self, significance_level=0.01, test_count=1, quiet=False): """ Run the Chi^2 test Parameter ``significance_level`` (float): Denotes the desired significance level (e.g. 0.01 for a test at the 1% significance level) Parameter ``test_count`` (int): Specifies the total number of statistical tests run by the user. This value will be used to adjust the provided significance level so that the combination of the entire set of tests has the provided significance level. Returns → bool: ``True`` upon success, ``False`` if the null hypothesis was rejected. """ from mitsuba.core import UInt32, Float64 from mitsuba.core.math import chi2 from mitsuba.python.math import rlgamma if self.histogram is None: self.tabulate_histogram() if self.pdf is None: self.tabulate_pdf() index = UInt32( [i[0] for i in sorted(enumerate(self.pdf), key=lambda x: x[1])]) # Sort entries by expected frequency (increasing) pdf = Float64(ek.gather(self.pdf, index)) histogram = Float64(ek.gather(self.histogram, index)) # Compute chi^2 statistic and pool low-valued cells chi2val, dof, pooled_in, pooled_out = \ chi2(histogram, pdf, 5) if dof < 1: self._log('Failure: The number of degrees of freedom is too low!') self.fail = True if ek.any(ek.eq(pdf, 0) & ek.neq(histogram, 0)): self._log('Failure: Found samples in a cell with expected ' 'frequency 0. Rejecting the null hypothesis!') self.fail = True if pooled_in > 0: self._log('Pooled %i low-valued cells into %i cells to ' 'ensure sufficiently high expected cell frequencies' % (pooled_in, pooled_out)) pdf_time = (self.pdf_end - self.pdf_start) * 1000 histogram_time = (self.histogram_end - self.histogram_start) * 1000 self._log('Histogram sum = %f (%.2f ms), PDF sum = %f (%.2f ms)' % (self.histogram_sum, histogram_time, self.pdf_sum, pdf_time)) self._log('Chi^2 statistic = %f (d.o.f = %i)' % (chi2val, dof)) # Probability of observing a test statistic at least as # extreme as the one here assuming that the distributions match self.p_value = 1 - rlgamma(dof / 2, chi2val / 2) # Apply the Šidák correction term, since we'll be conducting multiple # independent hypothesis tests. This accounts for the fact that the # probability of a failure increases quickly when several hypothesis # tests are run in sequence. significance_level = 1.0 - \ (1.0 - significance_level) ** (1.0 / test_count) if self.fail: self._log('Not running the test for reasons listed above. Target ' 'density and histogram were written to "chi2_data.py') result = False elif self.p_value < significance_level \ or not ek.isfinite(self.p_value): self._log('***** Rejected ***** the null hypothesis (p-value = %f,' ' significance level = %f). Target density and histogram' ' were written to "chi2_data.py".' % (self.p_value, significance_level)) result = False else: self._log('Accepted the null hypothesis (p-value = %f, ' 'significance level = %f)' % (self.p_value, significance_level)) result = True if not quiet: print(self.messages) if not result: self._dump_tables() return result