Skip to content

Commit

Permalink
Reduce number of warnings emitted during testing (#2887)
Browse files Browse the repository at this point in the history
A collection of minor fixes and updates improves the handling of warnings by updating tests to use new interfaces.
The original distribution of warnings when running 4 test jobs was 7299 emitted warnings in 211 locations:
5 DeprecationWarning
9 FutureWarning
1 MatplotlibDeprecationWarning
4 PendingDeprecationWarning
12 PNLCompilerWarning
2 PytestBenchmarkWarning
1 PytestRemovedIn8Warning
1 PytestReturnNotNoneWarning
4 RuntimeWarning
1 SyntaxWarning
171 UserWarning

Changes in this PR reduce this to 5696 emitted warnings in 191 locations:
2 FutureWarning
1 MatplotlibDeprecationWarning
4 PendingDeprecationWarning
12 PNLCompilerWarning
2 RuntimeWarning
170 UserWarning

Individual commits target different warning classes.
  • Loading branch information
jvesely authored Jan 25, 2024
2 parents f9705ca + b453f72 commit 26f6b64
Show file tree
Hide file tree
Showing 15 changed files with 104 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,8 @@ def _function(self,
elif operation == CROSS_ENTROPY:
v1 = variable[0]
v2 = variable[1]
combination = np.where(np.logical_and(v1 == 0, v2 == 0), 0.0, v1 * np.log(v2))
both_zero = np.logical_and(v1 == 0, v2 == 0)
combination = v1 * np.where(both_zero, 0.0, np.log(v2, where=np.logical_not(both_zero)))
else:
raise FunctionError("Unrecognized operator ({0}) for LinearCombination function".
format(operation.self.Operation.SUM))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,8 @@ def _function(self,
# MODIFIED CW 3/20/18: avoid divide by zero error by plugging in two zeros
# FIX: unsure about desired behavior when v2 = 0 and v1 != 0
# JDC: returns [inf]; leave, and let it generate a warning or error message for user
result = -np.sum(np.where(np.logical_and(v1 == 0, v2 == 0), 0.0, v1 * np.log(v2)))
both_zero = np.logical_and(v1 == 0, v2 == 0)
result = -np.sum(v1 * np.where(both_zero, 0.0, np.log(v2, where=np.logical_not(both_zero))))

# Energy
elif self.metric == ENERGY:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ def reset(self, previous_value=None, context=None):
if previous_value is None:
previous_value = self._get_current_parameter_value("initializer", context)

if previous_value is None or previous_value == []:
if previous_value is None or np.asarray(previous_value).size == 0:
self.parameters.previous_value._get(context).clear()
value = deque([], maxlen=self.parameters.history.get(context))

Expand Down Expand Up @@ -1752,7 +1752,7 @@ def _get_distance(self, cue:Union[list, np.ndarray],
field_weights = self._get_current_parameter_value('distance_field_weights', context)
# Set any items in field_weights to None if they are None or an empty list:
field_weights = np.atleast_1d([None if
fw is None or fw == [] or isinstance(fw, np.ndarray) and fw.tolist()==[]
fw is None or np.asarray(fw).size == 0
else fw
for fw in field_weights])
if granularity == 'per_field':
Expand All @@ -1763,7 +1763,7 @@ def _get_distance(self, cue:Union[list, np.ndarray],
if len(field_weights)==1:
field_weights = np.full(num_fields, field_weights[0])
for i in range(num_fields):
if not any([item is None or item == [] or isinstance(item, np.ndarray) and item.tolist() == []
if not any([item is None or np.asarray(item).size == 0
for item in [cue[i], candidate[i], field_weights[i]]]):
distances_by_field[i] = distance_fct([cue[i], candidate[i]]) * field_weights[i]
return list(distances_by_field)
Expand Down Expand Up @@ -2623,7 +2623,7 @@ def reset(self, previous_value=None, context=None):
if previous_value is None:
previous_value = self._get_current_parameter_value("initializer", context)

if previous_value == []:
if np.asarray(previous_value).size == 0:
value = np.ndarray(shape=(2, 0, len(self.defaults.variable[0])))
self.parameters.previous_value._set(copy.deepcopy(value), context)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@
**noise** (it must be the same length as the Mechanism's `variable <Mechanism_Base.variable>`), in which case each
element is applied Hadamard (elementwise) to the result, as shown here::
>>> my_linear_tm.noise = [1.0,1.2,.9]
>>> my_linear_tm.noise.base = [1.0,1.2,.9]
>>> my_linear_tm.execute([1.0, 1.0, 1.0])
array([[2. , 2.2, 1.9]])
Expand Down
2 changes: 1 addition & 1 deletion psyneulink/core/components/ports/port.py
Original file line number Diff line number Diff line change
Expand Up @@ -3002,7 +3002,7 @@ def _parse_port_spec(port_type=None,
port_type_name = port_type.__name__

proj_is_feedback = False
if isinstance(port_specification, tuple) and port_specification[1] == FEEDBACK:
if isinstance(port_specification, tuple) and str(port_specification[1]) == FEEDBACK:
port_specification = port_specification[0]
proj_is_feedback = True

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ required_plugins = pytest-benchmark pytest-cov pytest-helpers-namespace pytest-p
xfail_strict = True

filterwarnings =
error::SyntaxWarning
error:Creating an ndarray from ragged nested sequences \(which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes\) is deprecated.*:numpy.VisibleDeprecationWarning
error:Invalid escape sequence
ignore:Multiple ParameterPorts:UserWarning

[pycodestyle]
# for code explanation see https://pep8.readthedocs.io/en/latest/intro.html#error-codes
Expand Down
58 changes: 36 additions & 22 deletions tests/composition/test_composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -1185,19 +1185,22 @@ def test_add_processing_pathway_subset_duplicate_warning(self, verbosity):
C = TransferMechanism()
comp = Composition()

comp.add_linear_processing_pathway(pathway=[A,B,C])
comp.add_linear_processing_pathway(pathway=[A, B, C])
comp.verbosePref = PreferenceEntry(verbosity, PreferenceLevel.INSTANCE)

with warnings.catch_warnings(record=True) as msgs:
comp.add_linear_processing_pathway(pathway=[A, B])

# Test for warning if verbosePref is set to True
if verbosity:
regexp = f"Pathway specified in 'pathway' arg for add_linear_processing_pathway method of '{comp.name}' " \
f"has a subset of nodes in a Pathway already in '{comp.name}': Pathway-0; the latter will be used."
with pytest.warns(UserWarning, match=regexp):
comp.verbosePref = PreferenceEntry(True, PreferenceLevel.INSTANCE)
comp.add_linear_processing_pathway(pathway=[A,B])
# Test for warning if verbosePref is set to True
warning = f"Pathway specified in 'pathway' arg for add_linear_processing_pathway method of '{comp.name}' " \
f"has a subset of nodes in a Pathway already in '{comp.name}': Pathway-0; the latter will be used."

# The above issues 2 warnings, but we only test for one of them here
assert any(str(m.message) == warning for m in msgs), list(str(m.message) for m in msgs)
else:
# Test for suppression of warning if verbosePref not set
with pytest.warns(None):
comp.add_linear_processing_pathway(pathway=[A,B])
# Test for suppression of warning if verbosePref is not set
assert len(msgs) == 0

def test_add_backpropagation_pathway_exact_duplicate_warning(self):
A = TransferMechanism()
Expand Down Expand Up @@ -1230,19 +1233,24 @@ def test_add_backpropagation_pathway_contiguous_subset_duplicate_warning(self, v
B = TransferMechanism()
C = TransferMechanism()
comp = Composition()
comp.add_backpropagation_learning_pathway(pathway=[A,B,C])
comp.add_backpropagation_learning_pathway(pathway=[A, B, C])

comp.verbosePref = PreferenceEntry(verbosity, PreferenceLevel.INSTANCE)

with warnings.catch_warnings(record=True) as msgs:
comp.add_backpropagation_learning_pathway(pathway=[A, B])

# Test for warning if verbosePref is set to True
if verbosity:
regexp = f"Pathway specified in 'pathway' arg for add_backpropagation_learning_pathway method of '{comp.name}'" \
f" has a subset of nodes in a Pathway already in '{comp.name}':.*; the latter will be used."
with pytest.warns(UserWarning, match=regexp):
comp.verbosePref = PreferenceEntry(True, PreferenceLevel.INSTANCE)
comp.add_backpropagation_learning_pathway(pathway=[A,B])
# Test for warning if verbosePref is set to True
warning = f"Pathway specified in 'pathway' arg for add_backpropagation_learning_pathway method of '{comp.name}'" \
f" has a subset of nodes in a Pathway already in '{comp.name}': Pathway-0; the latter will be used."

# The above issues 2 warnings, but we only test for one of them here
assert any(str(m.message) == warning for m in msgs), list(str(m.message) for m in msgs)
else:
# Test for suppression of warning if verbosePref is not set
with pytest.warns(None):
comp.add_backpropagation_learning_pathway(pathway=[A,B])
assert len(msgs) == 0


def test_add_processing_pathway_non_contiguous_subset_is_OK(self):
A = TransferMechanism()
Expand Down Expand Up @@ -3833,7 +3841,10 @@ def test_execute_no_inputs(self, mode):
inner_comp = Composition(pathways=[m_inner])
m_outer = ProcessingMechanism(size=2)
outer_comp = Composition(pathways=[m_outer, inner_comp])
result = outer_comp.run(execution_mode=mode)

with pytest.warns(UserWarning, match="No inputs provided in call"):
result = outer_comp.run(execution_mode=mode)

np.testing.assert_allclose(result, [[0.0, 0.0]])

@pytest.mark.composition
Expand All @@ -3842,7 +3853,10 @@ def test_run_no_inputs(self, comp_mode):
inner_comp = Composition(pathways=[m_inner])
m_outer = ProcessingMechanism(size=2)
outer_comp = Composition(pathways=[m_outer, inner_comp])
result = outer_comp.run(execution_mode=comp_mode)

with pytest.warns(UserWarning, match="No inputs provided in call"):
result = outer_comp.run(execution_mode=comp_mode)

np.testing.assert_allclose(result, [[0.0, 0.0]])

def test_lpp_invalid_matrix_keyword(self):
Expand Down Expand Up @@ -4922,7 +4936,7 @@ def test_invalid_projection_deletion_when_nesting_comps(self):
allocation_samples=pnl.SampleSpec(start=1.0, stop=5.0, num=5))])
)
assert not ocomp._check_for_existing_projections(sender=ib, receiver=ocomp_objective_mechanism)
return ocomp

# # Does not work yet due to initialize_cycle_values bug that causes first recurrent projection to pass different values
# # to TranfserMechanism version vs Logistic fn + AdaptiveIntegrator fn version
# def test_recurrent_transfer_mechanism_composition(self):
Expand Down
37 changes: 16 additions & 21 deletions tests/composition/test_control.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import contextlib
import re

import numpy as np
import pytest

Expand Down Expand Up @@ -3587,27 +3587,27 @@ def test_model_based_num_estimates(self, num_estimates, rand_var):
intensity_cost_function=pnl.Linear(slope=0.))

objective_mech = pnl.ObjectiveMechanism(monitor=[B])
warning_type = None
warning_msg = f"'OptimizationControlMechanism-0' has 'num_estimates = {num_estimates}' specified, " \
f"but its 'agent_rep' \\('comp'\\) has no random variables: " \
f"'RANDOMIZATION_CONTROL_SIGNAL' will not be created, and num_estimates set to None."

if num_estimates and not rand_var:
warning_type = UserWarning
warning_msg = f'"\'OptimizationControlMechanism-0\' has \'num_estimates = {num_estimates}\' specified, ' \
f'but its \'agent_rep\' (\'comp\') has no random variables: ' \
f'\'RANDOMIZATION_CONTROL_SIGNAL\' will not be created, and num_estimates set to None."'
with pytest.warns(warning_type) as warnings:
warning_context = pytest.warns(UserWarning, match=warning_msg)
else:
warning_context = contextlib.nullcontext()

with warning_context:
ocm = pnl.OptimizationControlMechanism(agent_rep=comp,
state_features=[A.input_port],
objective_mechanism=objective_mech,
function=pnl.GridSearch(),
num_estimates=num_estimates,
control_signals=[control_signal])
if warning_type:
assert any(warning_msg == repr(w.message.args[0]) for w in warnings)

comp.add_controller(ocm)
inputs = {A: [[[1.0]]]}

comp.run(inputs=inputs,
num_trials=2)
comp.run(inputs=inputs, num_trials=2)

if not num_estimates or not rand_var:
assert pnl.RANDOMIZATION_CONTROL_SIGNAL not in comp.controller.control_signals # Confirm no estimates
Expand Down Expand Up @@ -3710,22 +3710,17 @@ def test_grid_search_random_selection(self, comp_mode, benchmark):

inputs = {A: [[[1.0]]]}

comp.run(inputs=inputs, num_trials=10, context='outer_comp', execution_mode=comp_mode)
np.testing.assert_allclose(comp.results, [[[0.7310585786300049]], [[0.999999694097773]], [[0.999999694097773]], [[0.9999999979388463]], [[0.9999999979388463]], [[0.999999694097773]], [[0.9999999979388463]], [[0.999999999986112]], [[0.999999694097773]], [[0.9999999999999993]]])
benchmark(comp.run, inputs=inputs, num_trials=10, context='outer_comp', execution_mode=comp_mode)
np.testing.assert_allclose(comp.results[:10],
[[[0.7310585786300049]], [[0.999999694097773]], [[0.999999694097773]], [[0.9999999979388463]], [[0.9999999979388463]],
[[0.999999694097773]], [[0.9999999979388463]], [[0.999999999986112]], [[0.999999694097773]], [[0.9999999999999993]]])

# control signal value (mod slope) is chosen randomly from all of the control signal values
# that correspond to a net outcome of 1
if comp_mode is pnl.ExecutionMode.Python:
log_arr = A.log.nparray_dictionary()
np.testing.assert_allclose([[1.], [15.], [15.], [20.], [20.], [15.], [20.], [25.], [15.], [35.]],
log_arr['outer_comp']['mod_slope'])

if benchmark.enabled:
# Disable logging for the benchmark run
A.log.set_log_conditions(items="mod_slope", log_condition=LogCondition.OFF)
A.log.clear_entries()
benchmark(comp.run, inputs=inputs, num_trials=10, context='bench_outer_comp', execution_mode=comp_mode)
assert len(A.log.get_logged_entries()) == 0
log_arr['outer_comp']['mod_slope'][:10])


def test_input_CIM_assignment(self, comp_mode):
Expand Down
26 changes: 10 additions & 16 deletions tests/composition/test_learning.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ def xor_network():
matrix=np.full((10,1), 0.1),
sender=hidden_layer,
receiver=output_layer)
inputs = np.array([[0, 0],[0, 1],[1, 0],[1, 1]])
targets = np.array([[0],[1],[1],[0]])
inputs = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
targets = np.array([[0], [1], [1], [0]])

def _get_comp_type(comp_type, comp_learning_rate, pathway_learning_rate):
if comp_type == 'composition':
xor = Composition(learning_rate=comp_learning_rate)
Expand Down Expand Up @@ -65,18 +66,15 @@ def _get_comp_type(comp_type, comp_learning_rate, pathway_learning_rate):
class TestInputAndTargetSpecs:

@pytest.mark.pytorch
@pytest.mark.parametrize('input_type', ['dict', 'func', 'gen', 'gen_func'],
ids=['dict', 'func', 'gen', 'gen_func'])
@pytest.mark.parametrize('input_type', ['dict', 'func', 'gen', 'gen_func'])
@pytest.mark.parametrize('exec_mode', [pnl.ExecutionMode.PyTorch,
pnl.ExecutionMode.LLVMRun,
pnl.ExecutionMode.Python],
ids=['PyTorch', 'LLVM', 'Python'])
@pytest.mark.parametrize('comp_type', ['composition', 'autodiff'],
ids=['composition', 'autodiff'])
def node_spec_types(self, xor_network, comp_type, input_type, exec_mode):
pnl.ExecutionMode.Python])
@pytest.mark.parametrize('comp_type', ['composition', 'autodiff'])
def test_node_spec_types(self, xor_network, comp_type, input_type, exec_mode):

if comp_type == 'composition' and exec_mode != pnl.ExecutionMode.Python:
pytest.skip(f"Execution mode {exec_mode} not relevant for Composition")
pytest.skip(f"Execution mode {exec_mode} not relevant for Composition learn")

comp, input_layer, hidden_layer, output_layer, target_mechanism, stims, targets =\
xor_network(comp_type, 0.001, None)
Expand Down Expand Up @@ -113,12 +111,8 @@ def get_inputs_gen():
else:
assert False, f"Unrecognized input_type: {input_type}"

expected_results = [[0.6341436044849351]]
if comp_type is 'composition':
results = comp.learn(inputs=inputs)
else:
results = comp.learn(inputs=inputs, execution_mode=exec_mode)
np.testing.assert_allclose(results, expected_results)
results = comp.learn(inputs=inputs, execution_mode=exec_mode)
np.testing.assert_allclose(results, [[0.6341436044849351]])

@pytest.mark.composition
@pytest.mark.pytorch
Expand Down
4 changes: 2 additions & 2 deletions tests/functions/test_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ def test_DictionaryMemory_without_assoc(self):

def test_DictionaryMemory_with_duplicate_entry_in_initializer_warning(self):

regexp = r'Attempt to initialize memory of DictionaryMemory with an entry \([[1 2 3]'
regexp = r'Attempt to initialize memory of DictionaryMemory with an entry \(\[\[1 2 3\]'
with pytest.warns(UserWarning, match=regexp):
em = EpisodicMemoryMechanism(
name='EPISODIC MEMORY MECH',
Expand Down Expand Up @@ -1034,7 +1034,7 @@ def test_ContentAddressableMemory_without_initializer_and_diff_field_sizes(self)

def test_ContentAddressableMemory_with_duplicate_entry_in_initializer_warning(self):

regexp = r'Attempt to initialize memory of ContentAddressableMemory with an entry \([[1 2 3]'
regexp = r'Attempt to initialize memory of ContentAddressableMemory with an entry \(\[\[1 2 3\]'
with pytest.warns(UserWarning, match=regexp):
c = ContentAddressableMemory(
initializer=np.array([[[1,2,3], [4,5,6]],
Expand Down
2 changes: 1 addition & 1 deletion tests/mechanisms/test_ddm_mechanism.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def test_valid(self):

# reset only decision variable
D.function.initializer = 1.0
D.function.non_decision_time = 0.0
D.function.non_decision_time.base = 0.0
D.reset()
np.testing.assert_allclose(D.function.value[0], 1.0)
np.testing.assert_allclose(D.function.parameters.previous_value.get(), 1.0)
Expand Down
12 changes: 7 additions & 5 deletions tests/mechanisms/test_lca.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,14 @@ def test_LCAMechanism_threshold_with_convergence(self, benchmark, comp_mode):
comp = Composition()
comp.add_node(lca)

result = comp.run(inputs={lca:[0,1,2]}, execution_mode=comp_mode)
np.testing.assert_allclose(result, [[0.19153799, 0.5, 0.80846201]])
def func(*args, **kwargs):
res = comp.run(*args, **kwargs)
return (res, lca.num_executions_before_finished)

results = benchmark(func, inputs={lca:[0,1,2]}, execution_mode=comp_mode)
np.testing.assert_allclose(results[0], [[0.19153799, 0.5, 0.80846201]])
if comp_mode is pnl.ExecutionMode.Python:
assert lca.num_executions_before_finished == 18
if benchmark.enabled:
benchmark(comp.run, inputs={lca:[0,1,2]}, execution_mode=comp_mode)
assert results[1] == 18

@pytest.mark.composition
@pytest.mark.lca_mechanism
Expand Down
2 changes: 1 addition & 1 deletion tests/mechanisms/test_mechanisms.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_noise_assignment_equivalence(self, noise):
t2 = pnl.TransferMechanism(name='t2', size=2)
t2.integrator_function.parameters.noise.set(noise())

t1.integrator_function.noise.seed = 0
t1.integrator_function.noise.seed.base = 0
t2.integrator_function.noise.base.seed = 0

for _ in range(5):
Expand Down
Loading

0 comments on commit 26f6b64

Please sign in to comment.