"Cannot get return value of a generator that hasn't returned " php 回溯
"Cannot get return value of a generator that hasn't returned " php backtracking
我正在尝试通过回溯来解决问题,但出现此错误:
Error: genator hasn´t returned
首先介绍一下本软件要解决的主要问题:
I have been trying to create the software for a hospital, this
software must create a schedule with the doctors for each day. Each
day must have 5 assigned doctors, one for a specialty called "trauma",
another for "ucr" and another for "box13".
Before assigning doctors, the user must enter the number of holes of
each type that doctor can do that month. So I know how many "trauma",
"ucr" or "box13" have any doctor that month.
Aaah! one more thing, you can not assign a doctor two days in a row.
所以我决定创建一个回溯算法,问题是我在执行结束时得到了一个生成器对象,但我没有得到一个有效的 return。
function bt($ps){
if($ps->is_solution()){
return $ps->get_solution();
}
else{
yield from $ps->successors();
}
}
class Briker_vc_PS{
public function __construct( $decisiones, $diasTotalFinal, $fechaInicio, $box13, $ucr, $trauma, $numGuardiasAsig){
$this->decisiones= $decisiones;
$this->diasTotalFinal = $diasTotalFinal;
$this->fechaInicio = $fechaInicio;
$this->box13 = $box13;
$this->ucr = $ucr;
$this->trauma = $trauma;
$this->numGuardiasAsig = $numGuardiasAsig;
}
public function is_solution(){
return $this->numGuardiasAsig == $this->diasTotalFinal*5;
}
public function get_solution(){
return $this->decisiones;
}
public function state(){
return $this->decisiones[$this->fechaInicio];
}
public function successors(){
if( array_key_exists( $this->fechaInicio, $this->decisiones) == false ){
$this->decisiones[$this->fechaInicio] = [];
}
if( array_key_exists( 'ids', $this->decisiones[$this->fechaInicio]) == false ){
$this->decisiones[$this->fechaInicio]['ids'] = [];
}
if( array_key_exists( $this->fechaInicio ,$this->decisiones) and array_key_exists( 'box13' ,$this->decisiones) and array_key_exists( 'trauma' ,$this->decisiones) and array_key_exists( 'ucr' ,$this->decisiones)){
if( (count($this->decisiones['trauma'])==1) and (count($this->decisiones['ucr'])==2) and (count($this->decisiones['box13'])==2) ){
$this->fechaInicio = date("Y-m-d",strtotime($this->fechaInicio." +1 day"));
$this->decisiones[$this->fechaInicio]['date'] = $this->fechaInicio;
}
}
$anterior = date("Y-m-d",strtotime($this->fechaInicio." -1 day"));
$Lista=[];
if( array_key_exists( 'trauma' ,$this->decisiones) == false ){
foreach($this->trauma as $key => $val){
if( (in_array($key, $this->decisiones[$this->fechaInicio]['ids']) == false) and (in_array($key, $this->decisiones[$anterior]['ids']) == false) ){
$decisions= $this->decisiones;
$decisions[$this->fechaInicio]['trauma'] = [$key];
$auxtra= $this->trauma;
if($auxtra[$key] -1 == 0){
unset($auxtra[$key]);
}else{
$auxtra[$key] = $auxtra[$key] -1;
}
$num = $this->numGuardiasAsig +1 ;
$decisions[$this->fechaInicio]['ids'][] = $key;
yield from bt(new Briker_vc_PS( $decisions, $this->diasTotalFinal, $this->fechaInicio, $this->box13, $this->ucr, $auxtra, $num));
}
}
}
if( (array_key_exists( 'box13' ,$this->decisiones) == false) or (count($this->decisiones['box13'])<2) ){
foreach($this->box13 as $key => $val){
if( (in_array($key, $this->decisiones[$this->fechaInicio]['ids']) == false) and (in_array($key, $this->decisiones[$anterior]['ids']) == false) ){
$decisions= $this->decisiones;
if(array_key_exists( 'box13' ,$this->decisiones) == false){
$decisions[$this->fechaInicio]['box13'] = array();
}
$decisions[$this->fechaInicio]['box13'][] = $key;
$auxbox13= $this->box13;
if($auxbox13[$key] -1 == 0){
unset($auxbox13[$key]);
}else{
$auxbox13[$key] = $auxbox13[$key] -1;
}
$num = $this->numGuardiasAsig +1 ;
$decisions[$this->fechaInicio]['ids'][] = $key;
yield from bt( new Briker_vc_PS( $decisions, $this->diasTotalFinal, $this->fechaInicio, $auxbox13, $this->ucr, $this->trauma, $num));
}
}
}
if( (array_key_exists( 'ucr' ,$this->decisiones) == false) or (count($this->decisiones['ucr'])<2) ){
foreach($this->ucr as $key => $val){
if( (in_array($key, $this->decisiones[$this->fechaInicio]['ids']) == false) and (in_array($key, $this->decisiones[$anterior]['ids']) == false) ){
$decisions= $this->decisiones;
if(array_key_exists( 'ucr' ,$this->decisiones) == false){
$decisions[$this->fechaInicio]['ucr'] = array();
}
$decisions[$this->fechaInicio]['ucr'][] = $key;
$auxucr= $this->ucr;
if($auxucr[$key] -1 == 0){
unset($auxucr[$key]);
}else{
$auxucr[$key] = $auxucr[$key] -1;
}
$decisions[$this->fechaInicio]['ids'][] = $key;
$num = $this->numGuardiasAsig +1 ;
yield from bt(new Briker_vc_PS( $decisions, $this->diasTotalFinal, $this->fechaInicio, $this->box13, $auxucr, $this->trauma, $num));
}
}
}
}
protected $GuardiasMedico;
protected $decisiones;
}
这是主程序
$month = $_REQUEST['mes'];
$year = $_REQUEST['any'];
$fecha_inicio = "01-".$month."-".$year;
// fisrt i get the number of "trauma", "ucr" and "box13" for each doctor
// And i create a array with it with key the doctor_id
$db = new SQLite3($dbname);
$result = $db->query('SELECT m.id, m.nombre, m.apellido, mgm.ucr, mgm.trauma, mgm.box13 FROM medico AS m INNER JOIN MedicoGuardiaMes AS mgm ON m.id = mgm.doctor_id WHERE m.borrado = 0 AND mgm.mes = '.$month.' AND mgm.any = '.$year);
$box13 = [];
$ucr = [];
$trauma = [];
while($res = $result->fetchArray()){
$box13[$res['id']] = $res['box13'];
$ucr[$res['id']] = $res['ucr'];
$trauma[$res['id']] = $res['trauma'];
}
// I create the solution array and add the last day from the previous month
$dataBaseDecisiones = [];
$anterior = date("Y-m-d",strtotime($fecha_inicio." -1 day"));
$dataBaseDecisiones[$anterior] = [];
$dataBaseDecisiones[$anterior]['ids'] = [];
$diasTotalFinal=cal_days_in_month(CAL_GREGORIAN, $month, $year);
// Finally I create the initial object and starts the backtracking
$initial_ps = new Briker_vc_PS($dataBaseDecisiones, $diasTotalFinal, $fecha_inicio, $box13, $ucr, $trauma, $numGuardiasAsig);
var_dump( bt($initial_ps)->getReturn() );
我不知道为什么这段代码不起作用,或者我是否以正确的方式使用 yield。
所报告的问题是由于您代码中的最后一行:
bt($initial_ps)->getReturn();
当 bt
执行 else
部分时,它执行递归搜索直到有 return
,然后它 产生 该值.但这并没有完成迭代器的结果,并且这个产生的值不被认为是迭代器的 return 值。所以 getReturn()
触发了你得到的异常。
你没有解释你打算在 var_dump
中得到什么作为输出。如果你想输出所有产生的结果,那么首先收集所有这些结果,例如 iterator_to_array
:
$iter = bt($initial_ps);
print_r(iterator_to_array($iter));
只有这样你才能执行:
print_r($iter->getReturn());
我正在尝试通过回溯来解决问题,但出现此错误:
Error: genator hasn´t returned
首先介绍一下本软件要解决的主要问题:
I have been trying to create the software for a hospital, this software must create a schedule with the doctors for each day. Each day must have 5 assigned doctors, one for a specialty called "trauma", another for "ucr" and another for "box13".
Before assigning doctors, the user must enter the number of holes of each type that doctor can do that month. So I know how many "trauma", "ucr" or "box13" have any doctor that month.
Aaah! one more thing, you can not assign a doctor two days in a row.
所以我决定创建一个回溯算法,问题是我在执行结束时得到了一个生成器对象,但我没有得到一个有效的 return。
function bt($ps){
if($ps->is_solution()){
return $ps->get_solution();
}
else{
yield from $ps->successors();
}
}
class Briker_vc_PS{
public function __construct( $decisiones, $diasTotalFinal, $fechaInicio, $box13, $ucr, $trauma, $numGuardiasAsig){
$this->decisiones= $decisiones;
$this->diasTotalFinal = $diasTotalFinal;
$this->fechaInicio = $fechaInicio;
$this->box13 = $box13;
$this->ucr = $ucr;
$this->trauma = $trauma;
$this->numGuardiasAsig = $numGuardiasAsig;
}
public function is_solution(){
return $this->numGuardiasAsig == $this->diasTotalFinal*5;
}
public function get_solution(){
return $this->decisiones;
}
public function state(){
return $this->decisiones[$this->fechaInicio];
}
public function successors(){
if( array_key_exists( $this->fechaInicio, $this->decisiones) == false ){
$this->decisiones[$this->fechaInicio] = [];
}
if( array_key_exists( 'ids', $this->decisiones[$this->fechaInicio]) == false ){
$this->decisiones[$this->fechaInicio]['ids'] = [];
}
if( array_key_exists( $this->fechaInicio ,$this->decisiones) and array_key_exists( 'box13' ,$this->decisiones) and array_key_exists( 'trauma' ,$this->decisiones) and array_key_exists( 'ucr' ,$this->decisiones)){
if( (count($this->decisiones['trauma'])==1) and (count($this->decisiones['ucr'])==2) and (count($this->decisiones['box13'])==2) ){
$this->fechaInicio = date("Y-m-d",strtotime($this->fechaInicio." +1 day"));
$this->decisiones[$this->fechaInicio]['date'] = $this->fechaInicio;
}
}
$anterior = date("Y-m-d",strtotime($this->fechaInicio." -1 day"));
$Lista=[];
if( array_key_exists( 'trauma' ,$this->decisiones) == false ){
foreach($this->trauma as $key => $val){
if( (in_array($key, $this->decisiones[$this->fechaInicio]['ids']) == false) and (in_array($key, $this->decisiones[$anterior]['ids']) == false) ){
$decisions= $this->decisiones;
$decisions[$this->fechaInicio]['trauma'] = [$key];
$auxtra= $this->trauma;
if($auxtra[$key] -1 == 0){
unset($auxtra[$key]);
}else{
$auxtra[$key] = $auxtra[$key] -1;
}
$num = $this->numGuardiasAsig +1 ;
$decisions[$this->fechaInicio]['ids'][] = $key;
yield from bt(new Briker_vc_PS( $decisions, $this->diasTotalFinal, $this->fechaInicio, $this->box13, $this->ucr, $auxtra, $num));
}
}
}
if( (array_key_exists( 'box13' ,$this->decisiones) == false) or (count($this->decisiones['box13'])<2) ){
foreach($this->box13 as $key => $val){
if( (in_array($key, $this->decisiones[$this->fechaInicio]['ids']) == false) and (in_array($key, $this->decisiones[$anterior]['ids']) == false) ){
$decisions= $this->decisiones;
if(array_key_exists( 'box13' ,$this->decisiones) == false){
$decisions[$this->fechaInicio]['box13'] = array();
}
$decisions[$this->fechaInicio]['box13'][] = $key;
$auxbox13= $this->box13;
if($auxbox13[$key] -1 == 0){
unset($auxbox13[$key]);
}else{
$auxbox13[$key] = $auxbox13[$key] -1;
}
$num = $this->numGuardiasAsig +1 ;
$decisions[$this->fechaInicio]['ids'][] = $key;
yield from bt( new Briker_vc_PS( $decisions, $this->diasTotalFinal, $this->fechaInicio, $auxbox13, $this->ucr, $this->trauma, $num));
}
}
}
if( (array_key_exists( 'ucr' ,$this->decisiones) == false) or (count($this->decisiones['ucr'])<2) ){
foreach($this->ucr as $key => $val){
if( (in_array($key, $this->decisiones[$this->fechaInicio]['ids']) == false) and (in_array($key, $this->decisiones[$anterior]['ids']) == false) ){
$decisions= $this->decisiones;
if(array_key_exists( 'ucr' ,$this->decisiones) == false){
$decisions[$this->fechaInicio]['ucr'] = array();
}
$decisions[$this->fechaInicio]['ucr'][] = $key;
$auxucr= $this->ucr;
if($auxucr[$key] -1 == 0){
unset($auxucr[$key]);
}else{
$auxucr[$key] = $auxucr[$key] -1;
}
$decisions[$this->fechaInicio]['ids'][] = $key;
$num = $this->numGuardiasAsig +1 ;
yield from bt(new Briker_vc_PS( $decisions, $this->diasTotalFinal, $this->fechaInicio, $this->box13, $auxucr, $this->trauma, $num));
}
}
}
}
protected $GuardiasMedico;
protected $decisiones;
}
这是主程序
$month = $_REQUEST['mes'];
$year = $_REQUEST['any'];
$fecha_inicio = "01-".$month."-".$year;
// fisrt i get the number of "trauma", "ucr" and "box13" for each doctor
// And i create a array with it with key the doctor_id
$db = new SQLite3($dbname);
$result = $db->query('SELECT m.id, m.nombre, m.apellido, mgm.ucr, mgm.trauma, mgm.box13 FROM medico AS m INNER JOIN MedicoGuardiaMes AS mgm ON m.id = mgm.doctor_id WHERE m.borrado = 0 AND mgm.mes = '.$month.' AND mgm.any = '.$year);
$box13 = [];
$ucr = [];
$trauma = [];
while($res = $result->fetchArray()){
$box13[$res['id']] = $res['box13'];
$ucr[$res['id']] = $res['ucr'];
$trauma[$res['id']] = $res['trauma'];
}
// I create the solution array and add the last day from the previous month
$dataBaseDecisiones = [];
$anterior = date("Y-m-d",strtotime($fecha_inicio." -1 day"));
$dataBaseDecisiones[$anterior] = [];
$dataBaseDecisiones[$anterior]['ids'] = [];
$diasTotalFinal=cal_days_in_month(CAL_GREGORIAN, $month, $year);
// Finally I create the initial object and starts the backtracking
$initial_ps = new Briker_vc_PS($dataBaseDecisiones, $diasTotalFinal, $fecha_inicio, $box13, $ucr, $trauma, $numGuardiasAsig);
var_dump( bt($initial_ps)->getReturn() );
我不知道为什么这段代码不起作用,或者我是否以正确的方式使用 yield。
所报告的问题是由于您代码中的最后一行:
bt($initial_ps)->getReturn();
当 bt
执行 else
部分时,它执行递归搜索直到有 return
,然后它 产生 该值.但这并没有完成迭代器的结果,并且这个产生的值不被认为是迭代器的 return 值。所以 getReturn()
触发了你得到的异常。
你没有解释你打算在 var_dump
中得到什么作为输出。如果你想输出所有产生的结果,那么首先收集所有这些结果,例如 iterator_to_array
:
$iter = bt($initial_ps);
print_r(iterator_to_array($iter));
只有这样你才能执行:
print_r($iter->getReturn());