Skip to content
This repository was archived by the owner on Oct 20, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion docs/usage/file_formats/dcop_format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ domains:
d3:
values : [1 .. 10]
type : non_semantic
initial_value: 3
dbool:
values : [true, false]

Expand Down
3 changes: 3 additions & 0 deletions pydcop/algorithms/adsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
from typing import Tuple, Any, List, Dict

from pydcop.algorithms import AlgoParameterDef, ComputationDef
from pydcop.dcop.objects import Domain
from pydcop.dcop.relations import (
find_optimum,
assignment_cost,
Expand Down Expand Up @@ -134,6 +135,8 @@ def __init__(self, comp_def):

assert comp_def.algo.algo == "adsa"
assert (comp_def.algo.mode == "min") or (comp_def.algo.mode == "max")
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self.mode = comp_def.algo.mode
self.probability = comp_def.algo.param_value("probability")
Expand Down
5 changes: 4 additions & 1 deletion pydcop/algorithms/amaxsum.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
from collections import defaultdict
from typing import Dict, Any, List

from pydcop.dcop.objects import VariableNoisyCostFunc, Variable
from pydcop.dcop.objects import VariableNoisyCostFunc, Variable, Domain
from pydcop.algorithms import AlgoParameterDef, ComputationDef
from pydcop.algorithms import maxsum
from pydcop.dcop.relations import generate_assignment_as_dict
Expand Down Expand Up @@ -114,6 +114,9 @@ class MaxSumFactorComputation(DcopComputation):
def __init__(self, comp_def=None):
assert comp_def.algo.algo == "amaxsum"
super().__init__(comp_def.node.factor.name, comp_def)
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self.mode = comp_def.algo.mode
self.factor = comp_def.node.factor
self.variables = self.factor.dimensions
Expand Down
6 changes: 4 additions & 2 deletions pydcop/algorithms/dba.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@

from pydcop.computations_graph.constraints_hypergraph import \
VariableComputationNode
from pydcop.dcop.objects import Variable
from pydcop.dcop.objects import Variable, Domain
from pydcop.dcop.relations import RelationProtocol, filter_assignment_dict

INFINITY = 10000
Expand Down Expand Up @@ -296,7 +296,9 @@ def __init__(self, variable: Variable,
raise ValueError('DBA is a constraint **satisfaction** '
'algorithm and only support '
'minimization objective')

# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self._msg_sender = msg_sender

global INFINITY
Expand Down
6 changes: 4 additions & 2 deletions pydcop/algorithms/dpop.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

from pydcop.computations_graph.pseudotree import get_dfs_relations
from pydcop.infrastructure.computations import Message, VariableComputation, register
from pydcop.dcop.objects import Variable
from pydcop.dcop.objects import Variable, Domain
from pydcop.dcop.relations import (
NAryMatrixRelation,
Constraint,
Expand Down Expand Up @@ -172,12 +172,14 @@ class DpopAlgo(VariableComputation):
"""

def __init__(self, comp_def: ComputationDef):

assert comp_def.algo.algo == "dpop"

super().__init__(comp_def.node.variable, comp_def)
self._mode = comp_def.algo.mode

# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self._parent, self._pseudo_parents, self._children, self._pseudo_children = get_dfs_relations(
self.computation_def.node
)
Expand Down
4 changes: 3 additions & 1 deletion pydcop/algorithms/dsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@

from pydcop.algorithms import AlgoParameterDef, ComputationDef
from pydcop.infrastructure.computations import Message, VariableComputation, register

from pydcop.dcop.objects import Domain
from pydcop.computations_graph.constraints_hypergraph import VariableComputationNode
from pydcop.dcop.relations import (
find_optimum,
Expand Down Expand Up @@ -247,6 +247,8 @@ def __init__(self, comp_def: ComputationDef):

assert comp_def.algo.algo == "dsa"
assert (comp_def.algo.mode == "min") or (comp_def.algo.mode == "max")
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self.mode = comp_def.algo.mode
self.probability = comp_def.algo.param_value("probability")
Expand Down
4 changes: 4 additions & 0 deletions pydcop/algorithms/dsatuto.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

from pydcop.algorithms import ComputationDef
from pydcop.dcop.relations import assignment_cost, find_optimal
from pydcop.dcop.objects import Domain
from pydcop.infrastructure.computations import (
VariableComputation,
message_type,
Expand Down Expand Up @@ -82,6 +83,9 @@ def __init__(self, computation_definition: ComputationDef):
super().__init__(computation_definition.node.variable, computation_definition)

assert computation_definition.algo.algo == "dsatuto"
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self.mode = computation_definition.algo.mode

self.constraints = computation_definition.node.constraints
Expand Down
4 changes: 3 additions & 1 deletion pydcop/algorithms/gdba.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
from pydcop.algorithms import AlgoParameterDef, ComputationDef
from pydcop.infrastructure.computations import Message, VariableComputation, register
from pydcop.computations_graph.constraints_hypergraph import VariableComputationNode
from pydcop.dcop.objects import Variable
from pydcop.dcop.objects import Variable, Domain
from pydcop.dcop.relations import (
RelationProtocol,
NAryMatrixRelation,
Expand Down Expand Up @@ -232,6 +232,8 @@ def __init__(
"""

super().__init__(variable, comp_def)
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self._msg_sender = msg_sender

Expand Down
7 changes: 5 additions & 2 deletions pydcop/algorithms/maxsum.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
FactorComputationNode,
VariableComputationNode,
)
from pydcop.dcop.objects import Variable, VariableNoisyCostFunc
from pydcop.dcop.objects import Variable, VariableNoisyCostFunc, Domain
from pydcop.dcop.relations import Constraint, generate_assignment_as_dict
from pydcop.infrastructure.computations import (
DcopComputation,
Expand Down Expand Up @@ -280,7 +280,10 @@ class MaxSumFactorComputation(SynchronousComputationMixin, DcopComputation):
def __init__(self, comp_def: ComputationDef):
assert comp_def.algo.algo == "maxsum"
super().__init__(comp_def.node.factor.name, comp_def)
self.logger.warning(f"Neiborghs {self.neighbors}")
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self.logger.warning(f"Neighbors {self.neighbors}")

self.mode = comp_def.algo.mode
self.factor = comp_def.node.factor
Expand Down
3 changes: 3 additions & 0 deletions pydcop/algorithms/maxsum_dynamic.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from pydcop.algorithms.amaxsum import MaxSumFactorComputation, MaxSumVariableComputation
from pydcop.algorithms.maxsum import MaxSumMessage
from pydcop.dcop.relations import NeutralRelation
from pydcop.dcop.objects import Domain


class DynamicFunctionFactorComputation(MaxSumFactorComputation):
Expand Down Expand Up @@ -76,6 +77,8 @@ class DynamicFunctionFactorComputation(MaxSumFactorComputation):

def __init__(self, comp_def=None):
super().__init__(comp_def=comp_def)
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

def change_factor_function(self, fn):
"""
Expand Down
3 changes: 3 additions & 0 deletions pydcop/algorithms/mgm.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
find_arg_optimal,
optimal_cost_value,
)
from pydcop.dcop.objects import Domain
from pydcop.infrastructure.computations import Message, VariableComputation, register

GRAPH_TYPE = "constraints_hypergraph"
Expand Down Expand Up @@ -231,6 +232,8 @@ def __init__(self, computation_definition: ComputationDef):
)

super().__init__(computation_definition.node.variable, computation_definition)
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self.__utilities__ = list(computation_definition.node.constraints)
self._mode = computation_definition.algo.mode # min or max
Expand Down
4 changes: 3 additions & 1 deletion pydcop/algorithms/mgm2.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

from pydcop.algorithms import AlgoParameterDef, ComputationDef
from pydcop.infrastructure.computations import Message, VariableComputation, register

from pydcop.dcop.objects import Domain
from pydcop.computations_graph.constraints_hypergraph import VariableComputationNode
from pydcop.dcop.relations import (
find_dependent_relations,
Expand Down Expand Up @@ -417,6 +417,8 @@ class Mgm2Computation(VariableComputation):
def __init__(self, computation_def: ComputationDef = None):
assert computation_def.algo.algo == "mgm2"
super().__init__(computation_def.node.variable, computation_def)
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self._mode = computation_def.algo.mode
self.stop_cycle = computation_def.algo.param_value("stop_cycle")
Expand Down
4 changes: 3 additions & 1 deletion pydcop/algorithms/mixeddsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

from pydcop.dcop.relations import RelationProtocol, generate_assignment_as_dict, \
filter_assignment_dict

from pydcop.dcop.objects import Domain
from pydcop.algorithms import AlgoParameterDef, ComputationDef
from pydcop.infrastructure.computations import Message, VariableComputation, \
register
Expand Down Expand Up @@ -183,6 +183,8 @@ def __init__(self, variable, constraints, variant='B', proba_hard=0.7,

"""
super().__init__(variable, comp_def)
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

self.proba_hard = proba_hard
self.proba_soft = proba_soft
Expand Down
4 changes: 3 additions & 1 deletion pydcop/algorithms/ncbb.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@

from pydcop.algorithms import ComputationDef
from pydcop.computations_graph.pseudotree import get_dfs_relations
from pydcop.dcop.objects import Domain
from pydcop.dcop.relations import find_optimal
from pydcop.infrastructure.computations import (
VariableComputation,
Expand Down Expand Up @@ -149,7 +150,8 @@ class NcbbAlgo(SynchronousComputationMixin, VariableComputation):

def __init__(self, computation_definition: ComputationDef):
super().__init__(computation_definition.node.variable, computation_definition)

# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain
assert computation_definition.algo.algo == "ncbb"
self._mode = computation_definition.algo.mode

Expand Down
4 changes: 3 additions & 1 deletion pydcop/algorithms/syncbb.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
from typing import Optional, List, Any, Tuple

from pydcop.algorithms import ComputationDef
from pydcop.dcop.objects import Variable
from pydcop.dcop.objects import Variable, Domain
from pydcop.dcop.relations import assignment_cost, Constraint
from pydcop.infrastructure.computations import (
VariableComputation,
Expand Down Expand Up @@ -181,6 +181,8 @@ class SyncBBComputation(VariableComputation):

def __init__(self, computation_definition: ComputationDef):
super().__init__(computation_definition.node.variable, computation_definition)
# Check if the domains of the variables are suitable
assert type(self._variable.domain) is Domain

assert computation_definition.algo.algo == "syncbb"
self.constraints = computation_definition.node.constraints
Expand Down
45 changes: 45 additions & 0 deletions pydcop/dcop/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,51 @@ def to_domain_value(self, val: str):
raise ValueError(str(val) + " is not in the domain " + self._name)


class ContinuousDomain(Domain):
"""
A ContinuousDomain indicates the lower and upper bound of the values
that are valid for variables with this domain.
It also indicates the type of environment state represented
by there variable : 'luminosity', humidity', etc.

The lower and upper bound of the domain is stored separately
as well as within the values (values = [lower bound, upper bound])
in order to be compatible with the Domain class.
"""

def __init__(self, name: str, domain_type: str, lower_bound: float, upper_bound: float) -> None:
"""

:param: name: name of the domain.
:param domain_type: a string identifying the kind of value in the
domain. For example : 'luminosity', 'humidity', ...
:param lower_bound: the lower bound of the domain of the valid values
:param upper_bound: the upper bound of the domain of the valid values
"""
# Check the bounds for consistency
assert lower_bound <= upper_bound

# Initiate the parent class
super().__init__(name, domain_type, [lower_bound, upper_bound])

# Store the parameters
self._lower_bound = lower_bound
self._upper_bound = upper_bound

@property
def upper_bound(self) -> float:
return self._upper_bound

@property
def lower_bound(self) -> float:
return self._lower_bound

def __str__(self):
return f"ContinuousDomain({self.name})"

def __repr__(self):
return f"ContinuousDomain({self.name}, {self.type}, ({self.lower_bound}..{self.upper_bound}))"

# We keep VariableDomain as an alias for the moment, but Domain should be
# preferred.
VariableDomain = Domain
Expand Down
42 changes: 13 additions & 29 deletions pydcop/dcop/yamldcop.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import yaml

from pydcop.dcop.objects import (
ContinuousDomain,
VariableDomain,
Variable,
ExternalVariable,
Expand Down Expand Up @@ -143,13 +144,22 @@ def _build_domains(loaded) -> Dict[str, VariableDomain]:
domains = {}
if "domains" in loaded:
for d_name in loaded["domains"]:
# Retrieve the properties
d = loaded["domains"][d_name]
values = d["values"]
d_type = d["type"] if "type" in d else ""

# Check the type of domain
if len(values) == 1 and ".." in values[0]:
values = str_2_domain_values(d["values"][0])
d_type = d["type"] if "type" in d else ""
domains[d_name] = VariableDomain(d_name, d_type, values)
# Continuous domain
bounds = [float(b)
for b
in values[0].replace(' ','').split('..')]
domains[d_name] = ContinuousDomain(
d_name, d_type, bounds[0], bounds[1])
else:
# Discrete domain
domains[d_name] = VariableDomain(d_name, d_type, values)

return domains

Expand Down Expand Up @@ -475,32 +485,6 @@ def _build_dist_hints(loaded, dcop):
must_host, dict(host_with) if host_with is not None else {}
)


def str_2_domain_values(domain_str):
"""
Deserialize a domain expressed as a string.

If all variable in the domain can be interpreted as a int, the list is a
list of int, otherwise it is a list of strings.

:param domain_str: a string like 0..5 of A, B, C, D

:return: the list of values in the domain
"""
try:
sep_index = domain_str.index("..")
# Domain str is : [0..5]
min_d = int(domain_str[0:sep_index])
max_d = int(domain_str[sep_index + 2 :])
return list(range(min_d, max_d + 1))
except ValueError:
values = [v.strip() for v in domain_str[1:].split(",")]
try:
return [int(v) for v in values]
except ValueError:
return values


def load_scenario_from_file(filename: str) -> Scenario:
"""
Load a scenario from a yaml file.
Expand Down
Loading