Skip to content

Commit 048aa07

Browse files
authored
Merge pull request #74 from N3PDF/trace_option
Add a signature discovery and trace option
2 parents d79a18f + e2171e5 commit 048aa07

19 files changed

+363
-260
lines changed

doc/source/examples.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ by using the CFFI library as you can see in `this <https://github.com/N3PDF/vega
174174
# Now you can read up the compiled C code as a python library
175175
from _integrand_cffi import ffi, lib
176176
177-
def integrand(xarr, n_dim, **kwargs):
177+
def integrand(xarr, **kwargs):
178+
n_dim = xarr.shape[-1]
178179
result = np.empty(n_events, dtype=DTYPE.as_numpy_dtype)
179180
x_flat = xarr.numpy().flatten()
180181

doc/source/how_to.rst

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ using the ``tf.function`` decorator.
4444
4545
import tensorflow as tf
4646
47-
def example_integrand(xarr, n_dim=None, weight=None):
47+
def example_integrand(xarr, weight=None):
4848
s = tf.reduce_sum(xarr, axis=1)
4949
result = tf.pow(0.1/s, 2)
5050
return result
@@ -76,17 +76,16 @@ the integration algorithm).
7676
7777
import numpy as np
7878
79-
def example_integrand(xarr, n_dim=None, weight=None):
80-
s = np.pow(xarr, axis=1)
79+
def example_integrand(xarr, weight=None):
80+
s = np.sum(xarr, axis=1)
8181
result = np.square(0.1/s)
8282
return result
8383
8484
vegas_instance.compile(example_integrand, compilable=False)
8585
86-
87-
.. note:: Integrands must accept the keyword arguments ``n_dim`` and ``weight``, as the integrators
88-
will try to pass those argument when convenient. It is however possible to construct integrands
89-
that accept only the array of random number ``xarr``, see :ref:`simple-label`
86+
.. note:: Integrands must always accept as first argument the random number (``xarr``)
87+
and can also accept the keyword argument ``weight``. The ``compile`` method of the integration
88+
will try to find the most adequate signature in each situation.
9089

9190

9291
It is also possible to completely avoid compilation,
@@ -112,7 +111,7 @@ These functions are wrappers around ``tf.cast`` `🔗 <https://www.tensorflow.or
112111
113112
constant = float_me(0.1)
114113
115-
def example_integrand(xarr, n_dim=None, weight=None):
114+
def example_integrand(xarr, weight=None):
116115
s = tf.reduce_sum(xarr, axis=1)
117116
result = tf.pow(constant/s, 2)
118117
return result
@@ -141,42 +140,6 @@ The full list of integration algorithms and wrappers can be consulted at: :ref:`
141140
Tips and Tricks
142141
===============
143142

144-
.. _simple-label:
145-
146-
Improving results by simplifying the integrand
147-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
148-
149-
In the above example the integrand receives the keyword arguments `n_dim` and `xjac`.
150-
Although these are useful for instance for filling histograms or dimensional-dependent integrands,
151-
these extra argument can harm the performance of the integration when they are not being used.
152-
153-
It is possible to instantiate ``VegasFlow`` algorithms with ``simplify_signature``.
154-
In this case the integrand will only receive the array of random numbers and, in exchange for this
155-
loss of flexibility, the function will be retraced less often.
156-
For more details in what function retracing entails we direct you to the `TensorFlow documentation <https://www.tensorflow.org/api_docs/python/tf/function>`_.
157-
158-
.. code-block:: python
159-
160-
from vegasflow import VegasFlow, float_me
161-
import tensorflow as tf
162-
163-
def example_integrand(xarr):
164-
c = float_me(0.1)
165-
s = tf.reduce_sum(xarr)
166-
result = tf.pow(c/s)
167-
return result
168-
169-
dimensions = 3
170-
n_calls = int(1e7)
171-
# Create an instance of the VegasFlow class
172-
vegas_instance = VegasFlow(dimensions, n_calls, simplify_signature = True)
173-
# Compile the function to be integrated
174-
vegas_instance.compile(example_integrand)
175-
# Compute the result after a number of iterations
176-
n_iter = 5
177-
result = vegas_instance.run_integration(n_iter)
178-
179-
180143
Seeding the random number generator
181144
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
182145

@@ -396,7 +359,7 @@ This is a crucial step (and the only fixed step) as this tensor will be accumula
396359
cummulator_tensor.assign(new_histograms)
397360
398361
@tf.function
399-
def integrand_example(xarr, n_dim=None, weight=fone):
362+
def integrand_example(xarr, weight=fone):
400363
# some complicated calculation that generates
401364
# a final_result and some histogram values:
402365
final_result = tf.constant(42, dtype=tf.float64)

doc/source/intalg.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,10 @@ Once that is generated it is possible to register an integrand by calling the ``
3535
.. code-block:: python
3636
3737
def example_integrand(x, **kwargs):
38-
return x
38+
y = 0.0
39+
for d in range(dims):
40+
y += x[:,d]
41+
return y
3942
4043
vegas_instance.compile(example_integrand)
4144
@@ -44,6 +47,7 @@ After each iteration the grid will be refined, producing more points (and hence
4447

4548
.. code-block:: python
4649
50+
n_iter = 3
4751
result = vegas_instance.run_integration(n_iter)
4852
4953
The output variable, in this example named ``result``, is a tuple variable where the first element is the result of the integration while the second element is the error of the integration.
@@ -103,7 +107,7 @@ The usage pattern is similar to :ref:`vegas-label`.
103107
.. code-block:: python
104108
105109
from vegasflow import PlainFlow
106-
plain_instance = PlainFlow(dimensions, ncalls)
110+
plain_instance = PlainFlow(dims, n_calls)
107111
plain_instance.compile(example_integrand)
108112
plain_instance.run_integration(n_iter)
109113

examples/asian_options_tf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030

3131
@tf.function
32-
def example_integrand(xarr, n_dim=None, **kwargs):
32+
def example_integrand(xarr, **kwargs):
3333
"""Asian options test function"""
3434
sum1 = tf.reduce_sum(ndtri(xarr), axis=1)
3535
a = S0 * tf.exp((r-sigma2/2) + sigma*sqrtdt*sum1)

examples/basic_example.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
Example: basic integration
33
4-
Very basic example with a simple integrand, uses simplify_signature
4+
Very basic example with a simple integrand
55
"""
66

77
from vegasflow import VegasFlow, float_me, run_eager
@@ -32,8 +32,11 @@ def symgauss(xarr):
3232
"""Testing several different integrations"""
3333
print(f"VEGAS MC, ncalls={ncalls}:")
3434
start = time.time()
35-
vegas_instance = VegasFlow(dim, ncalls, simplify_signature=True, events_limit=int(7e4))
35+
vegas_instance = VegasFlow(dim, ncalls, events_limit=int(7e4))
3636
vegas_instance.compile(symgauss)
3737
result = vegas_instance.run_integration(n_iter)
3838
end = time.time()
3939
print(f"Vegas took: time (s): {end-start}")
40+
print("Change the number of events and freeze the grid...")
41+
vegas_instance.freeze_grid()
42+
vegas_instance.run_integration(n_iter)

examples/drellyan_lo_tf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ def build_luminosity(x1, x2):
240240

241241

242242
@tf.function
243-
def drellyan(xarr, **kwargs):
243+
def drellyan(xarr, weight=None, **kwargs):
244244
"""Single-top (t-channel) at LO"""
245245
psw, flux, p0, p1, p2, p3, x1, x2 = make_event(xarr)
246246
wgts = evaluate_matrix_element_square(p0, p1, p2, p3)

examples/example_eager.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,9 @@
2020

2121

2222
@tf.function
23-
def symgauss_sigmoid(xarr, n_dim=None, **kwargs):
23+
def symgauss_sigmoid(xarr, **kwargs):
2424
"""symgauss test function"""
25-
if n_dim is None:
26-
n_dim = xarr.shape[-1]
25+
n_dim = xarr.shape[-1]
2726
a = 0.1
2827
pref = pow(1.0 / a / np.sqrt(np.pi), n_dim)
2928
coef = np.sum(np.arange(1, 101))

examples/example_pineappl.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import random as rn
44
from multiprocessing.pool import ThreadPool as Pool
55
from functools import partial
6+
from vegasflow.configflow import DTYPE, MAX_EVENTS_LIMIT, run_eager
7+
run_eager(True)
68
from pdfflow.pflow import mkPDF
79
import pineappl
810
from vegasflow.utils import generate_condition_function
911
from vegasflow.vflow import VegasFlow
10-
from vegasflow.configflow import DTYPE, MAX_EVENTS_LIMIT
1112
import time
1213
import numpy as np
1314
import tensorflow as tf
14-
tf.config.run_functions_eagerly(True)
1515

1616

1717
parser = argparse.ArgumentParser()
@@ -82,7 +82,7 @@ def fill(grid, x1, x2, q2, yll, weight):
8282
grid.fill_array(x1, x2, q2, zeros, yll, zeros, weight)
8383

8484

85-
def fill_grid(xarr, n_dim=None, **kwargs):
85+
def fill_grid(xarr, weight=1, **kwargs):
8686
s, t, u, x1, x2, jacobian = hadronic_pspgen(xarr, 10.0, 7000.0)
8787

8888
ptl = tf.sqrt((t * u / s))
@@ -102,18 +102,18 @@ def fill_grid(xarr, n_dim=None, **kwargs):
102102
t_6 = mll <= 120.0
103103
full_mask, indices = cuts(t_1, t_2, t_3, t_4, t_5, t_6)
104104

105-
weight = tf.boolean_mask(jacobian * int_photo(s, u, t), full_mask, axis=0)
105+
wgt = tf.boolean_mask(jacobian * int_photo(s, u, t), full_mask, axis=0)
106106
x1 = tf.boolean_mask(x1, full_mask, axis=0)
107107
x2 = tf.boolean_mask(x2, full_mask, axis=0)
108108
yll = tf.boolean_mask(yll, full_mask, axis=0)
109-
vweight = weight * tf.boolean_mask(kwargs.get('weight'), full_mask, axis=0)
109+
vweight = wgt * tf.boolean_mask(weight, full_mask, axis=0)
110110

111111
if kwargs.get('fill_pineappl'):
112112
q2 = 90.0 * 90.0 * tf.ones(weight.shape, dtype=tf.float64)
113113
kwargs.get('pool').apply_async(fill, [kwargs.get('grid'), x1.numpy(), x2.numpy(),
114114
q2.numpy(), tf.abs(yll).numpy(), vweight.numpy()])
115115

116-
return tf.scatter_nd(indices, weight, shape=xarr.shape[0:1])
116+
return tf.scatter_nd(indices, wgt, shape=xarr.shape[0:1])
117117

118118

119119
if __name__ == "__main__":

examples/histogram_ex.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,41 +19,34 @@
1919

2020

2121
def generate_integrand(cummulator_tensor):
22-
"""
22+
"""
2323
This function will generate an integrand function
2424
which will already hold a reference to the tensor to accumulate
2525
"""
2626

2727
@tf.function
2828
def histogram_collector(results, variables):
29-
""" This function will receive a tensor (result)
30-
and the variables corresponding to those integrand results
31-
In the example integrand below, these corresponds to
29+
"""This function will receive a tensor (result)
30+
and the variables corresponding to those integrand results
31+
In the example integrand below, these corresponds to
3232
`final_result` and `histogram_values` respectively.
3333
`current_histograms` instead is the current value of the histogram
34-
which will be overwritten """
34+
which will be overwritten"""
3535
# Fill a histogram with HISTO_BINS (2) bins, (0 to 0.5, 0.5 to 1)
3636
# First generate the indices with TF
37-
indices = tf.histogram_fixed_width_bins(
38-
variables, [fzero, fone], nbins=HISTO_BINS
39-
)
37+
indices = tf.histogram_fixed_width_bins(variables, [fzero, fone], nbins=HISTO_BINS)
4038
t_indices = tf.transpose(indices)
4139
# Then consume the results with the utility we provide
4240
partial_hist = consume_array_into_indices(results, t_indices, HISTO_BINS)
4341
# Then update the results of current_histograms
4442
new_histograms = partial_hist + current_histograms
4543
cummulator_tensor.assign(new_histograms)
4644

47-
def integrand_example(xarr, n_dim=None, weight=fone):
48-
""" Example of function which saves histograms """
49-
if n_dim is None:
50-
n_dim = xarr.shape[-1]
51-
if n_dim < hst_dim:
52-
raise ValueError(
53-
f"The number of dimensions has to be greater than {hst_dim} for this example"
54-
)
45+
def integrand_example(xarr, weight=fone):
46+
"""Example of function which saves histograms"""
47+
n_dim = xarr.shape[-1]
5548
a = tf.constant(0.1, dtype=DTYPE)
56-
n100 = tf.cast(100 * n_dim, dtype=DTYPE)
49+
n100 = tf.cast(100 * dim, dtype=DTYPE)
5750
pref = tf.pow(1.0 / a / np.sqrt(np.pi), n_dim)
5851
coef = tf.reduce_sum(tf.range(n100 + 1))
5952
coef += tf.reduce_sum(tf.square((xarr - 1.0 / 2.0) / a), axis=1)
@@ -69,6 +62,10 @@ def integrand_example(xarr, n_dim=None, weight=fone):
6962

7063
if __name__ == "__main__":
7164
"""Testing histogram generation"""
65+
if dim < hst_dim:
66+
raise ValueError(
67+
f"The number of dimensions has to be greater than {hst_dim} for this example"
68+
)
7269
print(f"Plain MC, ncalls={ncalls}:")
7370
start = time.time()
7471
# First we create the tensor in which to accumulate the histogra

examples/simgauss_cffi.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@
4949

5050
from _symgauss_cffi import ffi, lib
5151

52-
def symgauss(xarr, n_dim=None, **kwargs):
53-
if n_dim is None:
54-
n_dim = xarr.shape[-1]
52+
def symgauss(xarr, **kwargs):
53+
n_dim = xarr.shape[-1]
5554
n_events = xarr.shape[0]
5655

5756
res = np.empty(n_events, dtype = DTYPE.as_numpy_dtype)

0 commit comments

Comments
 (0)