One of the strengths of the CPM is that it can incorporate different processes of interest as separate "rules" given to the model. These rules can be mixed and matched to get a simulation of interest, making the CPM a very flexible framework. Artistoo implements a diverse set of model rules, called Constraints. This tutorial will walk you through how to use these constraints in your models.

## Soft versus hard constraints

In Artistoo, we distinguish two types of constraints: "hard" and "soft" constraints.

### Soft constraints

"Soft" constraints are the classical CPM energy rules. They are the terms of the model's Hamiltonian, or energy equation. When a copy attempt would break such a rule, this becomes visible as an energetic penalty making that copy attempt less likely. But a soft constraint is more a guideline than an actual rule; the model will mostly adhere to it, but not always.

For example, suppose we have a cell with a volume constraint, and that cell is already larger than its target volume. A copy attempt that would add another pixel to that cell would be associated with a $ΔH_\text{vol} \gt 0$. However, that does not mean that this copy attempt will always fail to go through. First, it may be that there are other constraints acting on the model for which this copy attempt is favourable, compensating for the volume penalty such that the global $ΔH$ is still negative. Second, even if the global $ΔH$ is positive, a copy attempt may still be accepted with a chance $e^{-ΔH T}$. Thus, soft constraints make some changes more likely to happen than others, but they can balance each other out and are not always listened to.

Most CPM constraints are soft constraints. But sometimes, there are things we would like to forbid completely. For that, we can use a hard constraint.

### Hard constraints

Whereas soft constraints are more guidelines than rules, "hard" constraints are set in stone. Before the $ΔH$ of a copy attempt is even computed, Artistoo checks whether it violates one of the hard constraints. If it does, it won't go through — ever.

Not many constraints are hard constraints, and in a typical CPM, you should be careful using them. But examples are the HardVolumeRangeConstraint, the BarrierConstraint, and the hard ConnectivityConstraint. See also this example of a 'particle' following a random walk, where we constrained the volume such that the cell can only be one or two pixels big:

## Adding a constraint to a model

There are two ways of adding a constraint to your model, which we will explain here.

### Method 1: via the conf object

The first method is to add the relevant constraint parameters to the conf object. This is the easiest method to add a constraint, but it only works for a few of the most used constraints (see this page for a list of the constraints for which this works).

For example:

let myCPM = new CPM.CPM(
[ 200, 200 ],
{
T : 20,
J : [[0,20],[20,0]],
V : [0,500],
LAMBDA_V: [ 0, 50]
}

)

will automatically create a CPM with an adhesion and a volume constraint inside it. If we open the browser console from a page with an Artistoo simulation in it, e.g. this one, we can check this. Go to the page, right click anywhere on the page outside of the grid, select "inspect" and then "console". Copy-paste the above code in the console and hit enter. If you now type:

myCPM.soft_constraints

and hit enter, you should see that there are two soft constraints in the model now: an Adhesion and a VolumeConstraint.

This works the same if we use the Simulation class, because the config.conf is passed along internally to the CPM constructor. So if we type:

let mySim = new CPM.Simulation(
{
field_size : [200,200],
conf : {
T : 20,
J : [[0,20],[20,0]],
V : [0,500],
LAMBDA_V: [ 0, 50]
},
simsettings : {
NRCELLS : [1]
}
}

)
mySim.C.soft_constraints

we again see our two constraints appear.

### Method 2: via the add() method

Note that, as mentioned, the first method does not work for all constraints. If we try to add an AttractionPointConstraint (another soft constraint) in this way:

let myCPM = new CPM.CPM(
[ 200, 200 ],
{
T : 20,
J : [[0,20],[20,0]],
V : [0,500],
LAMBDA_V: [ 0, 50],
LAMBDA_ATTRACTIONPOINT : [0,100],
ATTRACTIONPOINT: [[0,0],[100,100]]
}

)

then if we type:

myCPM.soft_constraints

we still only have our Adhesion and a VolumeConstraint. The AttractionPointConstrainthas not been added.

To add this constraint, we must use the add() method of the CPM class. If we have already put the relevant parameters in the conf object, this is easy:

//add constraint
myCPM.add( new CPM.AttractionPointConstraint( myCPM.conf ) )
myCPM.soft_constraints

you should now see an AttractionPointConstraint in the list of soft constraints. We've given the entire conf object of the CPM to the constraint's constructor, but it will just ignore the parameters that are not relevant to this constraint. However, we can also just give it it's own conf object. For example, we might add a second attraction point like this:

//add another constraint
LAMBDA_ATTRACTIONPOINT : [0,100],
ATTRACTIONPOINT: [[0,0],[150,150]]
} ) )
myCPM.soft_constraints

You should now see two attraction point constraints in your list.

A word of warning: when you add a new constraint, the model will use it. It won't check if another constraint of the same type was already present. For the example above, that's perfectly fine because we might want to have two different points of attraction. However, for other constraints such as the Adhesion, this might not be what you want (basically, this will be the same as having only one adhesion constraint where the parameters are twice as large. But someone checking your code may overlook your second adhesion constraint and think that the adhesion parameters are set lower than they actually are...).

## Accessing a constraint in your model

Once you've put a constraint in your model, you may want to access it from outside. The method getConstraint() allows you to do that. For example:

//get volumeconstraint
myCPM.getConstraint( "VolumeConstraint" )

will return the VolumeConstraint that is currently in your model.

If there are multiple constraints of the same name in your model, this method automatically gives you the first one:

//get the first attraction point constraint
myCPM.getConstraint( "AttractionPointConstraint" )

This yields the first attraction point we added (from the browser console, you can click the little triangle on the left to see more about the object. If you look at its conf object, you see that this is the settings we gave to our first attraction point constraint).

If we want to access the second attraction point, we can type:

//get the second attraction point constraint
myCPM.getConstraint( "AttractionPointConstraint", 1 )

(Note here that JavaScript uses zero-based indexing, so an element with number 1 is actually the second element)

## Implementation details

Constraints in Artistoo are implemented as separate classes, of which an instance can be added to a CPM model (See above for an explanation how). The base Constraint class underlies all of them, and has two subclasses: SoftConstraint and HardConstraint. These are never used by themselves, but can be extended to create a constraint (see also this tutorial to see how to develop custom modules).