Hoa central
Disjunction.php
Go to the documentation of this file.
1 <?php
2 
37 namespace Hoa\Realdom {
38 
39 use Hoa\Core;
40 use Hoa\Math;
41 use Hoa\Visitor;
42 
52  implements \ArrayAccess,
53  \IteratorAggregate,
54  \Countable,
56 {
62  protected $_originalRealdoms = [];
63 
69  protected $_realdoms = [];
70 
77  protected $__realdoms = [];
78 
85  protected $__matches = [];
86 
92  protected $_chosenRealdom = null;
93 
99  protected $_constraints = [];
100 
106  protected $_holder = null;
107 
108 
109 
115  public function __construct()
116  {
117  // Original realdoms are the same in every clone.
118  $this->_originalRealdoms = &$this->_originalRealdoms;
119 
120  // In the original object (not a clone):
121  $this->_realdoms = &$this->_originalRealdoms;
122 
123  return;
124  }
125 
131  public function __clone()
132  {
133 
134  // Break the reference.
135  unset($this->_realdoms);
136 
137  // Create a new array of references (of realdoms).
138  $this->_realdoms = $this->_originalRealdoms;
139 
140  $this->_chosenRealdom = null;
141 
142  return;
143  }
144 
151  public function __get($name)
152  {
153  if ('or' !== $name) {
154  return $this->$name;
155  }
156 
157  return $this;
158  }
159 
169  public function __call($name, Array $arguments)
170  {
171  $name = ucfirst(strtolower($name));
172 
173  if ('Const' === $name) {
174  $handle = $arguments;
175  Realdom::autoBoxing($handle);
176  $handle = $handle[0];
177  $arguments = [];
178  } elseif ('Variable' === $name) {
179  $handle = new Crate\Variable($arguments[0]);
180  } else {
181  if (Core\Consistency::isKeyword($name)) {
182  $name = 'Realdom' . $name;
183  }
184 
185  try {
186  $handle = dnew(
187  '(Hoathis or Hoa)\Realdom\\' . $name,
188  $arguments
189  );
190  } catch (Exception $e) {
191  throw $e;
192  } catch (Core\Exception $e) {
193  throw new Exception(
194  'Realistic domain %s() does not exist (or something ' .
195  'wrong happened).',
196  0,
197  strtolower($name),
198  $e
199  );
200  }
201  }
202 
203  $this->offsetSet(null, $handle);
204 
205  return $this;
206  }
207 
215  public function _call($name, Array $arguments = [])
216  {
217  return $this->__call($name, $arguments);
218  }
219 
226  public function offsetExists($offset)
227  {
228  return array_key_exists($offset, $this->_realdoms);
229  }
230 
237  public function offsetGet($offset)
238  {
239  if (false === $this->offsetExists($offset)) {
240  return null;
241  }
242 
243  return $this->_realdoms[$offset];
244  }
245 
254  public function offsetSet($offset, $realdom)
255  {
256  if ($realdom instanceof self) {
257  foreach ($realdom as $_realdom) {
258  $this->_offsetSet(null, $_realdom);
259  }
260 
261  return $this;
262  }
263 
264  if ($realdom instanceof Crate\Variable) {
265  $this->__realdoms[] = $realdom;
266  $unfolded = 1;
267 
268  foreach ($realdom->getDomains() as $_realdom) {
269  $this->_offsetSet(null, $_realdom, false);
270  ++$unfolded;
271  }
272 
273  $this->__matches[] = $unfolded;
274 
275  return $this;
276  }
277 
278  return $this->_offsetSet($offset, $realdom);
279  }
280 
290  protected function _offsetSet($offset, $realdom, $backStore = true)
291  {
292  if (!($realdom instanceof Realdom)) {
293  throw new Exception(
294  'A disjunction accepts only realdom; given %s.',
295  1,
296  is_object($realdom)
297  ? get_class($realdom)
298  : gettype($realdom)
299  );
300  }
301 
302  $realdom->setConstraints($this->_constraints);
303 
304  if (null === $offset) {
305  $this->_realdoms[] = $realdom;
306 
307  if (true === $backStore) {
308  $this->__realdoms[] = &$realdom;
309  $this->__matches[] = 1;
310  }
311  } else {
312  throw new Exception('Offset %s must be null.', 2);
313  }
314 
315  return $this;
316  }
317 
325  public function offsetUnset($offset)
326  {
327  if (null === $this->offsetGet($offset)) {
328  return;
329  }
330 
331  array_splice($this->__realdoms, $offset, 1);
332 
333  $acc = 0;
334 
335  for ($i = 0; $i < $offset - 1; ++$i) {
336  $acc += $this->__matches[$i];
337  }
338 
339  array_splice($this->_realdoms, $acc, $this->__matches[$i]);
340 
341  return;
342  }
343 
349  public function getRealdoms()
350  {
351  return $this->_realdoms;
352  }
353 
359  public function getChosenRealdom()
360  {
361  return $this->_chosenRealdom;
362  }
363 
369  public function reset()
370  {
371  foreach ($this->_realdoms as $realdom) {
372  $realdom->reset();
373  }
374 
375  return;
376  }
377 
384  public function predicate($q)
385  {
386  foreach ($this->_realdoms as $realdom) {
387  if (true === $realdom->predicate($q)) {
388  return true;
389  }
390  }
391 
392  return false;
393  }
394 
402  public function sample(Math\Sampler $sampler = null)
403  {
404  if (empty($this->_realdoms)) {
405  throw new Exception(
406  'Cannot sample because the disjunction is empty.',
407  3
408  );
409  }
410 
411  if (null === $sampler &&
412  null === $sampler = Realdom::getDefaultSampler()) {
413  throw new Exception(
414  'No sampler set. Please, use the %s::setDefaultSampler() ' .
415  'method.',
416  4,
417  __NAMESPACE__
418  );
419  }
420 
421  $m = count($this->_realdoms) - 1;
422  $i = $sampler->getInteger(0, $m);
423  $this->_chosenRealdom = $this->_realdoms[$i];
424 
425  return $this->_chosenRealdom->sample($sampler);
426  }
427 
435  public function propagateConstraints($type, $index)
436  {
437  foreach ($this->_realdoms as $realdom) {
438  $realdom->propagateConstraints($type, $index);
439  }
440 
441  return;
442  }
443 
449  public function getIterator()
450  {
451  return new \ArrayIterator($this->_realdoms);
452  }
453 
459  public function getUnflattenedRealdoms()
460  {
461  return $this->__realdoms;
462  }
463 
469  public function count()
470  {
471  return count($this->_realdoms);
472  }
473 
480  public function setHolder(IRealdom\Holder $holder)
481  {
482  $old = $holder;
483  $this->_holder = $holder;
484 
485  foreach ($this->_realdoms as $realdom) {
486  $realdom->setHolder($holder);
487  }
488 
489  return $old;
490  }
491 
497  public function getHolder()
498  {
499  return $this->_holder;
500  }
501 
510  public function accept(
511  Visitor\Visit $visitor,
512  &$handle = null,
513  $eldnah = null
514  ) {
515  return $visitor->visit($this, $handle, $eldnah);
516  }
517 }
518 
519 }
520 
521 namespace {
522 
528 if (!function_exists('realdom')) {
529  function realdom()
530  {
531  return new Hoa\Realdom\Disjunction();
532  }
533 }
534 
535 }
propagateConstraints($type, $index)
static autoBoxing(Array &$arguments, Realdom $self=null)
Definition: Realdom.php:366
setHolder(IRealdom\Holder $holder)
__call($name, Array $arguments)
static getDefaultSampler()
Definition: Realdom.php:542
_offsetSet($offset, $realdom, $backStore=true)
offsetSet($offset, $realdom)
sample(Math\Sampler $sampler=null)
accept(Visitor\Visit $visitor, &$handle=null, $eldnah=null)
_call($name, Array $arguments=[])