Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault on calling infr.marginals([]) twice #484

Open
Erotemic opened this issue Jan 31, 2017 · 1 comment
Open

Segfault on calling infr.marginals([]) twice #484

Erotemic opened this issue Jan 31, 2017 · 1 comment

Comments

@Erotemic
Copy link
Contributor

I've found a segfault after applying belief propogation to a dummy graph when I call infr.marginals([]) twice.
The first time it returns an empty array, and the second time it segfaults.

I don't think it makes sense to call infr.marginals like this, but its probably not good that the library segfaults in this case either.

Code to reproduce the issue.

import numpy as np
import itertools as it
import opengm
n_states = 2  # each node has 2 states
n_nodes = 4

# Unaries are the measured probabilites that each node is in a state
# The probability an node `a` is in state `s` is unaries[a, s]
unaries = np.empty((n_nodes, n_states))
rng = np.random.RandomState(0)
unaries[:, 0] = rng.rand(n_nodes)
unaries[:, 1] = 1 -  unaries[:, 0]
assert np.all(unaries.sum(axis=1) == 1), 'must sum to 1'

# Costs for having the same label
potts_func = opengm.PottsFunction(
    (n_states, n_states), valueEqual=.7, valueNotEqual=.3)

operator = 'multiplier'
accumulator = 'integrator'

# Define graphical model
node_state_card = np.ones(n_nodes, dtype=opengm.index_type) * n_states
gm = opengm.graphicalModel(node_state_card, operator=operator)

unary_factor_idxs = []
pairwise_factor_idxs = []

# Add unary terms to the graph
node_idxs = list(range(n_nodes))
for count, idx in enumerate(node_idxs, start=gm.numberOfFactors):
    fid = gm.addFunction(unaries[idx])
    gm.addFactor(fid, idx)
    unary_factor_idxs.append(count)

# Add pairwise edge terms to the graph
edge_idxs = list(it.combinations(node_idxs, 2))
potts_func_id = gm.addFunction(potts_func)

# Add Potts function for each edge
for count, (idx1, idx2) in enumerate(edge_idxs, start=gm.numberOfFactors):
    var_idxs = np.array([idx1, idx2])
    gm.addFactor(potts_func_id, var_idxs)
    pairwise_factor_idxs.append(count)

# Apply Inference
infr = opengm.inference.BeliefPropagation(gm, accumulator=accumulator)
infr.infer()

# The first call does not segfault
empty_marginals = infr.marginals([])
print('empty_marginals(1) = %r' % (empty_marginals,))

# But the second one does
empty_marginals = infr.marginals([])
print('empty_marginals(2) = %r' % (empty_marginals,))
@DerThorsten
Copy link
Collaborator

DerThorsten commented Feb 2, 2017

Hi,
So calling marginals with an empty list is not allowed and we could/should check / assert this on the python side.
The idea is to pass a list of variable indexes, a numpy array of indexes or a single index to this function.

But it is still not so nice that is segfaults if this is done twice, but i am not sure if it is allowed/intended to call this twice.
Might be some implementation details in BP that disallow calling this twice.
ATM there is no state machine inside the solvers and calling functions like 'infer','arg' and 'marginals' twice might lead to undefined behavior ( @joergkappes should know this part of the code the best)

Greetings Thorsten

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants